Skip to content

Commit

Permalink
Added service and validator
Browse files Browse the repository at this point in the history
+ integration test
  • Loading branch information
cgendreau committed Dec 23, 2024
1 parent c95f5ce commit e9a2534
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
import ca.gc.aafc.dina.vocabulary.VocabularyElement;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;

@SuperBuilder
@Getter
public class IdentifierType implements VocabularyElement {
public abstract class IdentifierType implements VocabularyElement, DinaEntity {

/**
* The key should not contain dot(.) See {@link VocabularyElement#getKey()}
*/
@Setter
private String key;

private String name;
Expand All @@ -26,8 +30,4 @@ public class IdentifierType implements VocabularyElement {
*/
private String uriTemplate;

public void setKey(String key) {

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package ca.gc.aafc.dina.service;

import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.SmartValidator;

import ca.gc.aafc.dina.entity.IdentifierType;
import ca.gc.aafc.dina.jpa.BaseDAO;
import ca.gc.aafc.dina.validation.IdentifierTypeValidator;
import ca.gc.aafc.dina.vocabulary.VocabularyKeyHelper;

import lombok.NonNull;

/**
* Service to handle {@link IdentifierType}
* @param <T>
*/
public class IdentifierTypeService<T extends IdentifierType> extends DefaultDinaService<T> {

private final IdentifierTypeValidator identifierTypeValidator;

public IdentifierTypeService(@NonNull BaseDAO baseDAO,
@NonNull SmartValidator validator,
IdentifierTypeValidator identifierTypeValidator) {
super(baseDAO, validator);
this.identifierTypeValidator = identifierTypeValidator;
}

@Override
protected void preCreate(T entity) {
if (StringUtils.isNotBlank(entity.getName())) {
entity.setKey(VocabularyKeyHelper.generateKeyFromName(entity.getName()));
}
}

@Override
public void validateBusinessRules(T identifierType) {
applyBusinessRule(identifierType, identifierTypeValidator);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,20 @@
import ca.gc.aafc.dina.entity.ManagedAttribute;
import ca.gc.aafc.dina.jpa.BaseDAO;
import ca.gc.aafc.dina.jpa.PredicateHelper;
import ca.gc.aafc.dina.vocabulary.VocabularyKeyHelper;

import lombok.NonNull;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.validation.SmartValidator;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
Expand All @@ -29,7 +27,6 @@
public abstract class ManagedAttributeService<T extends ManagedAttribute>
extends DefaultDinaService<T> {
private static final String KEY = "key";
private static final Pattern NON_ALPHANUMERICAL = Pattern.compile("[^a-z0-9]");
private final Class<T> maClass;

public ManagedAttributeService(BaseDAO baseDAO, SmartValidator smartValidator, @NonNull Class<T> managedAttributeClass) {
Expand All @@ -40,7 +37,7 @@ public ManagedAttributeService(BaseDAO baseDAO, SmartValidator smartValidator, @
@Override
protected void preCreate(T entity) {
if (StringUtils.isNotBlank(entity.getName())) {
entity.setKey(generateKeyFromName(entity.getName()));
entity.setKey(VocabularyKeyHelper.generateKeyFromName(entity.getName()));
}
}

Expand Down Expand Up @@ -86,26 +83,4 @@ public T findOneByKeyAnd(String key, Pair<String, Object> andClause) {
return findOneByProperties(maClass,
List.of(Pair.of(KEY, key), andClause));
}

/**
* Transforms a name into a key. camelCase is supported.
* "Aa bb !! mySuperAttribute # 11" will become aa_bb_my_super_attribute_11
* @param name
* @return
*/
private static String generateKeyFromName(String name) {
Objects.requireNonNull(name);

return Arrays.stream(StringUtils.
splitByCharacterTypeCamelCase(StringUtils.normalizeSpace(name)))
.filter(StringUtils::isNotBlank)
.map(ManagedAttributeService::processName)
.filter(StringUtils::isNotBlank)
.collect(Collectors.joining("_"));
}

private static String processName(String name) {
return RegExUtils.removeAll(name.toLowerCase(), NON_ALPHANUMERICAL);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ca.gc.aafc.dina.validation;

import javax.inject.Named;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.MessageSource;
import org.springframework.validation.Errors;

import ca.gc.aafc.dina.entity.IdentifierType;

public class IdentifierTypeValidator extends DinaBaseValidator<IdentifierType> {

private static final String MISSING_PLACEHOLDER_KEY = "identifierType.uriTemplate.missingPlaceholder";

public IdentifierTypeValidator(@Named("validationMessageSource") MessageSource messageSource) {
super(IdentifierType.class, messageSource);
}

@Override
public void validateTarget(IdentifierType target, Errors errors) {

if(StringUtils.isNotBlank(target.getUriTemplate())) {
if(!target.getUriTemplate().contains("$1")) {
errors.reject(MISSING_PLACEHOLDER_KEY, getMessage(MISSING_PLACEHOLDER_KEY));
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package ca.gc.aafc.dina.vocabulary;

import java.util.Arrays;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;

/**
* Utility class to have uniform handling of key generation from a name.
*/
public final class VocabularyKeyHelper {

private static final Pattern NON_ALPHANUMERICAL = Pattern.compile("[^a-z0-9]");

private VocabularyKeyHelper() {
// utility class
}

/**
* Transforms a name into a key. camelCase is supported.
* "Aa bb !! mySuperAttribute # 11" will become aa_bb_my_super_attribute_11
* @param name
* @return
*/
public static String generateKeyFromName(String name) {
Objects.requireNonNull(name);

return Arrays.stream(StringUtils.
splitByCharacterTypeCamelCase(StringUtils.normalizeSpace(name)))
.filter(StringUtils::isNotBlank)
.map(VocabularyKeyHelper::processName)
.filter(StringUtils::isNotBlank)
.collect(Collectors.joining("_"));
}

private static String processName(String name) {
return RegExUtils.removeAll(name.toLowerCase(), NON_ALPHANUMERICAL);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ location.nullWellCol=Well column cannot be null when well row is set.
location.nullWellRow=Well row cannot be null when well column is set.
location.invalidWellColumn=Invalid well column: {0}
location.invalidWellRow=Invalid well row: {0}

identifierType.uriTemplate.missingPlaceholder=Missing identifier placeholder $1
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package ca.gc.aafc.dina.service;

import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.validation.SmartValidator;

import ca.gc.aafc.dina.TestDinaBaseApp;
import ca.gc.aafc.dina.entity.IdentifierType;
import ca.gc.aafc.dina.jpa.BaseDAO;
import ca.gc.aafc.dina.testsupport.PostgresTestContainerInitializer;
import ca.gc.aafc.dina.validation.IdentifierTypeValidator;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.time.OffsetDateTime;
import java.util.UUID;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.transaction.Transactional;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;

@SpringBootTest(classes = {TestDinaBaseApp.class, IdentifierTypeServiceIT.IdentifierTypeServiceConfig.class})
@ContextConfiguration(initializers = { PostgresTestContainerInitializer.class })
public class IdentifierTypeServiceIT {

@Inject
private IdentifierTypeService<IdentifierType> identifierTypeService;

@Test
@Transactional
public void identifierTypeService_OnCreate_KeyCorrectlyGenerated() {

IdentifierType identifierType = identifierTypeService
.create(TestIdentifierType.builder()
.id(11)
.uuid(UUID.randomUUID())
.uriTemplate("https://abc.abc/$1")
.name("dina specialIdentifier #11").build());

assertEquals("dina_special_identifier_11", identifierType.getKey());
}

@TestConfiguration
@EntityScan(basePackageClasses = TestIdentifierType.class)
static class IdentifierTypeServiceConfig {

@Bean
public IdentifierTypeService<IdentifierType> identifierTypeService(BaseDAO baseDAO,
SmartValidator sv,
IdentifierTypeValidator iv) {
return new IdentifierTypeService<>(baseDAO, sv, iv) {
};
}

@Bean
public IdentifierTypeValidator identifierTypeValidator(@Named("validationMessageSource")
MessageSource messageSource) {
return new IdentifierTypeValidator(messageSource);
}
}

@Getter
@Setter
@SuperBuilder
@Entity
static class TestIdentifierType extends IdentifierType {

@Id
private Integer id;
private UUID uuid;
private String createdBy;
private OffsetDateTime createdOn;
}

}

0 comments on commit e9a2534

Please sign in to comment.