Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.breedinginsight.brapps.importer.model.imports;

import org.breedinginsight.dao.db.enums.TermType;
import java.util.Map;
import java.util.Optional;

public class TermTypeTranslator {

private static final Map<String, TermType> userDisplayToTermTypeMap = Map.of(
"Phenotype", TermType.PHENOTYPE,
"Germplasm Attribute", TermType.GERM_ATTRIBUTE,
"Germplasm Passport", TermType.GERM_PASSPORT);

public static Optional<TermType> getTermTypeFromUserDisplayName(String userDisplayName) {
return Optional.ofNullable(userDisplayToTermTypeMap.get(userDisplayName));
}
}
2 changes: 2 additions & 0 deletions src/main/java/org/breedinginsight/model/Trait.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public Trait(TraitEntity traitEntity) {
this.setUpdatedAt(traitEntity.getUpdatedAt());
this.setUpdatedBy(traitEntity.getUpdatedBy());
this.setActive(traitEntity.getActive());
this.setTermType(traitEntity.getTermType());
}

public static Trait parseSqlRecord(Record record) {
Expand All @@ -106,6 +107,7 @@ public static Trait parseSqlRecord(Record record) {
.updatedAt(record.getValue(TRAIT.UPDATED_AT))
.updatedBy(record.getValue(TRAIT.UPDATED_BY))
.active(record.getValue(TRAIT.ACTIVE))
.termType(record.getValue(TRAIT.TERM_TYPE))
.build();
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/breedinginsight/services/TraitService.java
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ public List<Trait> createTraits(UUID programId, List<Trait> traits, Authenticate
.createdBy(actingUser.getId())
.updatedBy(actingUser.getId())
.active(true)
.termType(trait.getTermType())
.build();
traitDAO.insert(jooqTrait);
trait.setId(jooqTrait.getId());
Expand Down Expand Up @@ -416,6 +417,7 @@ public List<Trait> updateTraits(UUID programId, List<Trait> traits, Authenticate
existingTraitEntity.setObservationVariableName(updatedTrait.getObservationVariableName());
existingTraitEntity.setProgramObservationLevelId(updatedTrait.getProgramObservationLevel().getId());
existingTraitEntity.setUpdatedBy(user.getId());
existingTraitEntity.setTermType(updatedTrait.getTermType());
traitDAO.update(existingTraitEntity);

// Update in brapi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public enum ParsingExceptionType {
INVALID_SCALE_DECIMAL_PLACES("Invalid scale decimal places value"),
INVALID_SCALE_LOWER_LIMIT("Invalid scale lower limit value. Value must be numeric and be a whole number."),
INVALID_SCALE_UPPER_LIMIT("Invalid scale upper limit value. Value must be numeric and be a whole number."),
INVALID_SCALE_CATEGORIES("Invalid scale categories format");
INVALID_SCALE_CATEGORIES("Invalid scale categories format"),
INVALID_TERM_TYPE("Invalid term type");

private String value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ public enum TraitFileColumns {
SCALE_UPPER_LIMIT("Scale upper limit"),
SCALE_CATEGORIES("Scale categories"),
TAGS("Tags"),
FULL_NAME("Full name");
FULL_NAME("Full name"),
TERM_TYPE("Term Type");


private String value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@
*/
package org.breedinginsight.services.parsers.trait;

import io.micronaut.core.util.StringUtils;
import io.micronaut.http.HttpStatus;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.text.WordUtils;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.ss.usermodel.*;
import org.brapi.v2.model.pheno.BrAPIScaleValidValuesCategories;
import org.breedinginsight.api.model.v1.response.ValidationError;
import org.breedinginsight.api.model.v1.response.ValidationErrors;
import org.breedinginsight.brapps.importer.model.imports.TermTypeTranslator;
import org.breedinginsight.dao.db.enums.DataType;
import org.breedinginsight.dao.db.enums.TermType;
import org.breedinginsight.model.*;
import org.breedinginsight.services.exceptions.UnprocessableEntityException;
import org.breedinginsight.services.exceptions.ValidatorException;
Expand Down Expand Up @@ -250,6 +252,21 @@ private List<Trait> excelRecordsToTraits(List<ExcelRecord> records) throws Valid
String tagsString = parseExcelValueAsString(record, TraitFileColumns.TAGS);
List<String> traitTags = parseListValue(tagsString);

//Set to backend value for user input term type, if none, set to default
TermType termType = TermType.PHENOTYPE;

String termTypeVal = parseExcelValueAsString(record, TraitFileColumns.TERM_TYPE);
if ((!Objects.isNull(termTypeVal)) && (!termTypeVal.isBlank())) {
Optional<TermType> termTypeOpt = TermTypeTranslator.getTermTypeFromUserDisplayName(WordUtils.capitalizeFully(termTypeVal));
if (termTypeOpt.isPresent()) {
termType = termTypeOpt.get();
} else {
ValidationError error = new ValidationError(TraitFileColumns.TERM_TYPE.toString(),
ParsingExceptionType.INVALID_TERM_TYPE.toString(), HttpStatus.UNPROCESSABLE_ENTITY);
validationErrors.addError(traitValidatorError.getRowNumber(i), error);
}
}

Trait trait = Trait.builder()
.observationVariableName(parseExcelValueAsString(record, TraitFileColumns.NAME))
.traitDescription(parseExcelValueAsString(record, TraitFileColumns.DESCRIPTION))
Expand All @@ -263,6 +280,7 @@ private List<Trait> excelRecordsToTraits(List<ExcelRecord> records) throws Valid
.method(method)
.scale(scale)
.tags(traitTags)
.termType(termType)
.build();

traits.add(trait);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ public TraitQueryMapper() {
Map.entry("updatedByUserId",
trait -> trait.getUpdatedByUser() != null ? trait.getUpdatedByUser().getId() : null),
Map.entry("updatedByUserName",
trait -> trait.getUpdatedByUser() != null ? trait.getUpdatedByUser().getName() : null)
trait -> trait.getUpdatedByUser() != null ? trait.getUpdatedByUser().getName() : null),
Map.entry("termType", Trait::getTermType)
);
}

Expand Down
25 changes: 25 additions & 0 deletions src/main/resources/db/migration/V1.0.10__add_onto_term_type.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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.
*/

CREATE TYPE "term_type" AS ENUM (
'PHENOTYPE',
'GERM_ATTRIBUTE',
'GERM_PASSPORT'
);

ALTER TABLE trait ADD COLUMN term_type term_type NOT NULL DEFAULT 'PHENOTYPE';
UPDATE trait SET term_type='PHENOTYPE';
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.breedinginsight.api.model.v1.request.query.SearchRequest;
import org.breedinginsight.api.v1.controller.metadata.SortOrder;
import org.breedinginsight.dao.db.enums.DataType;
import org.breedinginsight.dao.db.enums.TermType;
import org.breedinginsight.dao.db.tables.daos.ProgramDao;
import org.breedinginsight.dao.db.tables.pojos.BiUserEntity;
import org.breedinginsight.dao.db.tables.pojos.ProgramEntity;
Expand Down Expand Up @@ -570,6 +571,8 @@ private void checkValidTraitUpload(JsonObject traitUpload) {
assertEquals("Leaf", observationLevel.get("name").getAsString(), "wrong level name");

assertEquals(true, trait.get("active").getAsBoolean(), "wrong status");
assertEquals(TermType.GERM_PASSPORT.toString(), trait.get("termType").getAsString());

// TODO: trait lists

JsonObject method = trait.get("method").getAsJsonObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.breedinginsight.api.model.v1.response.ValidationError;
import org.breedinginsight.api.model.v1.response.ValidationErrors;
import org.breedinginsight.dao.db.enums.DataType;
import org.breedinginsight.dao.db.enums.TermType;
import org.breedinginsight.model.Method;
import org.breedinginsight.model.Scale;
import org.breedinginsight.model.Trait;
Expand Down Expand Up @@ -182,6 +183,7 @@ void parseCsvConvertToTraitsError() {
expectedErrors3.put(TraitFileColumns.SCALE_DECIMAL_PLACES.toString(), ParsingExceptionType.INVALID_SCALE_DECIMAL_PLACES);
expectedErrors3.put(TraitFileColumns.SCALE_LOWER_LIMIT.toString(), ParsingExceptionType.INVALID_SCALE_LOWER_LIMIT);
expectedErrors3.put(TraitFileColumns.SCALE_UPPER_LIMIT.toString(), ParsingExceptionType.INVALID_SCALE_UPPER_LIMIT);
expectedErrors3.put(TraitFileColumns.TERM_TYPE.toString(), ParsingExceptionType.INVALID_TERM_TYPE);

checkParsingExceptionErrors(rowErrors.getRowErrors().get(0), expectedErrors1);
checkParsingExceptionErrors(rowErrors.getRowErrors().get(1), expectedErrors2);
Expand Down Expand Up @@ -286,6 +288,7 @@ private void assertTestTraitEquals(Trait trait) {
assertEquals("leaf", trait.getEntity(), "wrong entity");
assertEquals("powdery mildew severity", trait.getAttribute(), "wrong attribute");
assertEquals(true, trait.getActive(), "wrong status");
assertEquals(TermType.GERM_PASSPORT, trait.getTermType(), "wrong term type");
// TODO: trait lists
Method method = trait.getMethod();
assertEquals("Powdery Mildew severity, leaf", method.getDescription(), "wrong method description");
Expand Down
2 changes: 1 addition & 1 deletion src/test/resources/files/columns_no_data.csv
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Name,Synonyms,Description,Trait entity,Trait attribute,Status,Tags,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,Scale upper limit,Scale categories,Full Name
Name,Synonyms,Description,Trait entity,Trait attribute,Status,Tags,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,Scale upper limit,Scale categories,Full Name,Term Type
4 changes: 2 additions & 2 deletions src/test/resources/files/data_duplicate_headers.csv
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Name,ONTOLOgY TErM NaME,Trait Abbreviations,trAit synoNyms,trait Description,Trait entity,Trait attribute,Status,Trait lists,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,ScALe Upper limit,Scale CAtegories,Full Name
PM_Leaf,Powdery Mildew; Powdery Mildew Severity,"Powdery mildew (PM) due to Erysiphe necator severity in field, leaves only ",Plant,active,mildew,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation",Observed severity of Powdery Mildew on leaves,Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,2,2,9999,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,
Name,ONTOLOgY TErM NaME,Trait Abbreviations,trAit synoNyms,trait Description,Trait entity,Trait attribute,Status,Trait lists,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,ScALe Upper limit,Scale CAtegories,Full Name,Term Type
PM_Leaf,Powdery Mildew; Powdery Mildew Severity,"Powdery mildew (PM) due to Erysiphe necator severity in field, leaves only ",Plant,active,mildew,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation",Observed severity of Powdery Mildew on leaves,Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,2,2,9999,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,,
4 changes: 2 additions & 2 deletions src/test/resources/files/data_duplicate_method_name.csv
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Name,Synonyms,Description,Trait entity,Trait attribute,Status,Trait lists,Method name,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,Scale upper limit,Scale categories,Full Name
PM_Leaf,Powdery Mildew; Powdery Mildew Severity,"Powdery mildew (PM) due to Erysiphe necator severity in field, leaves only ",leaf,powdery mildew severity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation ",blah,"Powdery Mildew severity, leaf",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,2,2,9999,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",
Name,Synonyms,Description,Trait entity,Trait attribute,Status,Trait lists,Method name,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,Scale upper limit,Scale categories,Full Name,Term Type
PM_Leaf,Powdery Mildew; Powdery Mildew Severity,"Powdery mildew (PM) due to Erysiphe necator severity in field, leaves only ",leaf,powdery mildew severity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation ",blah,"Powdery Mildew severity, leaf",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,2,2,9999,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,
4 changes: 2 additions & 2 deletions src/test/resources/files/data_min_max_swap.csv
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Name,Synonyms,Description,Trait entity,Trait attribute,Status,Trait lists,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,Scale upper limit,Scale categories,Tags,Full Name
PM_Leaf,Powdery Mildew; Powdery Mildew Severity,"Powdery mildew (PM) due to Erysiphe necator severity in field, leaves only ",leaf,powdery mildew severity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation","Powdery Mildew severity, leaf",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,2,9999,2.11,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,
Name,Synonyms,Description,Trait entity,Trait attribute,Status,Trait lists,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,Scale upper limit,Scale categories,Tags,Full Name,Term Type
PM_Leaf,Powdery Mildew; Powdery Mildew Severity,"Powdery mildew (PM) due to Erysiphe necator severity in field, leaves only ",leaf,powdery mildew severity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation","Powdery Mildew severity, leaf",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,2,9999,2.11,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,,
4 changes: 2 additions & 2 deletions src/test/resources/files/data_mismatched_cases.csv
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
name,synoNyms,deScription,Trait entity,Trait attribute,StaTus,Trait lists,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,ScALe Upper limit,Scale CAtegories,Tags,Full Name
PM_Leaf,Powdery Mildew; Powdery Mildew Severity,"Powdery mildew (PM) due to Erysiphe necator severity in field, leaves only ",leaf,powdery mildew severity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation","Powdery Mildew severity, leaf",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,2,2,9999,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,
name,synoNyms,deScription,Trait entity,Trait attribute,StaTus,Trait lists,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,ScALe Upper limit,Scale CAtegories,Tags,Full Name,Term Type
PM_Leaf,Powdery Mildew; Powdery Mildew Severity,"Powdery mildew (PM) due to Erysiphe necator severity in field, leaves only ",leaf,powdery mildew severity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation","Powdery Mildew severity, leaf",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,2,2,9999,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,,Germplasm PASSPORT
8 changes: 4 additions & 4 deletions src/test/resources/files/data_multiple_rows.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Name,Synonyms,Description,Trait entity,Trait attribute,Status,Trait lists,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,Scale upper limit,Scale categories,Tags,Full Name
PM_leaf,Powdery Mildew Leaf; Powdery Mildew Severity Leaf,"Powdery mildew (PM) due to Erysiphe necator severity in field, leaves only ",leaf,powdery mildew deverity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation ","Powdery Mildew severity, leaf",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,,,,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,Powdery Mildew Severity Leaf
PM_bud,Powdery Mildew Bud; Powdery Mildew Severity Bud,"Powdery mildew (PM) due to Erysiphe necator severity in field, bud only ",bud,powdery mildew deverity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation ","Powdery Mildew severity, bud",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,,,,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,Powdery Mildew Severity Bud
PM_stem,Powdery Mildew Stem; Powdery Mildew Severity Stem,"Powdery mildew (PM) due to Erysiphe necator severity in field, stem only ",stem,powdery mildew deverity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation ","Powdery Mildew severity, stem",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,,,,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,Powdery Mildew Severity Stem
Name,Synonyms,Description,Trait entity,Trait attribute,Status,Trait lists,Method name,Method description,Method class,Method formula,Units,Scale class,Scale decimal places,Scale lower limit,Scale upper limit,Scale categories,Tags,Full Name,Term Type
PM_leaf,Powdery Mildew Leaf; Powdery Mildew Severity Leaf,"Powdery mildew (PM) due to Erysiphe necator severity in field, leaves only ",leaf,powdery mildew deverity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation ","Powdery Mildew severity, leaf",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,,,,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,Powdery Mildew Severity Leaf,Germplasm Attribute
PM_bud,Powdery Mildew Bud; Powdery Mildew Severity Bud,"Powdery mildew (PM) due to Erysiphe necator severity in field, bud only ",bud,powdery mildew deverity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation ","Powdery Mildew severity, bud",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,,,,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,Powdery Mildew Severity Bud,
PM_stem,Powdery Mildew Stem; Powdery Mildew Severity Stem,"Powdery mildew (PM) due to Erysiphe necator severity in field, stem only ",stem,powdery mildew deverity,active,Nursery evaluation; Greenhouse evaluation; Trial evaluation,"Powdery Mildew severity, leaves - Estimation ","Powdery Mildew severity, stem",Estimation,a^2 + b^2 = c^2,1-4 Parlier field response score,Ordinal,,,,"1=No visible infection; 2=Very few, small colonies; 3=< 50% coverage; 4=>50% coverage",,Powdery Mildew Severity Stem,phenotype
Binary file modified src/test/resources/files/data_multiple_rows.xls
Binary file not shown.
Binary file modified src/test/resources/files/data_multiple_rows.xlsx
Binary file not shown.
Loading