fr.ird.observe.toolkit.templates.navigation.MetaModelBuilderFromModel Maven / Gradle / Ivy
package fr.ird.observe.toolkit.templates.navigation;
/*-
* #%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 com.google.common.collect.ArrayListMultimap;
import fr.ird.observe.spi.ProjectPackagesDefinition;
import fr.ird.observe.spi.navigation.model.MetaModel;
import fr.ird.observe.spi.navigation.model.MetaModelBuilder;
import fr.ird.observe.spi.navigation.model.MetaModelNodeLinkMultiplicity;
import fr.ird.observe.spi.navigation.model.MetaModelNodeType;
import fr.ird.observe.spi.navigation.parent.ParentLink;
import fr.ird.observe.toolkit.templates.ToolkitTagValues;
import io.ultreia.java4all.lang.Strings;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.LogProxy;
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.ObjectModelPackage;
import org.nuiton.topia.templates.TopiaExtensionTagValues;
import org.nuiton.topia.templates.TopiaTemplateHelper;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Created on 30/12/2021.
*
* @author Tony Chemit - [email protected]
* @since 5.0.64
*/
public class MetaModelBuilderFromModel extends MetaModelBuilder {
private final LogProxy log;
private final ObjectModel model;
private final ToolkitTagValues observeTagValues;
private final TopiaExtensionTagValues topiaExtensionTagValues;
private final List entityClassesWithNode;
private final LinkedList entityClassesOpen;
private final ProjectPackagesDefinition def;
private final List entityClasses;
private final List entityClassesNames;
private final Set parentLinks = new LinkedHashSet<>();
private final ArrayListMultimap referentialClasses;
private final LinkedList entityClassesEntryPoints;
MetaModelBuilderFromModel(LogProxy log, ObjectModel model, ProjectPackagesDefinition def) {
this.log = log;
this.model = model;
TopiaTemplateHelper templateHelper = new TopiaTemplateHelper(model);
this.observeTagValues = new ToolkitTagValues();
this.topiaExtensionTagValues = new TopiaExtensionTagValues();
this.entityClasses = templateHelper.getEntityClasses(model, false);
this.entityClassesNames = entityClasses.stream().map(ObjectModelClass::getQualifiedName).collect(Collectors.toList());
this.entityClassesWithNode = entityClasses.stream().filter(entityClass -> observeTagValues.getNavigationNodeTypeTagValue(entityClass, null) != null).map(ObjectModelClass::getQualifiedName).collect(Collectors.toCollection(LinkedList::new));
this.referentialClasses = ArrayListMultimap.create();
for (ObjectModelClass referentialClass : entityClasses.stream().filter(entityClass -> entityClass.getPackageName().contains("referential.")).collect(Collectors.toList())) {
this.referentialClasses.put(referentialClass.getPackageName(), referentialClass);
}
this.entityClassesOpen = entityClasses.stream().filter(entityClass -> Objects.equals(observeTagValues.getNavigationNodeTypeTagValue(entityClass, null), "Open")).map(ObjectModelClass::getQualifiedName).collect(Collectors.toCollection(LinkedList::new));
this.entityClassesEntryPoints = entityClasses.stream().filter(topiaExtensionTagValues::isEntryPoint).map(ObjectModelClass::getQualifiedName).collect(Collectors.toCollection(LinkedList::new));
this.def = def;
}
public MetaModel build() {
entityClassesEntryPoints.stream().map(model::getClass).forEach(input -> addEntryPoint(toNavigationNode(input), MetaModelNodeType.RootOpen, () -> scan(input)));
referentialClasses.keySet().stream().sorted().forEach(referentialPackageName -> addEntryPoint(toNavigationPackage(referentialPackageName), MetaModelNodeType.ReferentialPackage, () -> {
List types = referentialClasses.get(referentialPackageName);
for (ObjectModelClass type : types) {
String simpleName = toNavigationNodeName(type.getName());
addChildren(simpleName, MetaModelNodeType.ReferentialType, toNavigationNode(type), MetaModelNodeLinkMultiplicity.ONE, null);
}
}));
return super.build();
}
public List getParentLinks() {
return new ArrayList<>(parentLinks);
}
private void scan(ObjectModelClass input) {
String[] groupByList = topiaExtensionTagValues.getGroupBy(input);
if (groupByList != null) {
addGroupBy(input, groupByList);
}
ObjectModelPackage clazzPackage = model.getPackage(input);
String navigationNodeExtraTypeTagValue = observeTagValues.getNavigationNodeExtraTypeTagValue(input);
if (navigationNodeExtraTypeTagValue != null) {
for (String typeStr : navigationNodeExtraTypeTagValue.split("\\s*,\\s*")) {
log.info(String.format("[%-70s] Add extra type %s.", input.getQualifiedName(), typeStr));
String simpleName = GeneratorUtil.getSimpleName(typeStr);
String packageName = typeStr.substring(0, typeStr.length() - simpleName.length() - 1);
String dtoSimpleName = toNavigationNodeName(simpleName);
String nodeDataType = toNavigationNode(packageName, simpleName);
addChildren(dtoSimpleName, MetaModelNodeType.Simple, nodeDataType, MetaModelNodeLinkMultiplicity.ONE, null);
}
}
List attributes = input.getAttributes().stream().filter(
a -> a.isNavigable()
&& entityClassesNames.contains(a.getType())
&& !topiaExtensionTagValues.isSkipModelNavigation(clazzPackage, input, a)
).collect(Collectors.toCollection(LinkedList::new));
for (ObjectModelAttribute attribute : attributes) {
String attributeType = attribute.getType();
ObjectModelClass dependency = model.getClass(attributeType);
if (def.isReferentialFromEntityPackageName(dependency.getPackageName())) {
continue;
}
String navigationNodeTypeTagValue = Objects.requireNonNull(observeTagValues.getNavigationNodeTypeTagValue(dependency, attribute));
MetaModelNodeLinkMultiplicity entityMultiplicity;
MetaModelNodeLinkMultiplicity multiplicity;
MetaModelNodeType nodeType = MetaModelNodeType.valueOf(navigationNodeTypeTagValue);
switch (nodeType) {
case Open:
multiplicity = MetaModelNodeLinkMultiplicity.MANY;
entityMultiplicity = MetaModelNodeLinkMultiplicity.MANY;
break;
case Edit:
multiplicity = GeneratorUtil.isNMultiplicity(attribute) ? MetaModelNodeLinkMultiplicity.MANY : MetaModelNodeLinkMultiplicity.OPTIONAL;
entityMultiplicity = GeneratorUtil.isNMultiplicity(attribute) ? MetaModelNodeLinkMultiplicity.MANY : MetaModelNodeLinkMultiplicity.OPTIONAL;
break;
default:
multiplicity = MetaModelNodeLinkMultiplicity.ONE;
entityMultiplicity = GeneratorUtil.isNMultiplicity(attribute) ? MetaModelNodeLinkMultiplicity.MANY : MetaModelNodeLinkMultiplicity.OPTIONAL;
}
ParentLink parentLink = new ParentLink(attribute.getName(), toNavigationNode(dependency), toNavigationNode(input), entityMultiplicity);
if (!entityClassesWithNode.contains(attribute.getType())) {
// no navigation
parentLinks.add(parentLink);
scanDependencies(dependency);
continue;
}
if (MetaModelNodeType.Simple.name().equals(navigationNodeTypeTagValue)) {
parentLinks.add(parentLink);
scanDependencies(dependency);
continue;
}
String nodeDataType = toNavigationNode(dependency);
String linkName = attribute.getName();
if (entityClassesOpen.contains(dependency.getQualifiedName()) && MetaModelNodeType.Edit.name().equals(navigationNodeTypeTagValue)) {
// special case: use a open data as a edit one
// must declare a new type
log.info(String.format("Found a special Open → Edit node on %s.%s", input.getName(), linkName));
String packageName = dependency.getPackageName();
String simpleName = input.getName() + Strings.capitalize(dependency.getName());
nodeDataType = toNavigationNode(packageName, simpleName);
parentLink = new ParentLink(linkName, nodeDataType, toNavigationNode(input), multiplicity);
}
parentLinks.add(parentLink);
addChildren(linkName, nodeType, nodeDataType, multiplicity, () -> scan(dependency));
}
}
private void scanDependencies(ObjectModelClass input) {
ObjectModelPackage clazzPackage = model.getPackage(input);
List attributes = input.getAttributes().stream().filter(
a -> a.isNavigable()
&& entityClassesNames.contains(a.getType())
&& !topiaExtensionTagValues.isSkipModelNavigation(clazzPackage, input, a)
).collect(Collectors.toCollection(LinkedList::new));
for (ObjectModelAttribute attribute : attributes) {
String attributeType = attribute.getType();
ObjectModelClass dependency = model.getClass(attributeType);
if (def.isReferentialFromEntityPackageName(dependency.getPackageName())) {
continue;
}
MetaModelNodeLinkMultiplicity entityMultiplicity = GeneratorUtil.isNMultiplicity(attribute) ? MetaModelNodeLinkMultiplicity.MANY : MetaModelNodeLinkMultiplicity.OPTIONAL;
ParentLink parentLink = new ParentLink(attribute.getName(), toNavigationNode(dependency), toNavigationNode(input), entityMultiplicity);
parentLinks.add(parentLink);
scanDependencies(dependency);
}
}
void addGroupBy(ObjectModelClass input, String[] groupByList) {
for (String groupByPattern : groupByList) {
String groupBy = groupByPattern;
String groupBySecond = null;
int index = groupByPattern.indexOf(":");
if (index > -1) {
groupBy = groupByPattern.substring(0, index);
} else {
index = groupByPattern.indexOf(".");
if (index > -1) {
groupBy = groupByPattern.substring(0, index);
groupBySecond = groupByPattern.substring(index + 1);
}
}
ObjectModelAttribute parentAttribute = Objects.requireNonNull(input.getAttribute(groupBy));
ObjectModelClassifier classifier = parentAttribute.getClassifier();
if (classifier instanceof ObjectModelClass && entityClasses.contains(classifier)) {
if (groupBySecond == null) {
addGroupBy(groupBy, toNavigationNode(classifier));
} else {
ObjectModelAttribute secondClassifier = classifier.getAttribute(groupBySecond);
String capitalize = Strings.capitalize(groupBySecond);
addGroupBy(groupBy + capitalize, toNavigationNode(secondClassifier.getClassifier()));
}
} else {
addGroupBy(groupBy, parentAttribute.getType());
}
}
}
private String toNavigationPackage(String packageName) {
String result = def.getRelativeEntityPackage(packageName);
result = def.getRelativeDtoPackage(result);
return result.startsWith(".") ? result.substring(1) : result;
}
private String toNavigationNode(String packageName, String name) {
return toNavigationPackage(packageName) + "." + toNavigationNodeName(name);
}
private String toNavigationNode(ObjectModelClassifier clazz) {
return toNavigationPackage(clazz.getPackageName()) + "." + toNavigationNodeName(clazz.getName());
}
private String toNavigationNodeName(String prefix) {
return Strings.capitalize(prefix.replace("Dto", ""));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy