
fr.ird.observe.toolkit.templates.validation.GenerateCollectionUniqueKeyValidators Maven / Gradle / Ivy
package fr.ird.observe.toolkit.templates.validation;
/*-
* #%L
* Toolkit :: Templates
* %%
* Copyright (C) 2017 - 2024 Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* .
* #L%
*/
import fr.ird.observe.dto.I18nDecoratorHelper;
import fr.ird.observe.spi.ProjectPackagesDefinition;
import fr.ird.observe.toolkit.templates.TemplateContract;
import fr.ird.observe.validation.validator.collection.AbstractCollectionUniqueKeyValidator;
import io.ultreia.java4all.bean.JavaBean;
import io.ultreia.java4all.i18n.I18n;
import io.ultreia.java4all.i18n.spi.bean.BeanPropertyI18nKeyProducer;
import io.ultreia.java4all.lang.Objects2;
import io.ultreia.java4all.lang.Strings;
import org.codehaus.plexus.component.annotations.Component;
import org.nuiton.eugene.EugeneCoreTagValues;
import org.nuiton.eugene.Template;
import org.nuiton.eugene.java.BeanTransformerContext;
import org.nuiton.eugene.java.BeanTransformerTagValues;
import org.nuiton.eugene.java.EugeneJavaTagValues;
import org.nuiton.eugene.java.JavaGeneratorUtil;
import org.nuiton.eugene.java.ObjectModelTransformerToJava;
import org.nuiton.eugene.java.extension.ObjectModelAnnotation;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelAttribute;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.eugene.models.object.ObjectModelClassifier;
import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
import org.nuiton.eugene.models.object.ObjectModelOperation;
import org.nuiton.eugene.models.object.ObjectModelPackage;
import org.nuiton.eugene.models.tagvalue.ObjectModelTagValuesStore;
import org.nuiton.topia.templates.sql.TopiaMetadataModelGeneratorSupport;
import javax.annotation.Generated;
import java.beans.Introspector;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.stream.Collectors;
/**
* To generate compile time collection unique key validators using the tagValue {@link ValidationTagValues.Store#collectionUniqueKey}.
*
* Created on 30/10/2022.
*
* @author Tony Chemit - [email protected]
* @since 9.0.17
*/
@Component(role = Template.class, hint = "fr.ird.observe.toolkit.templates.validation.GenerateCollectionUniqueKeyValidators")
public class GenerateCollectionUniqueKeyValidators extends ObjectModelTransformerToJava implements TemplateContract {
@Override
public void applyTemplate(ObjectModel model, File destDir) throws IOException {
File realTarget = TopiaMetadataModelGeneratorSupport.getNotGeneratedSourceDirector(destDir);
super.applyTemplate(model, realTarget);
}
@Override
public void addGeneratedAnnotation(ObjectModelClassifier element) {
String generatorName = getClass().getName();
ObjectModelAnnotation annotation = addAnnotation(element, element, Generated.class);
addAnnotationParameter(element, annotation, "value", generatorName);
}
@Override
public void transformFromModel(ObjectModel model) {
super.transformFromModel(model);
ProjectPackagesDefinition def = ProjectPackagesDefinition.of(getClassLoader());
ObjectModelTagValuesStore tagValuesStore = model.getTagValuesStore();
ValidationTagValues validationTagValues = new ValidationTagValues();
Map> beanUniqueKeysToProcess = new LinkedHashMap<>();
BeanTransformerContext context = new BeanTransformerContext(model, new EugeneCoreTagValues(), new EugeneJavaTagValues(), new BeanTransformerTagValues(), false, false, input -> {
Collection attributes = new LinkedList<>(input.getAttributes());
attributes.addAll(input.getAllOtherAttributes());
Map collectionUniqueKey = ValidatorTransformer.getStringProperties(input, attributes, (c, a) -> validationTagValues.getCollectionUniqueKey(tagValuesStore, c, a));
if (collectionUniqueKey.isEmpty()) {
return false;
}
beanUniqueKeysToProcess.put(input, collectionUniqueKey);
return true;
}, getLog());
context.report();
BeanPropertyI18nKeyProducer labelsBuilder = I18nDecoratorHelper.get().getDefaultLabelsBuilder();
for (Map.Entry> entry : beanUniqueKeysToProcess.entrySet()) {
ObjectModelClassifier input = entry.getKey();
ObjectModelPackage thisPackage = getPackage(input);
String dtoType = context.classesNameTranslation.get(input);
Class extends JavaBean> dtoClazz = Objects2.forName(thisPackage.getName() + "." + dtoType);
Map collectionUniqueKeysPerAttribute = entry.getValue();
for (Map.Entry attributesEntry : collectionUniqueKeysPerAttribute.entrySet()) {
String attributeName = attributesEntry.getKey();
ObjectModelAttribute attribute = input.getAttribute(attributeName);
String attributeType = attribute.getType();
if (attribute.getClassifier() != null) {
attributeType += "Dto";
}
Class extends JavaBean> attributeClazz = Objects2.forName(attributeType);
String collectionUniqueKeyI18n = labelsBuilder.getI18nPropertyKey(dtoClazz, attributeName) + ".validation.uniqueKey";
String[] collectionUniqueKeyComponents = attributesEntry.getValue().split("\\s*,\\s*");
String relativeDtoPackage = def.getRelativeDtoPackage(dtoClazz.getName()).substring(1);
String validatorType = getValidatorType(relativeDtoPackage, attributeName);
generateValidator(dtoClazz,
relativeDtoPackage,
attributeName,
attributeClazz,
collectionUniqueKeyI18n,
collectionUniqueKeyComponents,
validatorType);
}
}
}
public static String getValidatorType(String relativeDtoPackage, String attributeName) {
String validatorType = Arrays.stream(relativeDtoPackage.split("\\.")).map(Strings::capitalize).collect(Collectors.joining()) + Strings.capitalize(attributeName) + "CollectionUniqueKey";
validatorType = Strings.removeStart(validatorType, "Data");
validatorType = Strings.removeStart(validatorType, "Referential");
validatorType = Introspector.decapitalize(validatorType);
return validatorType;
}
static String dtoToValidationClassName(Class> dtoClazz, String attributeName) {
return dtoClazz.getSimpleName() + Strings.capitalize(attributeName) + "CollectionUniqueKeyValidator";
}
static String dtoToValidationPackageName(Class> dtoClazz) {
return dtoClazz.getPackageName().replace(".dto.", ".dto.validation.validator.");
}
@SuppressWarnings({"CommentedOutCode", "StringOperationCanBeSimplified"})
private void generateValidator(Class extends JavaBean> dtoClazz,
@SuppressWarnings("unused") String relativeDtoPackage,
String attributeName,
Class extends JavaBean> attributeClazz,
@SuppressWarnings("unused") String collectionUniqueKeyI18n,
String[] collectionUniqueKeyComponents,
@SuppressWarnings("unused") String vaslidatorType) {
ObjectModelClass output = createClass(dtoClazz.getSimpleName() + Strings.capitalize(attributeName) + "CollectionUniqueKeyValidator",dtoToValidationPackageName( dtoClazz));
setSuperClass(output, String.format("%s<%s, %s>", AbstractCollectionUniqueKeyValidator.class.getName(), dtoClazz.getName(), attributeClazz.getName()));
addImport(output, I18n.class);
ObjectModelOperation constructor = addConstructor(output, ObjectModelJavaModifier.PUBLIC);
String getterName = getJavaBeanMethodName(JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX, attributeName);
setOperationBody(constructor, ""+"\n"
+" super(\""+attributeName+"\", "+dtoClazz.getSimpleName()+"::"+getterName+", I18n.n(\""+collectionUniqueKeyI18n+"\"));\n"
+" ");
ObjectModelOperation computeUniqueKeyMethod = addOperation(output, "computeUniqueKey", String.class, ObjectModelJavaModifier.PROTECTED);
addParameter(computeUniqueKeyMethod, attributeClazz.getName(), "collectionValue");
addAnnotation(output, computeUniqueKeyMethod, Override.class);
StringBuilder computeUniqueKeyMethodContent = new StringBuilder(""+"\n"
+" StringBuilder builder = new StringBuilder();");
for (String collectionUniqueKeyComponent : collectionUniqueKeyComponents) {
@SuppressWarnings("unused") String getter = getJavaBeanMethodName("get", collectionUniqueKeyComponent);
computeUniqueKeyMethodContent.append(""+"\n"
+" addComponentValue(builder, collectionValue."+getter+"());");
}
computeUniqueKeyMethodContent.append(""+"\n"
+" return builder.substring(1);\n"
+" ");
setOperationBody(computeUniqueKeyMethod, computeUniqueKeyMethodContent.toString());
output.getQualifiedName();
}
}