Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
fr.ird.observe.toolkit.templates.dto.DtoTransformer Maven / Gradle / Ivy
package fr.ird.observe.toolkit.templates.dto;
/*-
* #%L
* ObServe Toolkit :: Templates
* %%
* Copyright (C) 2017 - 2020 IRD, 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 com.google.common.collect.ImmutableMap;
import fr.ird.observe.dto.DtoToReference;
import fr.ird.observe.dto.IdDto;
import fr.ird.observe.dto.form.FormDefinition;
import fr.ird.observe.dto.referential.ReferentialLocale;
import fr.ird.observe.spi.ProjectPackagesDefinition;
import fr.ird.observe.spi.mapping.DtoToFormDtoMapping;
import fr.ird.observe.spi.mapping.DtoToMainDtoClassMapping;
import fr.ird.observe.toolkit.templates.ObserveTagValues;
import fr.ird.observe.toolkit.templates.TemplateContract;
import io.ultreia.java4all.classmapping.ImmutableClassMapping;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.plexus.component.annotations.Component;
import org.nuiton.eugene.EugeneCoreTagValues;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.Template;
import org.nuiton.eugene.java.BeanTransformer;
import org.nuiton.eugene.java.BeanTransformerContext;
import org.nuiton.eugene.java.BeanTransformerTagValues;
import org.nuiton.eugene.java.EugeneJavaTagValues;
import org.nuiton.eugene.java.JavaBuilder;
import org.nuiton.eugene.java.JavaGeneratorUtil;
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.ObjectModelElement;
import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
import org.nuiton.eugene.models.object.ObjectModelModifier;
import org.nuiton.eugene.models.object.ObjectModelOperation;
import org.nuiton.eugene.models.object.ObjectModelPackage;
import org.nuiton.eugene.models.object.ObjectModelParameter;
import org.nuiton.eugene.models.object.xml.ObjectModelAttributeImpl;
import org.nuiton.eugene.models.object.xml.ObjectModelClassifierImpl;
import org.nuiton.eugene.models.object.xml.ObjectModelOperationImpl;
import org.nuiton.eugene.models.object.xml.ObjectModelParameterImpl;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import static fr.ird.observe.toolkit.templates.TemplateContract.isReferentialFromPackageName;
/**
* @author Tony Chemit - [email protected]
* @since ?
*/
@Component(role = Template.class, hint = "fr.ird.observe.toolkit.templates.dto.DtoTransformer")
public class DtoTransformer extends BeanTransformer implements TemplateContract {
private final EugeneCoreTagValues coreTagValues;
private final EugeneJavaTagValues javaTemplatesTagValues;
private final BeanTransformerTagValues beanTagValues;
private final ObserveTagValues observeTagValues;
private BeanTransformerContext context;
private final Map dtoFormMapping = new TreeMap<>();
private final Map dtoMainMapping = new TreeMap<>();
public DtoTransformer() {
coreTagValues = new EugeneCoreTagValues();
javaTemplatesTagValues = new EugeneJavaTagValues();
beanTagValues = new BeanTransformerTagValues();
observeTagValues = new ObserveTagValues();
}
@Override
public void transformFromModel(ObjectModel model) {
super.transformFromModel(model);
context = new BeanTransformerContext(model, coreTagValues, javaTemplatesTagValues, beanTagValues, false, false, input -> {
ObjectModelPackage aPackage = model.getPackage(input.getPackageName());
boolean referential = isReferentialFromPackageName(aPackage.getName());
String referencesTagValue = observeTagValues.getReferencesTagValue(input);
return referencesTagValue != null || referential;
}, getLog());
context.report();
}
@Override
protected void debugOutputModel() {
super.debugOutputModel();
generateClassMapping(true, model.getName() + " dto → form dto mapping", DtoToFormDtoMapping.class, "Class extends " + IdDto.class.getName() + ">", FormDefinition.class.getName() + ">", ImmutableMap.class, "build", dtoFormMapping);
generateClassMapping(true, model.getName() + " dto → main dto class mapping", DtoToMainDtoClassMapping.class, IdDto.class.getName(), IdDto.class.getName(), ImmutableClassMapping.class, "getMappingBuilder", dtoMainMapping);
}
@Override
protected ObjectModelClass generateGeneratedClass(ObjectModelPackage aPackage, ObjectModelClass input, String className, String mainClassName) {
ObjectModelClass output = super.generateGeneratedClass(aPackage, input, className, mainClassName);
boolean referential = TemplateContract.isReferentialFromPackageName(aPackage.getName());
if (context.selectedClasses.contains(input)) {
String referencesTagValue = observeTagValues.getReferencesTagValue(input);
if (referencesTagValue == null && referential) {
referencesTagValue = "code,label,uri";
}
Objects.requireNonNull(referencesTagValue);
Set availableProperties = new LinkedHashSet<>(Arrays.asList(referencesTagValue.split(",")));
Map binderProperties = DtoReferenceTransformer.getReferenceProperties(context.selectedClassesFqn, input, availableProperties, this::getAttributeType);
String dtoName = context.classesNameTranslation.get(input);
String referenceName = ProjectPackagesDefinition.cleanType(dtoName) + "Reference";
addInterface(output, String.format("%s<%s, %s>", DtoToReference.class.getName(), mainClassName, referenceName));
addToReferenceMethod(output, binderProperties, referenceName);
}
if (!input.isAbstract()) {
addFormDefinitionAttribute(input, output, referential);
addMainDtoMapping(input, referential);
}
return output;
}
private void addMainDtoMapping(ObjectModelClass input, boolean referential) {
String mainDtoTagValue = observeTagValues.getMainDtoTagValue(input);
if (Objects.equals("skip", mainDtoTagValue)) {
return;
}
String dtoType = input.getPackageName() + "." + context.classesNameTranslation.get(input);
String mainDtoType;
if (mainDtoTagValue == null) {
// this is a main dto
mainDtoType = dtoType;
} else {
mainDtoType = getDefaultPackageName() + "." + mainDtoTagValue;
ObjectModelClass mainDtoClass = context.classesByFqn.get(mainDtoType);
mainDtoType = mainDtoClass.getPackageName() + "." + context.classesNameTranslation.get(mainDtoClass);
}
dtoMainMapping.put(dtoType, mainDtoType + ".class");
}
private void addFormDefinitionAttribute(ObjectModelClass input, ObjectModelClass output, boolean referential) {
ObjectModelPackage thisPackage = getPackage(input);
String formTagValue = observeTagValues.getFormTagValue(input, thisPackage);
getLog().debug("FormTagValue: " + formTagValue);
ObjectModelPackage defaultPackage = getModel().getPackage(getDefaultPackageName());
String packageName = defaultPackage.getName() + ".";
String formType;
String dtoType = thisPackage.getName() + "." + context.classesNameTranslation.get(input);
String dtoTypeSimpleName = GeneratorUtil.getSimpleName(thisPackage.getName() + "." + context.classesNameTranslation.get(input));
boolean addForm = false;
Map properties;
if (formTagValue != null && formTagValue.equals("self")) {
formType = dtoType;
properties = getFormProperties(input, output);
getLog().debug(String.format("form: %s, found %d properties.", formType, properties.size()));
addForm = referential || !properties.isEmpty();
if (addForm) {
StringBuilder bodyBuilder = new StringBuilder();
bodyBuilder.append(""+"\n"
+" new FormDefinition.Builder<>("+dtoTypeSimpleName+".class)");
for (Map.Entry entry : properties.entrySet()) {
String propertyName = entry.getKey();
String referenceType = entry.getValue();
propertyName = JavaGeneratorUtil.convertVariableNameToConstantName("property" + JavaGeneratorUtil.capitalizeJavaBeanPropertyName(propertyName));
bodyBuilder.append(""+"\n"
+" .addProperty("+propertyName+", "+referenceType+".DEFINITION)");
}
bodyBuilder.append(""+"\n"
+" .build()");
addImport(output, formType);
addAttribute(output, "FORM_DEFINITION", "FormDefinition<" + GeneratorUtil.getSimpleName(formType) + ">", bodyBuilder.toString(), ObjectModelJavaModifier.STATIC, ObjectModelJavaModifier.FINAL, ObjectModelJavaModifier.PUBLIC);
}
} else {
ObjectModelClass aClass = getModel().getClass(packageName + formTagValue);
formType = aClass.getPackageName() + "." + context.classesNameTranslation.get(aClass);
// addImport(output, formType);
addForm = true;
}
if (addForm) {
addImport(output, FormDefinition.class);
dtoFormMapping.put(dtoType, formType + ".FORM_DEFINITION");
}
}
private void addToReferenceMethod(ObjectModelClass output, Map properties, String referenceName) {
boolean useRelativeName = context.useRelativeName;
ObjectModelOperation operation = addOperation(output, "toReference", referenceName, ObjectModelJavaModifier.PUBLIC);
addAnnotation(output, operation, Override.class);
addParameter(operation, ReferentialLocale.class, "referentialLocale");
int prefixLength = (" return new " + referenceName + "(").length();
String prefix = StringUtils.leftPad("", prefixLength, " ");
StringBuilder body = new StringBuilder(""+"\n"
+" return new "+referenceName+"(this,");
Iterator> iterator = properties.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = iterator.next();
ObjectModelAttribute attr = entry.getKey();
ObjectModelAttribute dtoAttr = entry.getValue();
String content = "";
if (dtoAttr != null) {
String getterName;
String type = useRelativeName ? dtoAttr.getType() : JavaGeneratorUtil.getSimpleName(dtoAttr.getType());
String dtoAttrname = dtoAttr.getName();
boolean booleanProperty = JavaGeneratorUtil.isBooleanPrimitive(dtoAttr);
if (booleanProperty) {
getterName = JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX;
} else {
getterName = JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX;
}
getterName += JavaGeneratorUtil.capitalizeJavaBeanPropertyName(dtoAttrname);
content = getterName + "()";
if (context.selectedClassesFqn.contains(ProjectPackagesDefinition.cleanType(dtoAttr.getType()))) {
// Dto
if (!type.endsWith("Reference")) {
// not a ref, get a ref
type = ProjectPackagesDefinition.cleanType(type) + "Reference";
}
if (attr.getName().equals(dtoAttrname + "Id")) {
addImport(output, Optional.class);
addImport(output, IdDto.class);
content = String.format("Optional.ofNullable(%s).map(%s::getId).orElse(null)", content, type);
} else if (attr.getName().equals(dtoAttrname + "Label")) {
addImport(output, Optional.class);
addImport(output, IdDto.class);
String method = "getLabel";
if (type.equals("SpeciesReference")) {
method = "getScientificLabel";
}
content = String.format("Optional.ofNullable(%s).map(%s::%s).orElse(null)", content, type, method);
} else if (attr.getName().equals(dtoAttrname + "Code")) {
addImport(output, Optional.class);
addImport(output, IdDto.class);
content = String.format("Optional.ofNullable(%s).map(%s::getCode).orElse(null)", content, type);
}
}
} else {
if (attr.getName().equals("label")) {
content = "getLabel(referentialLocale)";
} else {
content = "null";
}
}
content = prefix + content;
String coma = iterator.hasNext() ? "," : "";
body.append(""+"\n"
+""+content+""+coma+""
);
}
body.append(""+");\n"
+" ");
setOperationBody(operation, body.toString());
}
@Override
protected ObjectModel initOutputModel() {
//FIXME Override builder to avoid bad imports when using synonyms in model...
builder = new JavaBuilder(getModel().getName()){
@Override
public ObjectModelOperation addOperation(ObjectModelClassifier classifier, String name, String type, ObjectModelModifier... modifiers) {
ObjectModelOperationImpl result = new ObjectModelOperationImpl();
result.setName(name);
if (type != null) {
ObjectModelParameterImpl returnParameter =
new ObjectModelParameterImpl();
returnParameter.setType(type);
result.setReturnParameter(returnParameter);
}
result.addModifier(modifiers);
((ObjectModelClassifierImpl) classifier).addOperation(result);
return result;
}
@Override
public ObjectModelParameter addParameter(ObjectModelOperation operation, String type, String name) {
ObjectModelOperationImpl impl = (ObjectModelOperationImpl) operation;
ObjectModelParameterImpl param = new ObjectModelParameterImpl();
param.setType(type);
param.setName(name);
impl.addParameter(param);
return param;
}
@Override
public ObjectModelAttribute addAttribute(ObjectModelClassifier classifier, String name, String type, String value, ObjectModelModifier... modifiers) {
ObjectModelAttributeImpl attribute = new ObjectModelAttributeImpl();
attribute.setName(name);
attribute.setType(type);
attribute.setDefaultValue(value);
attribute.addModifier(modifiers);
ObjectModelClassifierImpl classifierImpl = (ObjectModelClassifierImpl) classifier;
classifierImpl.addAttribute(attribute);
return attribute;
}
};
setConstantPrefix("");
return builder.getModel();
}
private Map getFormProperties(ObjectModelClass input, ObjectModelClass output) {
Collection attributes = new LinkedList<>(input.getAttributes());
attributes.addAll(input.getAllOtherAttributes());
Map properties = new TreeMap<>();
for (ObjectModelAttribute attr : attributes) {
if (!attr.isNavigable()) {
continue;
}
String type = attr.getType();
if (!type.endsWith("Reference") || !type.contains("referential")) {
continue;
}
// if (true) {
// properties.put(attr.getName(), type);
// } else {
addImport(output, type);
properties.put(attr.getName(), JavaGeneratorUtil.getSimpleName(type));
// }
}
return properties;
}
@Override
public ObjectModelClass createClass(String className, String packageName) {
return super.createClass(className, packageName);
}
@Override
public void addImport(ObjectModelClass output, Class> type) {
super.addImport(output, type);
}
@Override
public void addImport(ObjectModelClass output, String type) {
super.addImport(output, type);
}
@Override
public void setSuperClass(ObjectModelClass output, Class> superClass) {
super.setSuperClass(output, superClass);
}
@Override
public ObjectModelAnnotation addAnnotation(ObjectModelClass output, ObjectModelElement output1, Class> annotationType) {
return super.addAnnotation(output, output1, annotationType);
}
@Override
public void addAnnotationParameter(ObjectModelClass output, ObjectModelAnnotation annotation, String name, String value) {
super.addAnnotationParameter(output, annotation, name, value);
}
@Override
public ObjectModelOperation addConstructor(ObjectModelClass output, ObjectModelJavaModifier modifiers) {
return super.addConstructor(output, modifiers);
}
@Override
public void setOperationBody(ObjectModelOperation constructor, String body) {
super.setOperationBody(constructor, body);
}
@Override
public ObjectModelParameter addParameter(ObjectModelOperation operation, Class> type, String name) {
return super.addParameter(operation, type, name);
}
}