fr.ird.observe.toolkit.templates.entity.ToolkitEntityScriptModelGenerator 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 com.google.gson.Gson;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.eugene.models.object.ObjectModelType;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.service.sql.internal.TopiaEntitySqlModelResourceImpl;
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.TopiaMetadataReverseAssociation;
import org.nuiton.topia.service.sql.script.DeleteReferentialScript;
import org.nuiton.topia.service.sql.script.DisableReferentialScript;
import org.nuiton.topia.service.sql.script.ReplaceReferentialInDataScript;
import org.nuiton.topia.service.sql.script.ReplaceReferentialInReferentialScript;
import org.nuiton.topia.service.sql.script.TopiaEntitySqlScript;
import org.nuiton.topia.service.sql.script.TopiaEntitySqlScriptModel;
import org.nuiton.topia.service.sql.script.UpdateLastUpdateDateFieldScript;
import org.nuiton.topia.service.sql.script.UpdateLastUpdateDateTableScript;
import org.nuiton.topia.templates.TopiaTemplateHelper;
import org.nuiton.topia.templates.sql.TopiaMetadataModelBuilder;
import org.nuiton.topia.templates.sql.TopiaMetadataModelGeneratorSupport;
import java.io.File;
import java.io.Writer;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
/**
* Created on 13/09/2020.
*
* @author Tony Chemit - [email protected]
* @since 1.27
*/
public class ToolkitEntityScriptModelGenerator extends TopiaMetadataModelGeneratorSupport {
private static final String UPDATE_LAST_UPDATE_DATE_FIELD_SQL_START = "UPDATE %s.%s SET lastUpdateDate = '%%1$s'::timestamp, topiaVersion = topiaVersion + 1";
private static final String UPDATE_LAST_UPDATE_DATE_FIELD_SQL_WHERE_EQUALS = " WHERE %s = '%%2$s'";
private static final String UPDATE_LAST_UPDATE_DATE_FIELD_SQL_WHERE_SELECT = " WHERE topiaId = ( %s )";
private static final String UPDATE_LAST_UPDATE_DATA_FIELD_SQL_SELECT_START = "SELECT %3$s FROM %1$s.%2$s %2$s";
private static final String UPDATE_LAST_UPDATE_DATA_FIELD_SQL_INNER_JOIN_REVERSE = " INNER JOIN %1$s.%2$s %2$s ON %2$s.%3$s = %4$s.%5$s";
private static final String UPDATE_LAST_UPDATE_DATA_FIELD_SQL_INNER_JOIN_SIMPLE = " INNER JOIN %1$s.%2$s %2$s ON %2$s.%3$s = %4$s.topiaId";
private static final String UPDATE_LAST_UPDATE_DATE_TABLE_SQL = "UPDATE common.lastUpdateDate SET lastUpdateDate = '%%1$s'::timestamp WHERE type ='%s'";
private final Gson gson = TopiaEntitySqlModelResourceImpl.getGsonBuilder().create();
@Override
public String getFilenameForModel(ObjectModel model) {
return TopiaEntitySqlModelResourceImpl.toScriptModelLocation(super.getFilenameForModel(model));
}
@Override
protected File getDestinationFile(File destDir, String filename) {
return destDir.toPath().resolve(filename).toFile();
}
@Override
protected void generateFromElement(Object element, File destDir, String filename, ObjectModelType type) {
if (ObjectModelType.OBJECT_MODEL != type) {
// only generate on model
return;
}
super.generateFromElement(element, destDir, filename, type);
}
@Override
public void generateFromModel(Writer output, ObjectModel input) {
TopiaTemplateHelper templateHelper = getTemplateHelper();
metadataModel = TopiaMetadataModelBuilder.buildFull(isVerbose(), model, templateHelper);
allPaths = getAllPaths();
Map queries = new TreeMap<>();
List entityClasses = templateHelper.getEntityClasses(model, true);
for (ObjectModelClass entityClass : entityClasses) {
if (entityClass.isAbstract()) {
continue;
}
boolean referential = entityClass.getPackageName().contains(".referential");
TopiaMetadataEntity entity = getEntityEnumName(entityClass);
UpdateLastUpdateDateFieldScript fieldRequests = new UpdateLastUpdateDateFieldScript(generateLastUpdateDateFieldRequests(entity));
UpdateLastUpdateDateTableScript tableRequests = new UpdateLastUpdateDateTableScript(generateLastUpdateDateTableRequests(entity));
ReplaceReferentialInDataScript replaceReferentialInDataScript = null;
ReplaceReferentialInReferentialScript replaceReferentialInReferentialScript = null;
DeleteReferentialScript deleteReferentialScript = null;
DisableReferentialScript disableReferentialScript = null;
if (referential) {
List replaceInDataScriptRequests = new ReplaceReferentialScriptGenerator(metadataModel, entity).generateSql("%2$s", "%3$s", "%1$s", true);
List replaceInReferentialScriptRequests = new ReplaceReferentialScriptGenerator(metadataModel, entity).generateSql("%2$s", "%3$s", "%1$s", false);
List deleteScriptRequests = new DeleteReferentialScriptGenerator(metadataModel, entity).generateSql("%1$s");
List disableScriptRequests = List.of(new DisableReferentialScriptGenerator(entity).generateSql());
replaceReferentialInDataScript = replaceInDataScriptRequests.isEmpty() ? null : new ReplaceReferentialInDataScript(replaceInDataScriptRequests);
replaceReferentialInReferentialScript = replaceInReferentialScriptRequests.isEmpty() ? null : new ReplaceReferentialInReferentialScript(replaceInReferentialScriptRequests);
deleteReferentialScript = new DeleteReferentialScript(deleteScriptRequests);
disableReferentialScript = new DisableReferentialScript(disableScriptRequests);
}
TopiaEntitySqlScript entityQueries = new TopiaEntitySqlScript(fieldRequests, tableRequests, replaceReferentialInDataScript, replaceReferentialInReferentialScript, deleteReferentialScript, disableReferentialScript);
queries.put(entity.getFullyQualifiedName(), entityQueries);
}
TopiaEntitySqlScriptModel scriptModel = new TopiaEntitySqlScriptModel(queries);
gson.toJson(scriptModel, output);
}
protected List generateLastUpdateDateFieldRequests(TopiaMetadataEntity entity) {
List types;
List links;
Optional optionalPath = getAllPaths().getEntityPathsForEntryPoint(entity);
if (optionalPath.isPresent()) {
TopiaMetadataEntityPath path = optionalPath.get();
links = new LinkedList<>(path.getLinks());
types = new LinkedList<>(path.getTypes());
} else {
// limit case, only one type
types = List.of(entity);
// and no link
links = List.of();
}
return generateLastUpdateDateFieldRequests(types, links);
}
protected List generateLastUpdateDateTableRequests(TopiaMetadataEntity entity) {
List types;
Optional optionalPath = getAllPaths().getEntityPathsForEntryPoint(entity);
if (optionalPath.isPresent()) {
TopiaMetadataEntityPath path = optionalPath.get();
types = new LinkedList<>(path.getTypes());
} else {
// limit case, only one type
types = List.of(entity);
// and no link
}
return generateLastUpdateDateTableRequests(types);
}
private List generateLastUpdateDateTableRequests(List types) {
List result = new LinkedList<>();
List tmp = new LinkedList<>(types);
Collections.reverse(tmp);
for (TopiaMetadataEntity type : tmp) {
String tableSql = String.format(UPDATE_LAST_UPDATE_DATE_TABLE_SQL, type.getFullyQualifiedName());
result.add(tableSql + ";");
}
return result;
}
private List generateLastUpdateDateFieldRequests(List types, List links) {
List builder = new LinkedList<>();
// take types in reverse order
Collections.reverse(types);
// take links in reverse order
Collections.reverse(links);
List inProcess = null;
Iterator linksIterator = links.iterator();
for (TopiaMetadataEntity type : types) {
String fieldSql = generateLastUpdateDateFieldRequest(type, inProcess);
builder.add(fieldSql + ";");
if (inProcess == null) {
// first round
inProcess = new LinkedList<>();
}
if (linksIterator.hasNext()) {
inProcess.add(linksIterator.next());
}
}
return builder;
}
private String generateLastUpdateDateFieldRequest(TopiaMetadataEntity type, List inProcess) {
String sql = String.format(UPDATE_LAST_UPDATE_DATE_FIELD_SQL_START, type.getDbSchemaName(), type.getDbTableName());
if (inProcess == null) {
sql += finalizeRequest(TopiaEntity.PROPERTY_TOPIA_ID);
return sql;
}
// Needs links from root to type
List tmp = new LinkedList<>(inProcess);
Collections.reverse(tmp);
Iterator inOderLinks = tmp.iterator();
TopiaMetadataLink firstLink = inOderLinks.next();
if (!inOderLinks.hasNext() && firstLink instanceof TopiaMetadataReverseAssociation) {
sql += finalizeRequest(firstLink.getTargetDbName());
return sql;
}
StringBuilder selectSql = new StringBuilder();
selectSql.append(prepareSubSelect(firstLink));
TopiaMetadataLink lastLink = firstLink;
while (inOderLinks.hasNext()) {
TopiaMetadataLink nextLink = inOderLinks.next();
if (!(nextLink instanceof TopiaMetadataReverseAssociation)) {
selectSql.append(appendInnerJoin(lastLink, nextLink));
}
lastLink = nextLink;
}
selectSql.append(finalizeSubSelect(lastLink));
sql += String.format(UPDATE_LAST_UPDATE_DATE_FIELD_SQL_WHERE_SELECT, selectSql);
return sql;
}
private String finalizeRequest(String column) {
return String.format(UPDATE_LAST_UPDATE_DATE_FIELD_SQL_WHERE_EQUALS, column);
}
private String prepareSubSelect(TopiaMetadataLink firstLink) {
String selectColumn;
TopiaMetadataEntity tableOwner;
if (firstLink instanceof TopiaMetadataReverseAssociation) {
tableOwner = firstLink.getOwner();
selectColumn = TopiaEntity.PROPERTY_TOPIA_ID;
} else {
tableOwner = firstLink.getTarget();
selectColumn = firstLink.getTarget().getDbColumnName(firstLink.getOwner().getDbTableName());
}
return String.format(UPDATE_LAST_UPDATE_DATA_FIELD_SQL_SELECT_START, tableOwner.getDbSchemaName(), tableOwner.getDbTableName(), tableOwner.getDbTableName() + "." + selectColumn);
}
private String appendInnerJoin(TopiaMetadataLink lastLink, TopiaMetadataLink nextLink) {
TopiaMetadataEntity tableOwner = nextLink.getTarget();
if (lastLink instanceof TopiaMetadataReverseAssociation) {
String columnName = lastLink.getTargetDbName();
return String.format(UPDATE_LAST_UPDATE_DATA_FIELD_SQL_INNER_JOIN_REVERSE, tableOwner.getDbSchemaName(), tableOwner.getDbTableName(), columnName, lastLink.getOwner().getDbTableName(), lastLink.getTargetDbName());
}
String columnName = tableOwner.getDbColumnName(nextLink.getOwner().getDbTableName());
return String.format(UPDATE_LAST_UPDATE_DATA_FIELD_SQL_INNER_JOIN_SIMPLE, tableOwner.getDbSchemaName(), tableOwner.getDbTableName(), columnName, lastLink.getTarget().getDbTableName());
}
private String finalizeSubSelect(TopiaMetadataLink lastLink) {
String targetColumn;
if (lastLink instanceof TopiaMetadataReverseAssociation) {
targetColumn = lastLink.getTableName() + "." + lastLink.getTargetDbName();
} else {
targetColumn = lastLink.getTarget().getDbTableName() + "." + TopiaEntity.PROPERTY_TOPIA_ID;
}
return finalizeRequest(targetColumn);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy