fr.ird.observe.toolkit.templates.entity.ToolkitEntityHibernateMappingTransformer Maven / Gradle / Ivy
package fr.ird.observe.toolkit.templates.entity;
/*-
* #%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.toolkit.templates.ToolkitTagValues;
import fr.ird.observe.toolkit.templates.entity.query.SqlQueryDefinition;
import org.codehaus.plexus.component.annotations.Component;
import org.nuiton.eugene.Template;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelAttribute;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataAssociation;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataEntity;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataEntityPath;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataLink;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataModel;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataModelPaths;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataOneToOneComposition;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataReverseAssociation;
import org.nuiton.topia.templates.EntityHibernateMappingTransformer;
import org.nuiton.topia.templates.hibernate.HibernateClassContext;
import org.nuiton.topia.templates.sql.TopiaMetadataEntityPathsBuilder;
import org.nuiton.topia.templates.sql.TopiaMetadataModelBuilder;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Created on 27/04/2021.
*
* @author Tony Chemit - [email protected]
* @since 5.0.19
*/
@Component(role = Template.class, hint = "fr.ird.observe.toolkit.templates.entity.ToolkitEntityHibernateMappingTransformer")
public class ToolkitEntityHibernateMappingTransformer extends EntityHibernateMappingTransformer {
private final ToolkitTagValues toolkitTagValues = new ToolkitTagValues();
private TopiaMetadataModel metadataModel;
private TopiaMetadataModelPaths allPaths;
private GroupBySqlHelper groupBySqlHelper;
public static String getReferenceQuery(TopiaMetadataEntity table, String referencesTagValue) {
List realReferences = new LinkedList<>();
realReferences.add("topiaId");
realReferences.add("topiaCreateDate");
realReferences.add("topiaVersion");
realReferences.addAll(List.of(referencesTagValue.split("\\s*,\\s*")));
return String.format("SELECT %1$s FROM %2$s.%3$s main",
realReferences.stream().map(s -> "main." + s).collect(Collectors.joining(", ")),
table.getDbSchemaName(),
table.getDbTableName());
}
@Override
public void generateFromModel(Writer output, ObjectModel input) throws IOException {
metadataModel = TopiaMetadataModelBuilder.buildFull(isVerbose(), input, getTemplateHelper());
allPaths = TopiaMetadataEntityPathsBuilder.create(metadataModel);
groupBySqlHelper = new GroupBySqlHelper(topiaHibernateTagValues, metadataModel, model, getTemplateHelper(), this);
super.generateFromModel(output, input);
}
@Override
protected void generateSqlQueries(Writer output, HibernateClassContext classContext) throws IOException {
ObjectModelClass input = classContext.getInput();
Set userQueries = getTemplateHelper().queriesForType(input.getQualifiedName(),classContext.getMetadataEntity().getDbSchemaName(),classContext.getMetadataEntity().getDbTableName());
addUserQueries(output, userQueries);
addEntityToIdsProjection(output, input);
addEntityToIdEqualsProjection(output, input);
addEntityToIdInProjection(output, input);
addEntityToIdBeforeProjection(output, input);
addEntityToIdAfterProjection(output, input);
TopiaMetadataEntity entity = metadataModel.getEntity(getTemplateHelper().getEntityEnumLiteralName(input));
String inputClassName = entity.getFullyQualifiedName();
if (inputClassName.contains(".referential.")) {
return;
}
String referencesTagValue = toolkitTagValues.getReferencesTagValue(input);
if (referencesTagValue != null) {
addReferenceQuery(output, input.getQualifiedName(), entity, referencesTagValue);
}
String[] navigationParentTagValues = topiaExtensionTagValues.getGroupBy(input);
if (navigationParentTagValues != null) {
for (String groupByPattern : navigationParentTagValues) {
if (isVerbose()) {
getLog().info(String.format("Add entry point parent query on %s::%s", inputClassName, groupByPattern));
}
String groupBy = groupByPattern;
String groupByPredicate = null;
String groupBySecond = null;
int index = groupByPattern.indexOf(":");
if (index > -1) {
groupBy = groupByPattern.substring(0, index);
groupByPredicate = groupByPattern.substring(index + 1);
} else {
index = groupByPattern.indexOf(".");
if (index > -1) {
groupBy = groupByPattern.substring(0, index);
groupBySecond = groupByPattern.substring(index + 1);
}
}
ObjectModelAttribute attribute = input.getAttribute(groupBy);
groupBySqlHelper.addRootGetMultipleParentEntity(output,
classContext.getPackage(),
input,
inputClassName,
entity,
Objects.requireNonNull(attribute),
groupBy,
groupBy,
groupByPredicate,
groupBySecond);
}
return;
}
if (!allPaths.containsKey(entity)) {
return;
}
List paths = new ArrayList<>(allPaths.getEntityPath(entity));
if (paths.size() == 2) {
int match = 0;
for (TopiaMetadataEntityPath path : paths) {
TopiaMetadataLink lastLink = path.getLastLink();
if (lastLink instanceof TopiaMetadataAssociation) {
match++;
}
}
if (match == 2) {
// no need two paths
paths.remove(1);
} else {
for (TopiaMetadataEntityPath path : paths) {
registerParentQuery(output, input, entity, path);
}
return;
}
}
if (paths.size() == 1) {
for (TopiaMetadataEntityPath path : paths) {
int linksSize = path.getLinksSize();
if (linksSize == 0) {
continue;
}
registerParentQuery(output, input, entity, path);
}
} else {
throw new IllegalStateException("Can't manage three paths to data for " + input.getQualifiedName());
}
}
private void addUserQueries(Writer output, Set userQueries) throws IOException {
for (SqlQueryDefinition userQuery : userQueries) {
String queryName = userQuery.getFullyQualifiedName();
String query = userQuery.getQuery();
String extraParameters = " read-only=\"true\"";
if (userQuery.isCallable()) {
extraParameters += " callable=\"true\"";
}
boolean added = addSqlQuery(output, queryName, query, extraParameters, userQuery.getComment(), userQuery.withParameters() ? userQuery.getParameters() : null);
if (!added) {
throw new IllegalStateException(String.format("Can't add query: %s", queryName));
}
}
}
private void registerParentQuery(Writer output, ObjectModelClass input, TopiaMetadataEntity entity, TopiaMetadataEntityPath path) throws IOException {
TopiaMetadataLink lastLink = path.getLastLink();
String property = lastLink.getTargetPropertyName();
TopiaMetadataEntity owner = lastLink.getOwner();
String key = owner.getFullyQualifiedName() + "-" + lastLink.getTargetPropertyName();
if (lastLink instanceof TopiaMetadataReverseAssociation) {
if (isVerbose()) {
getLog().info(String.format("Add single parent query on %s", lastLink));
}
addGetSingleParentEntity(output, input.getQualifiedName(), key, lastLink.getOwner(), property);
} else if (lastLink instanceof TopiaMetadataOneToOneComposition) {
if (isVerbose()) {
getLog().info(String.format("Add single parent query on %s", lastLink));
}
addGetMultipleParentEntity(output, input.getQualifiedName(), key, entity, owner, ((TopiaMetadataOneToOneComposition) lastLink).getSourceDbName());
} else {
if (isVerbose()) {
getLog().info(String.format("Add multiple parent query on %s", lastLink));
}
addGetMultipleParentEntity(output, input.getQualifiedName(), key, entity, owner, owner.getDbTableName());
}
}
private void addReferenceQuery(Writer output, String input, TopiaMetadataEntity table, String referencesTagValue) throws IOException {
String queryName = input + "::reference";
String query = getReferenceQuery(table, referencesTagValue);
boolean added = addSqlQuery(output, queryName, query, " read-only=\"true\"");
if (!added) {
throw new IllegalStateException(String.format("Can't add query: %s", queryName));
}
}
private void addGetMultipleParentEntity(Writer output, String input, String key, TopiaMetadataEntity table, TopiaMetadataEntity parentTable, String property) throws IOException {
{
String query = String.format("select p.topiaId, p.lastUpdateDate from %s.%s p inner join %s.%s e on e.%s = p.topiaId where e.topiaId = ?", parentTable.getDbSchemaName(), parentTable.getDbTableName(), table.getDbSchemaName(), table.getDbTableName(), property);
String queryName = String.format("%s::getParentId::%s", input, key);
boolean added = addSqlQuery(output, queryName, query, " read-only=\"true\"");
if (!added) {
throw new IllegalStateException(String.format("Can't add query: %s", queryName));
}
}
{
String query = String.format("select distinct(e.topiaId) from %s.%s e where e.%s in ( ?1 )", table.getDbSchemaName(), table.getDbTableName(), property);
String queryName = String.format("%s::byParentId::%s", input, key);
boolean added = addSqlQuery(output, queryName, query, " read-only=\"true\"");
if (!added) {
throw new IllegalStateException(String.format("Can't add query: %s", queryName));
}
}
}
private void addGetSingleParentEntity(Writer output, String input, String key, TopiaMetadataEntity table, String property) throws IOException {
{
String query = String.format("select p.topiaId, p.lastUpdateDate from %s.%s as p where p.%s = ?", table.getDbSchemaName(), table.getDbTableName(), property);
String queryName = String.format("%s::getParentId::%s", input, key);
boolean added = addSqlQuery(output, queryName, query, " read-only=\"true\"");
if (!added) {
throw new IllegalStateException(String.format("Can't add query: %s", queryName));
}
}
{
String query = String.format("select distinct(e.%3$s) from %1$s.%2$s e where e.topiaId in ( ?1 )", table.getDbSchemaName(), table.getDbTableName(), property);
String queryName = String.format("%s::byParentId::%s", input, key);
boolean added = addSqlQuery(output, queryName, query, " read-only=\"true\"");
if (!added) {
throw new IllegalStateException(String.format("Can't add query: %s", queryName));
}
}
}
private void addEntityToIdsProjection(Writer output, ObjectModelClass input) throws IOException {
String query = String.format("select new fr.ird.observe.dto.ToolkitIdBean(id, lastUpdateDate)\n" +
" from %s as e", input.getQualifiedName() + "Impl");
addQuery(output, input.getQualifiedName() + "::id::all", query, " read-only=\"true\"");
}
private void addEntityToIdEqualsProjection(Writer output, ObjectModelClass input) throws IOException {
String query = String.format("select new fr.ird.observe.dto.ToolkitIdBean(id, lastUpdateDate)\n" +
" from %s as e\n" +
" where e.id = ?1", input.getQualifiedName() + "Impl");
addQuery(output, input.getQualifiedName() + "::id::equals", query, " read-only=\"true\"");
}
private void addEntityToIdInProjection(Writer output, ObjectModelClass input) throws IOException {
String query = String.format("select new fr.ird.observe.dto.ToolkitIdBean(id, lastUpdateDate)\n" +
" from %s as e\n" +
" where e.id in ( ?1 )", input.getQualifiedName() + "Impl");
addQuery(output, input.getQualifiedName() + "::id::in", query, " read-only=\"true\"");
}
private void addEntityToIdBeforeProjection(Writer output, ObjectModelClass input) throws IOException {
String query = String.format("select new fr.ird.observe.dto.ToolkitIdBean(id, lastUpdateDate)\n" +
" from %s as e\n" +
" where e.lastUpdateDate <= ?1", input.getQualifiedName() + "Impl");
addQuery(output, input.getQualifiedName() + "::id::before", query, " read-only=\"true\"");
}
private void addEntityToIdAfterProjection(Writer output, ObjectModelClass input) throws IOException {
String query = String.format("select new fr.ird.observe.dto.ToolkitIdBean(id, lastUpdateDate)\n" +
" from %s as e\n" +
" where e.lastUpdateDate > ?1", input.getQualifiedName() + "Impl");
addQuery(output, input.getQualifiedName() + "::id::after", query, " read-only=\"true\"");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy