fr.ird.observe.toolkit.templates.DtoMetaTransformer Maven / Gradle / Ivy
package fr.ird.observe.toolkit.templates;
/*-
* #%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.WithAtLeastOneSelected;
import fr.ird.observe.dto.data.ContainerDto;
import fr.ird.observe.dto.data.InlineDataDto;
import fr.ird.observe.toolkit.templates.io.TagValues;
import fr.ird.observe.toolkit.templates.validation.ValidationTagValues;
import org.nuiton.eugene.AbstractMetaTransformer;
import org.nuiton.eugene.EugeneCoreTagValues;
import org.nuiton.eugene.LogProxy;
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.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelAttribute;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.eugene.models.object.ObjectModelPackage;
import org.nuiton.eugene.models.object.xml.ObjectModelAttributeImpl;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* Created on 24/01/2021.
*
* @author Tony Chemit - [email protected]
* @since 8.0.5
*/
public abstract class DtoMetaTransformer extends AbstractMetaTransformer {
@Override
protected void applyTemplates(ObjectModel model, List extends Template> templates, File destDir) throws IOException {
for (Template template : templates) {
template.setLog(getLog());
}
super.applyTemplates(model, templates, destDir);
}
@Override
protected boolean validateModel(ObjectModel model) {
String packageName = getConfiguration().getProperty(PROP_DEFAULT_PACKAGE);
ToolkitTagValues observeTagValues = new ToolkitTagValues();
ValidationTagValues validationTagValues = new ValidationTagValues();
Path outputDirectory = getConfiguration().getProperty(PROP_OUTPUT_DIRECTORY, File.class).toPath().getParent().getParent();
TagValues tagValues = new TagValues(model, "dto", getLog());
try {
tagValues.load(getClassLoader(), outputDirectory, isVerbose());
} catch (Exception e) {
throw new IllegalStateException("Can't load tag-values", e);
}
BeanTransformerContext allWithAbstract = new BeanTransformerContext(model, new EugeneCoreTagValues(), new EugeneJavaTagValues(), new BeanTransformerTagValues(), true, false, t -> true, getLog());
BeanTransformerContext all = new BeanTransformerContext(model, new EugeneCoreTagValues(), new EugeneJavaTagValues(), new BeanTransformerTagValues(), false, false, t -> true, getLog());
augmentsReferences(allWithAbstract, packageName);
augmentsTagValues(model, all, observeTagValues);
consolidateModel(model, all, observeTagValues, getLog());
augmentsTagValuesFinal(model, all, observeTagValues, validationTagValues);
return true;
}
protected void augmentsTagValues(ObjectModel model, BeanTransformerContext all, ToolkitTagValues observeTagValues) {
String defaultPackageName = getConfiguration().getProperty(PROP_DEFAULT_PACKAGE);
for (ObjectModelClass aClass : all.selectedClasses) {
ObjectModelPackage aPackage = model.getPackage(aClass.getPackageName());
String mainDtoTagValue = observeTagValues.getMainDtoTagValue(aClass);
if (observeTagValues.notSkip(mainDtoTagValue) != null) {
String newValue;
if (mainDtoTagValue.contains(".")) {
// absolute value
newValue = defaultPackageName + "." + mainDtoTagValue + "Dto";
} else {
newValue = aPackage.getName() + "." + mainDtoTagValue + "Dto";
}
getLog().debug(String.format("Augments tag value %s.mainDto=%s", aClass.getQualifiedName(), newValue));
aClass.getTagValues().put(ToolkitTagValues.Store.mainDto.name(), newValue);
}
String formTagValue = observeTagValues.getFormTagValue(aClass, aPackage);
if (observeTagValues.notSkip(formTagValue) != null && !Objects.equals("self", formTagValue)) {
String newValue;
if (formTagValue.contains(".")) {
// absolute value
newValue = defaultPackageName + "." + formTagValue + "Dto";
} else {
newValue = aPackage.getName() + "." + formTagValue + "Dto";
}
getLog().debug(String.format("Augments tag value %s.form=%s", aClass.getQualifiedName(), newValue));
aClass.getTagValues().put(ToolkitTagValues.Store.form.name(), newValue);
}
}
}
protected void augmentsReferences(BeanTransformerContext all, String packageName) {
for (ObjectModelClass aClass : all.selectedClasses) {
for (ObjectModelAttribute attribute : aClass.getAttributes()) {
String attributeType = attribute.getType();
if (!attributeType.startsWith(packageName) && attributeType.endsWith("Reference")) {
// add full package
String newValue = packageName + "." + attributeType;
getLog().debug(String.format("Augments reference attribute value %s.%s=%s", aClass.getQualifiedName(), attribute.getName(), newValue));
((ObjectModelAttributeImpl) attribute).setType(newValue);
}
}
}
}
protected void augmentsTagValuesFinal(ObjectModel model, BeanTransformerContext all, ToolkitTagValues observeTagValues, ValidationTagValues validationTagValues) {
for (ObjectModelClass aClass : all.selectedClasses) {
ObjectModelPackage aPackage = model.getPackage(aClass.getPackageName());
String atLeastOneSelectedTagValue = validationTagValues.getAtLeastOneSelected(aClass);
if (atLeastOneSelectedTagValue != null) {
boolean notFound = aClass.getInterfaces().stream().noneMatch(i -> i.getQualifiedName().equals(WithAtLeastOneSelected.class.getName()));
if (notFound) {
// add interface on class
getLog().debug(String.format("Add interface %s on %s", WithAtLeastOneSelected.class.getName(), aClass.getQualifiedName()));
aClass.getInterfaces().add(model.getInterface(WithAtLeastOneSelected.class.getName()));
}
}
String inlineDataDtoPropertiesTagValue = observeTagValues.getInlineDataDtoPropertiesTagValue(aClass);
if (inlineDataDtoPropertiesTagValue != null) {
boolean notFound = aClass.getInterfaces().stream().noneMatch(i -> i.getQualifiedName().equals(InlineDataDto.class.getName()));
if (notFound) {
// add interface on class
getLog().debug(String.format("Add interface %s on %s", InlineDataDto.class.getName(), aClass.getQualifiedName()));
aClass.getInterfaces().add(model.getInterface(InlineDataDto.class.getName()));
}
}
String formTagValue = observeTagValues.getFormTagValue(aClass, aPackage);
if (Objects.equals("self", formTagValue)) {
String newValue = aClass.getQualifiedName() + "Dto";
getLog().debug(String.format("Augments tag value %s.form=%s", aClass.getQualifiedName(), newValue));
aClass.getTagValues().put(ToolkitTagValues.Store.form.name(), newValue);
}
String mainDtoTagValue = observeTagValues.getMainDtoTagValue(aClass);
if (mainDtoTagValue == null) {
String newValue = aClass.getQualifiedName() + "Dto";
getLog().debug(String.format("Augments tag value %s.mainDto=%s", aClass.getQualifiedName(), newValue));
aClass.getTagValues().put(ToolkitTagValues.Store.mainDto.name(), newValue);
}
}
}
protected void consolidateModel(ObjectModel model, BeanTransformerContext all, ToolkitTagValues observeTagValues, LogProxy log) {
for (ObjectModelClass aClass : all.selectedClasses) {
ObjectModelPackage aPackage = model.getPackage(aClass.getPackageName());
boolean containerDto = aClass.getSuperclasses().stream().anyMatch(i -> (i.getQualifiedName() + "Dto").equals(ContainerDto.class.getName()));
if (containerDto) {
String mainDtoTagValue = observeTagValues.getMainDtoTagValue(aClass);
String formTagValue = observeTagValues.getFormTagValue(aClass, aPackage);
if (mainDtoTagValue == null && (formTagValue == null || Objects.equals("self", formTagValue))) {
log.debug(String.format("found ContainerDto without any tagValues, add convention tagValues: %s", aClass.getQualifiedName()));
ObjectModelClass childType = guessChildType(all.selectedClasses, aClass);
log.debug(String.format("add tag value %s.form=%s", aClass.getQualifiedName(), childType.getQualifiedName()) + "Dto");
ObjectModelClass mainType = guessMainType(all.selectedClasses, aClass, childType);
log.debug(String.format("add tag value %s.mainDto=%s", aClass.getQualifiedName(), mainType.getQualifiedName()) + "Dto");
aClass.getTagValues().put(ToolkitTagValues.Store.form.name(), childType.getQualifiedName() + "Dto");
aClass.getTagValues().put(ToolkitTagValues.Store.mainDto.name(), mainType.getQualifiedName() + "Dto");
}
}
}
}
private ObjectModelClass guessChildType(Set selectedClasses, ObjectModelClass aClass) {
String name = aClass.getName();
String packageName = aClass.getPackageName();
List candidates = new LinkedList<>();
for (ObjectModelClass selectedClass : selectedClasses) {
if (!Objects.equals(packageName, selectedClass.getPackageName())) {
// not in same package
continue;
}
if (name.equals(selectedClass.getName())) {
// same class
continue;
}
if (name.endsWith(selectedClass.getName())) {
if (!candidates.isEmpty()) {
ObjectModelClass objectModelClass = candidates.get(0);
if (selectedClass.getName().endsWith(objectModelClass.getName())) {
candidates.remove(0);
} else if (objectModelClass.getName().endsWith(selectedClass.getName())) {
// not keeping this one
continue;
}
}
candidates.add(selectedClass);
}
}
if (candidates.isEmpty()) {
throw new IllegalStateException("Can't guess child type for " + aClass.getQualifiedName());
}
if (candidates.size() == 1) {
// only one candidate, found it!
return candidates.get(0);
}
// should take the biggest matching candidate ?
candidates.sort(Comparator.comparing(ObjectModelClass::getQualifiedName, Comparator.comparingInt(String::length)).reversed());
return candidates.get(0);
}
private ObjectModelClass guessMainType(Set selectedClasses, ObjectModelClass aClass, ObjectModelClass childType) {
String name = aClass.getName();
String childTypeName = childType.getName();
String packageName = aClass.getPackageName();
List candidates = new LinkedList<>();
for (ObjectModelClass selectedClass : selectedClasses) {
if (!Objects.equals(packageName, selectedClass.getPackageName())) {
// not in same package
continue;
}
if (name.equals(selectedClass.getName())) {
// same class
continue;
}
if (name.equals(selectedClass.getName() + childTypeName)) {
candidates.add(selectedClass);
}
}
if (candidates.isEmpty()) {
throw new IllegalStateException("Can't guess main type for " + aClass.getQualifiedName());
}
if (candidates.size() == 1) {
// only one candidate, found it!
return candidates.get(0);
}
// should take the smallest matching candidate ?
candidates.sort(Comparator.comparing(ObjectModelClass::getQualifiedName, Comparator.comparingInt(String::length)).reversed());
return candidates.get(0);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy