All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.topia.service.sql.TopiaEntitySqlModelResource Maven / Gradle / Ivy

The newest version!
package org.nuiton.topia.service.sql;

/*-
 * #%L
 * ToPIA Extension :: API
 * %%
 * Copyright (C) 2018 - 2022 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 org.nuiton.topia.service.sql.blob.TopiaEntitySqlBlobModel;
import org.nuiton.topia.service.sql.internal.SqlRequestSet;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataModel;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataModelPaths;
import org.nuiton.topia.service.sql.model.TopiaEntitySqlModel;
import org.nuiton.topia.service.sql.model.TopiaEntitySqlSelectArgument;
import org.nuiton.topia.service.sql.plan.copy.TopiaEntitySqlCopyPlan;
import org.nuiton.topia.service.sql.plan.copy.TopiaEntitySqlCopyPlanModel;
import org.nuiton.topia.service.sql.plan.copy.TopiaEntitySqlCopyPlanTask;
import org.nuiton.topia.service.sql.plan.delete.TopiaEntitySqlDeletePlan;
import org.nuiton.topia.service.sql.plan.delete.TopiaEntitySqlDeletePlanModel;
import org.nuiton.topia.service.sql.plan.replicate.TopiaEntitySqlReplicatePartialPlan;
import org.nuiton.topia.service.sql.plan.replicate.TopiaEntitySqlReplicatePartialPlanTask;
import org.nuiton.topia.service.sql.plan.replicate.TopiaEntitySqlReplicatePlan;
import org.nuiton.topia.service.sql.plan.replicate.TopiaEntitySqlReplicatePlanModel;
import org.nuiton.topia.service.sql.plan.replicate.TopiaEntitySqlReplicatePlanTask;
import org.nuiton.topia.service.sql.request.CopyRequest;
import org.nuiton.topia.service.sql.request.CreateDatabaseRequest;
import org.nuiton.topia.service.sql.request.DeletePartialRequest;
import org.nuiton.topia.service.sql.request.DeleteRequest;
import org.nuiton.topia.service.sql.request.ReplicatePartialRequest;
import org.nuiton.topia.service.sql.request.ReplicatePartialRequestCallback;
import org.nuiton.topia.service.sql.request.ReplicateRequest;
import org.nuiton.topia.service.sql.request.ReplicateRequestCallback;
import org.nuiton.topia.service.sql.usage.TopiaEntitySqlUsageModel;

import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * Created on 01/03/2022.
 *
 * @author Tony Chemit - [email protected]
 * @since 1.67
 */
public interface TopiaEntitySqlModelResource {

    TopiaEntitySqlModel getModel();

    TopiaEntitySqlCopyPlanModel getCopyPlanModel();

    TopiaEntitySqlReplicatePlanModel getReplicatePlanModel();

    TopiaEntitySqlDeletePlanModel getDeletePlanModel();

    TopiaEntitySqlUsageModel getUsageModel();

    TopiaEntitySqlBlobModel getBlobModel();

    TopiaMetadataModel getMetaModel();

    TopiaMetadataModelPaths getMetaModelPaths();

    Set getReplicatePartialRequestCallbacks();

    Set getReplicateRequestCallbacks();

    default Set createShell(ReplicatePartialRequest request) {
        return createPartialShell(request.getDataType(), request.getLayoutTypes());
    }

    default Set createShell(DeletePartialRequest request) {
        return createPartialShell(request.getDataType(), request.getLayoutTypes());
    }

    default SqlRequestSet buildSqlRequestSet(TopiaSqlServiceRequest request, Path targetPath) {
        SqlRequestSet.Builder builder = createBuilder(request, targetPath);
        if (request instanceof DeletePartialRequest) {
            buildSqlRequestSet(builder, ((DeletePartialRequest) request));
        } else if (request instanceof DeleteRequest) {
            buildSqlRequestSet(builder, ((DeleteRequest) request));
        } else if (request instanceof CopyRequest) {
            buildSqlRequestSet(builder, ((CopyRequest) request));
        } else if (request instanceof CreateDatabaseRequest) {
            buildSqlRequestSet(builder, ((CreateDatabaseRequest) request));
        } else if (request instanceof ReplicateRequest) {
            buildSqlRequestSet(builder, ((ReplicateRequest) request));
        } else if (request instanceof ReplicatePartialRequest) {
            buildSqlRequestSet(builder, ((ReplicatePartialRequest) request));
        } else {
            throw new IllegalArgumentException("Can't manage request: " + request);
        }
        return builder.build(this);
    }

    private void buildSqlRequestSet(SqlRequestSet.Builder builder, DeletePartialRequest request) {
        String dataType = request.getDataType();
        Set layoutTypes = request.getLayoutTypes();
        Set shell = createShell(request);
        // keys are existing shell on which perform detach (value entry key is table, value is column name)
        Map>> toDetach = new TreeMap<>();
        TopiaEntitySqlReplicatePlanModel replicatePlanModel = getReplicatePlanModel();
        for (TopiaEntitySqlReplicatePlan plan : replicatePlanModel.getPlans().values()) {
            for (TopiaEntitySqlReplicatePlanTask task : plan.getTasks()) {
                if (task.isEntryPoint() && !task.getColumnsToDetachSimple().isEmpty() && !shell.contains(task.getSchemaAndTableName())) {
                    for (Map.Entry entry : task.getColumnsToDetachSimple()) {
                        String requiredTable = entry.getValue();
                        if (shell.contains(requiredTable)) {
                            // need to detach this one
                            toDetach.computeIfAbsent(requiredTable, e -> new LinkedList<>()).add(Map.entry(task.getSchemaAndTableName(), entry.getKey()));
                        }
                    }
                }
            }
        }
        Map>> detachTasksMapping = new LinkedHashMap<>();
        for (String entityTypeName : layoutTypes) {
            TopiaEntitySqlReplicatePlan replicatePlan = replicatePlanModel.getPlan(entityTypeName);
            for (TopiaEntitySqlReplicatePlanTask replicateTask : replicatePlan) {
                boolean canExecute = replicateTask.accept(shell);
                if (canExecute) {
                    String name = replicateTask.getSchemaAndTableName();
                    List> detachTasks = toDetach.get(name);
                    if (detachTasks != null) {
                        Map> cleanDetachTasks = new TreeMap<>();
                        for (Map.Entry detachTask : detachTasks) {
                            String table = detachTask.getKey();
                            cleanDetachTasks.computeIfAbsent(table, e -> new TreeSet<>()).add(detachTask.getValue());
                        }
                        detachTasksMapping.put(name, cleanDetachTasks);
                    }
                }
            }
        }
        TopiaEntitySqlDeletePlan plan = getDeletePlanModel().getPlan(dataType);
        TopiaEntitySqlSelectArgument selectArgument = TopiaEntitySqlSelectArgument.of(request.getDataIds());
        builder.addDeletePartialTableRequest(plan, selectArgument, shell, detachTasksMapping);
    }

    private void buildSqlRequestSet(SqlRequestSet.Builder builder, DeleteRequest request) {
        TopiaEntitySqlDeletePlan plan = getDeletePlanModel().getPlan(request.getDataType());
        TopiaEntitySqlSelectArgument selectArgument = TopiaEntitySqlSelectArgument.of(request.getDataIds());
        builder.addDeleteTableRequest(plan, selectArgument);
    }

    private void buildSqlRequestSet(SqlRequestSet.Builder builder, CopyRequest request) {
        TopiaEntitySqlCopyPlan plan = getCopyPlanModel().getEntryPointPlan(request.getDataType());
        TopiaEntitySqlSelectArgument selectArgument = request.getDataIds().isEmpty() ? null : TopiaEntitySqlSelectArgument.of(request.getDataIds());
        builder.addCopyTableRequest(plan, selectArgument);
    }

    private void buildSqlRequestSet(SqlRequestSet.Builder builder, ReplicateRequest request) {
        TopiaEntitySqlReplicatePlan plan = getReplicatePlanModel().getPlan(request.getDataType());
        TopiaEntitySqlSelectArgument selectArgument = TopiaEntitySqlSelectArgument.of(request.getDataIds());
        Set callbacks = getReplicateRequestCallbacks().stream().filter(e -> e.accept(request)).collect(Collectors.toSet());
        builder.addReplicateTableRequest(plan, request, callbacks);
    }

    private void buildSqlRequestSet(SqlRequestSet.Builder builder, ReplicatePartialRequest request) {
        String dataType = request.getDataType();
        Set layoutTypes = request.getLayoutTypes();
        Set shell = createShell(request);
        TopiaEntitySqlCopyPlan copyPlan = getCopyPlanModel().getEntryPointPlan(dataType);
        Map copyTaskByTable = Objects.requireNonNull(copyPlan).tasksByTable();
        TopiaEntitySqlReplicatePlanModel replicatePlanModel = getReplicatePlanModel();
        Map taskMapping = new TreeMap<>();
        for (String entityTypeName : layoutTypes) {
            TopiaEntitySqlReplicatePlan replicatePlan = replicatePlanModel.getPlan(entityTypeName);
            for (TopiaEntitySqlReplicatePlanTask replicateTask : replicatePlan) {
                boolean canExecute = replicateTask.accept(shell);
                if (canExecute) {
                    String name = replicateTask.getSchemaAndTableName();
                    TopiaEntitySqlCopyPlanTask copyTask = copyTaskByTable.get(name);
                    taskMapping.put(name, new TopiaEntitySqlReplicatePartialPlanTask(copyTask, replicateTask));
                }
            }
        }
        Set callbacks = getReplicatePartialRequestCallbacks().stream().filter(e -> e.accept(request)).collect(Collectors.toSet());
        Set tasks = shell.stream().map(taskMapping::get).collect(Collectors.toCollection(LinkedHashSet::new));
        TopiaEntitySqlReplicatePartialPlan plan = new TopiaEntitySqlReplicatePartialPlan(tasks);
        builder.addReplicatePartialTableRequest(plan, request, callbacks);
    }

    private void buildSqlRequestSet(SqlRequestSet.Builder builder, CreateDatabaseRequest request) {
        if (request.isAddSchema()) {
            builder.addCreateSchemaRequest(true, true);
        }
        if (request.isAddGeneratedSchema()) {
            builder.addGeneratedSchemaRequest(request.getDbVersion());
        }
        if (request.isAddVersionTable()) {
            builder.addVersionTableRequest(request.getDbVersion());
        }
        TopiaEntitySqlCopyPlanModel copyPlan = getCopyPlanModel();
        if (request.isAddStandaloneTables()) {
            builder.addCopyTableRequest(copyPlan.getStandalonePlan(), null);
        }
        if (request.isAddData()) {
            Map> allDataIds = request.getDataIds();
            Map entryPoints = copyPlan.getEntryPointPlans();
            boolean copyAll = allDataIds.isEmpty();
            for (Map.Entry entry : entryPoints.entrySet()) {
                String entryPoint = entry.getKey();
                TopiaEntitySqlCopyPlan plan = entry.getValue();
                if (copyAll) {
                    builder.addCopyTableRequest(plan, null);
                } else {
                    Set dataIds = allDataIds.get(entryPoint);
                    if (dataIds != null && !dataIds.isEmpty()) {
                        TopiaEntitySqlSelectArgument selectArgument = TopiaEntitySqlSelectArgument.of(dataIds);
                        builder.addCopyTableRequest(plan, selectArgument);
                    }
                }
            }
        }
    }

    private SqlRequestSet.Builder createBuilder(TopiaSqlServiceRequest request, Path targetPath) {
        SqlRequestSet.Builder builder = SqlRequestSet.builder(targetPath);
        if (request.isPostgres()) {
            builder.forPostgresql();
        } else {
            builder.forH2();
        }
        return builder;
    }

    private Set createPartialShell(String entryPointType, Set layoutTypes) {
        TopiaEntitySqlReplicatePlanModel replicatePlanModel = getReplicatePlanModel();
        List unorderedShell = new LinkedList<>();
        for (String entityTypeName : layoutTypes) {
            TopiaEntitySqlReplicatePlan replicatePlan = replicatePlanModel.getPlan(entityTypeName);
            Set shell = replicatePlan.getShell();
            unorderedShell.addAll(shell);
        }
        TopiaEntitySqlCopyPlan copyPlan = getCopyPlanModel().getEntryPointPlan(entryPointType);
        Set shell = copyPlan.getShell();
        shell.retainAll(unorderedShell);
        return shell;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy