-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #251 from AAFC-BICoE/35302_add_managed_attribute_u…
…sage_on_generic_molecular_analysis 35302 Add managed attribute usage on generic molecular analysis
- Loading branch information
Showing
11 changed files
with
299 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
src/main/java/ca/gc/aafc/seqdb/api/util/ManagedAttributeIdMapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package ca.gc.aafc.seqdb.api.util; | ||
|
||
import io.crnk.core.engine.parser.StringMapper; | ||
import java.util.UUID; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
/** | ||
* Lets you use either the UUID or the component type + key as the ID. | ||
* e.g. /managed-attribute/generic_molecular_analysis.attribute_name. | ||
*/ | ||
@RequiredArgsConstructor | ||
public class ManagedAttributeIdMapper implements StringMapper<Object> { | ||
private final StringMapper<Object> stringMapper; | ||
|
||
@Override | ||
public Object parse(String input) { | ||
// If the input's not in UUID format then use the raw string as the ID: | ||
try { | ||
UUID.fromString(input); | ||
} catch (IllegalArgumentException e) { | ||
return input; | ||
} | ||
return stringMapper.parse(input); | ||
} | ||
|
||
@Override | ||
public String toString(Object input) { | ||
return stringMapper.toString(input); | ||
} | ||
|
||
} |
110 changes: 110 additions & 0 deletions
110
src/main/java/ca/gc/aafc/seqdb/api/validation/SequenceManagedAttributeValueValidator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package ca.gc.aafc.seqdb.api.validation; | ||
|
||
import org.apache.commons.lang3.tuple.Pair; | ||
import org.springframework.context.MessageSource; | ||
import org.springframework.context.i18n.LocaleContextHolder; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.validation.Errors; | ||
|
||
import ca.gc.aafc.dina.entity.DinaEntity; | ||
import ca.gc.aafc.dina.service.ManagedAttributeService; | ||
import ca.gc.aafc.dina.validation.ManagedAttributeValueValidator; | ||
import ca.gc.aafc.dina.validation.ValidationContext; | ||
import ca.gc.aafc.seqdb.api.entities.SequenceManagedAttribute; | ||
|
||
import java.util.EnumMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
import javax.inject.Named; | ||
import lombok.NonNull; | ||
|
||
@Component | ||
public class SequenceManagedAttributeValueValidator extends ManagedAttributeValueValidator<SequenceManagedAttribute> { | ||
|
||
private static final String INVALID_VALIDATION_CONTEXT_KEY = "managedAttribute.validation.context.invalid"; | ||
private static final String COMPONENT_FIELD_NAME = "managedAttributeComponent"; | ||
|
||
private final ManagedAttributeService<SequenceManagedAttribute> dinaService; | ||
private final MessageSource messageSource; | ||
|
||
public SequenceManagedAttributeValueValidator( | ||
@Named("validationMessageSource") MessageSource baseMessageSource, // from dina-base | ||
@NonNull MessageSource messageSource, | ||
@NonNull ManagedAttributeService<SequenceManagedAttribute> dinaService) { | ||
super(baseMessageSource, dinaService); | ||
this.dinaService = dinaService; | ||
this.messageSource = messageSource; | ||
} | ||
|
||
public <D extends DinaEntity> void validate(D entity, Map<String, String> managedAttributes, SequenceManagedAttributeValidationContext context) { | ||
super.validate(entity, managedAttributes, context); | ||
} | ||
|
||
/** | ||
* override base class version to also add a restriction on the component since the uniqueness | ||
* for CollectionManagedAttribute is key + component. | ||
* @param keys | ||
* @param validationContext | ||
* @return | ||
*/ | ||
@Override | ||
protected Map<String, SequenceManagedAttribute> findAttributesForValidation(Set<String> keys, ValidationContext validationContext) { | ||
return dinaService.findAttributesForKeys(keys, Pair.of(COMPONENT_FIELD_NAME, validationContext.getValue())); | ||
} | ||
|
||
@Override | ||
protected boolean preValidateValue(SequenceManagedAttribute managedAttributeDefinition, | ||
String value, Errors errors, ValidationContext validationContext) { | ||
|
||
// expected context based on the component | ||
SequenceManagedAttributeValidationContext expectedContext = | ||
SequenceManagedAttributeValidationContext.from(managedAttributeDefinition.getManagedAttributeComponent()); | ||
|
||
if (!expectedContext.equals(validationContext)) { | ||
errors.reject(INVALID_VALIDATION_CONTEXT_KEY, getMessageForKey(INVALID_VALIDATION_CONTEXT_KEY, | ||
Objects.toString(validationContext), expectedContext.toString())); | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
/** | ||
* Wrapper class to expose {@link ca.gc.aafc.seqdb.api.entities.SequenceManagedAttribute.ManagedAttributeComponent} as | ||
* {@link ValidationContext}. | ||
*/ | ||
public static final class SequenceManagedAttributeValidationContext implements ValidationContext { | ||
// make sure to only keep 1 instance per enum value | ||
private static final EnumMap<SequenceManagedAttribute.ManagedAttributeComponent, SequenceManagedAttributeValidationContext> | ||
INSTANCES = new EnumMap<>(SequenceManagedAttribute.ManagedAttributeComponent.class); | ||
|
||
private final SequenceManagedAttribute.ManagedAttributeComponent managedAttributeComponent; | ||
|
||
/** | ||
* Use {@link #from(SequenceManagedAttribute.ManagedAttributeComponent)} method | ||
* @param managedAttributeComponent | ||
*/ | ||
private SequenceManagedAttributeValidationContext(SequenceManagedAttribute.ManagedAttributeComponent managedAttributeComponent) { | ||
this.managedAttributeComponent = managedAttributeComponent; | ||
} | ||
|
||
public static SequenceManagedAttributeValidationContext from(SequenceManagedAttribute.ManagedAttributeComponent managedAttributeComponent) { | ||
return INSTANCES.computeIfAbsent(managedAttributeComponent, SequenceManagedAttributeValidationContext::new); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return managedAttributeComponent.toString(); | ||
} | ||
|
||
@Override | ||
public Object getValue() { | ||
return managedAttributeComponent; | ||
} | ||
} | ||
|
||
// to be replaced by dina-base whne 0.132 will be released | ||
private String getMessageForKey(String key, Object... objects) { | ||
return messageSource.getMessage(key, objects, LocaleContextHolder.getLocale()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
...main/resources/db/changelog/migrations/56-Add_managed_attribute_to_molecular_analysis.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?xml version="1.1" encoding="UTF-8" standalone="no"?> | ||
<databaseChangeLog | ||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://local.xsd/dbchangelog-4.4.xsd" | ||
objectQuotingStrategy="QUOTE_ONLY_RESERVED_WORDS"> | ||
|
||
<changeSet id="56-Add_managed_attribute_to_molecular_analysis" context="schema-change" author="cgendreau"> | ||
<addColumn tableName="generic_molecular_analysis"> | ||
<column name="managed_attributes" type="jsonb" defaultValue="{}" /> | ||
</addColumn> | ||
</changeSet> | ||
</databaseChangeLog> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
src/test/java/ca/gc/aafc/seqdb/api/service/GenericMolecularAnalysisServiceIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package ca.gc.aafc.seqdb.api.service; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import ca.gc.aafc.dina.vocabulary.TypedVocabularyElement; | ||
import ca.gc.aafc.seqdb.api.SequenceModuleBaseIT; | ||
import ca.gc.aafc.seqdb.api.entities.GenericMolecularAnalysis; | ||
import ca.gc.aafc.seqdb.api.entities.SequenceManagedAttribute; | ||
import ca.gc.aafc.seqdb.api.testsupport.factories.GenericMolecularAnalysisFactory; | ||
import ca.gc.aafc.seqdb.api.testsupport.factories.SequenceManagedAttributeFactory; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
import java.util.Map; | ||
import javax.validation.ValidationException; | ||
|
||
public class GenericMolecularAnalysisServiceIT extends SequenceModuleBaseIT { | ||
|
||
private static final String GROUP = "grp"; | ||
|
||
@Test | ||
void assignedValueContainedInAcceptedValues_validationPasses() { | ||
SequenceManagedAttribute testManagedAttribute = SequenceManagedAttributeFactory.newManagedAttribute() | ||
.acceptedValues(new String[]{"val1", "val2"}) | ||
.managedAttributeComponent(SequenceManagedAttribute.ManagedAttributeComponent.GENERIC_MOLECULAR_ANALYSIS) | ||
.build(); | ||
|
||
managedAttributeService.create(testManagedAttribute); | ||
|
||
GenericMolecularAnalysis genericMolecularAnalysis = GenericMolecularAnalysisFactory | ||
.newGenericMolecularAnalysis() | ||
.managedAttributes(Map.of(testManagedAttribute.getKey(), testManagedAttribute.getAcceptedValues()[0])) | ||
.build(); | ||
|
||
assertDoesNotThrow(() -> genericMolecularAnalysisService.create(genericMolecularAnalysis)); | ||
} | ||
|
||
@Test | ||
void validate_WhenInvalidIntegerType_ExceptionThrown() { | ||
SequenceManagedAttribute testManagedAttribute = | ||
SequenceManagedAttributeFactory.newManagedAttribute() | ||
.createdBy("GenericMolecularAnalysisServiceIT") | ||
.managedAttributeComponent( | ||
SequenceManagedAttribute.ManagedAttributeComponent.GENERIC_MOLECULAR_ANALYSIS) | ||
.group(GROUP) | ||
.vocabularyElementType(TypedVocabularyElement.VocabularyElementType.INTEGER) | ||
.acceptedValues(null) | ||
.build(); | ||
|
||
managedAttributeService.create(testManagedAttribute); | ||
|
||
GenericMolecularAnalysis genericMolecularAnalysis = GenericMolecularAnalysisFactory | ||
.newGenericMolecularAnalysis() | ||
.managedAttributes(Map.of(testManagedAttribute.getKey(), "1.2")) | ||
.build(); | ||
|
||
assertThrows(ValidationException.class, | ||
() -> genericMolecularAnalysisService.create(genericMolecularAnalysis)); | ||
} | ||
} |
Oops, something went wrong.