From 2316b4b1f79b0f641acf072bd7344609d1f58649 Mon Sep 17 00:00:00 2001 From: okoyzar Date: Tue, 17 Sep 2024 10:50:35 +0100 Subject: [PATCH 1/2] Data Type Maintain merge #7138 #CTCTOWALTZ-3346 --- .../maintain/DataTypeMaintain.svelte | 93 +++++++++++++++++++ waltz-ng/client/data-types/index.js | 4 +- .../data-types/pages/home/data-type-home.html | 11 ++- .../pages/maintain/data-type-maintain.html | 21 +++++ .../pages/maintain/data-type-maintain.js | 51 ++++++++++ waltz-ng/client/data-types/routes.js | 10 +- 6 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 waltz-ng/client/data-types/components/maintain/DataTypeMaintain.svelte create mode 100644 waltz-ng/client/data-types/pages/maintain/data-type-maintain.html create mode 100644 waltz-ng/client/data-types/pages/maintain/data-type-maintain.js diff --git a/waltz-ng/client/data-types/components/maintain/DataTypeMaintain.svelte b/waltz-ng/client/data-types/components/maintain/DataTypeMaintain.svelte new file mode 100644 index 0000000000..70d0cadc2b --- /dev/null +++ b/waltz-ng/client/data-types/components/maintain/DataTypeMaintain.svelte @@ -0,0 +1,93 @@ + + + + +
+
    +
  1. + Home +
  2. +
  3. + Data Types +
  4. +
  5. + Maintain +
  6. +
+
+
+ +
+
+

+ Hello World +

+
+
+ From + + {#if sourceDataType} + + + {:else} + + {/if} +
+
+ Migrate » +
+
+ To + + {#if targetDataType} + + + {:else} + + {/if} +
+
+

{canApply}

+ +
+
diff --git a/waltz-ng/client/data-types/index.js b/waltz-ng/client/data-types/index.js index dbcca0c218..a75ad87078 100644 --- a/waltz-ng/client/data-types/index.js +++ b/waltz-ng/client/data-types/index.js @@ -31,6 +31,7 @@ import RelatedDataTypesSection from './components/related-data-types-section/rel import DataTypesDecoratorSection from './components/data-type-decorator-section/data-type-decorator-section'; import Routes from './routes'; import DataTypeViewData from './services/data-type-view-data'; +import DataTypeMaintain from './pages/maintain/data-type-maintain'; export default () => { const module = angular.module('waltz.data.types', []); @@ -47,7 +48,8 @@ export default () => { DataTypeUsageSelector, DataTypeUsageTree, RelatedDataTypesSection, - DataTypesDecoratorSection + DataTypesDecoratorSection, + DataTypeMaintain ]); module diff --git a/waltz-ng/client/data-types/pages/home/data-type-home.html b/waltz-ng/client/data-types/pages/home/data-type-home.html index cc57366e88..9b8afba771 100644 --- a/waltz-ng/client/data-types/pages/home/data-type-home.html +++ b/waltz-ng/client/data-types/pages/home/data-type-home.html @@ -18,7 +18,7 @@
- @@ -29,7 +29,7 @@ Home -
  • Data
  • +
  • Data Types
  • @@ -76,6 +76,13 @@ +
    +
    diff --git a/waltz-ng/client/data-types/pages/maintain/data-type-maintain.html b/waltz-ng/client/data-types/pages/maintain/data-type-maintain.html new file mode 100644 index 0000000000..8dffd57002 --- /dev/null +++ b/waltz-ng/client/data-types/pages/maintain/data-type-maintain.html @@ -0,0 +1,21 @@ + + + + \ No newline at end of file diff --git a/waltz-ng/client/data-types/pages/maintain/data-type-maintain.js b/waltz-ng/client/data-types/pages/maintain/data-type-maintain.js new file mode 100644 index 0000000000..11fab18a53 --- /dev/null +++ b/waltz-ng/client/data-types/pages/maintain/data-type-maintain.js @@ -0,0 +1,51 @@ +/* + * Waltz - Enterprise Architecture + * Copyright (C) 2016, 2017, 2018, 2019 Waltz open source project + * See README.md for more information + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific + * + */ + +import angular from "angular"; +import template from "./data-type-maintain.html"; +import {initialiseData} from "../../../common"; +import {CORE_API} from "../../../common/services/core-api-utils"; +import DataTypeMaintain from "../../components/maintain/DataTypeMaintain.svelte" + + +const bindings = {} + +const initialState = { + DataTypeMaintain +}; + + +function controller() { + + const vm = initialiseData(this, initialState); +} + + +controller.$inject = []; + + +const component = { + template, + controller, + bindings +} + +export default { + component, + id: "waltzDataTypeMaintain", +}; \ No newline at end of file diff --git a/waltz-ng/client/data-types/routes.js b/waltz-ng/client/data-types/routes.js index 2c026cb5a2..86eb55c757 100644 --- a/waltz-ng/client/data-types/routes.js +++ b/waltz-ng/client/data-types/routes.js @@ -20,6 +20,7 @@ import {loadDataTypes, dataTypeByCodeResolver, dataTypeByIdResolver} from "./res import HomePage from './pages/home/data-type-home'; import ViewPage from './pages/view/data-type-view'; +import MaintainPage from './pages/maintain/data-type-maintain'; const baseState = { @@ -54,6 +55,12 @@ const viewState = { resolve: {dataType: dataTypeByIdResolver } }; +const maintainState = { + url: 'data-types/maintain', + views: {'content@': MaintainPage.id } +}; + + function setup($stateProvider) { $stateProvider @@ -61,7 +68,8 @@ function setup($stateProvider) { .state('main.data-type.list', listState) .state('main.data-type.code', viewByCodeState) .state('main.data-type.external-id', viewByExternalIdState) - .state('main.data-type.view', viewState); + .state('main.data-type.view', viewState) + .state('main.data-type.maintain', maintainState); } setup.$inject = ['$stateProvider']; From 71b573153f76b2d7b7f80192f5252a169a97b070 Mon Sep 17 00:00:00 2001 From: okoyzar Date: Mon, 23 Sep 2024 15:54:11 +0100 Subject: [PATCH 2/2] Data Type Maintain merge - Added error checking - Added UI to display results on migrate - Enabled removal of source data type #7138 #CTCTOWALTZ-3346 --- .../waltz/data/data_type/DataTypeDao.java | 7 + .../data/data_type}/DataTypeUtilities.java | 104 ++++---- .../datatype/DataTypeMigrationResult.java | 14 ++ .../maintain/DataTypeMaintain.svelte | 226 +++++++++++++++--- .../pages/maintain/data-type-maintain.html | 2 +- .../client/svelte-stores/data-type-store.js | 12 +- .../service/data_type/DataTypeService.java | 5 + .../web/endpoints/api/DataTypesEndpoint.java | 47 ++-- 8 files changed, 317 insertions(+), 100 deletions(-) rename {waltz-jobs/src/main/java/org/finos/waltz/jobs/tools => waltz-data/src/main/java/org/finos/waltz/data/data_type}/DataTypeUtilities.java (84%) create mode 100644 waltz-model/src/main/java/org/finos/waltz/model/datatype/DataTypeMigrationResult.java diff --git a/waltz-data/src/main/java/org/finos/waltz/data/data_type/DataTypeDao.java b/waltz-data/src/main/java/org/finos/waltz/data/data_type/DataTypeDao.java index cccd7c77a8..28ac96530f 100644 --- a/waltz-data/src/main/java/org/finos/waltz/data/data_type/DataTypeDao.java +++ b/waltz-data/src/main/java/org/finos/waltz/data/data_type/DataTypeDao.java @@ -23,6 +23,7 @@ import org.finos.waltz.model.EntityLifecycleStatus; import org.finos.waltz.model.EntityReference; import org.finos.waltz.model.datatype.DataType; +import org.finos.waltz.model.datatype.DataTypeMigrationResult; import org.finos.waltz.model.datatype.ImmutableDataType; import org.finos.waltz.schema.tables.records.DataTypeRecord; import org.jooq.Condition; @@ -76,6 +77,12 @@ public DataTypeDao(DSLContext dsl) { this.dsl = dsl; } + public DataTypeMigrationResult migrate(Long fromId, Long toId, boolean deleteOldDataType) { + return dsl.transactionResult(ctx -> { + DSLContext tx = ctx.dsl(); + return DataTypeUtilities.migrate(tx, fromId, toId, deleteOldDataType); + }); + } public List findAll() { return dsl diff --git a/waltz-jobs/src/main/java/org/finos/waltz/jobs/tools/DataTypeUtilities.java b/waltz-data/src/main/java/org/finos/waltz/data/data_type/DataTypeUtilities.java similarity index 84% rename from waltz-jobs/src/main/java/org/finos/waltz/jobs/tools/DataTypeUtilities.java rename to waltz-data/src/main/java/org/finos/waltz/data/data_type/DataTypeUtilities.java index ff72fdd702..1c7fc2a055 100644 --- a/waltz-jobs/src/main/java/org/finos/waltz/jobs/tools/DataTypeUtilities.java +++ b/waltz-data/src/main/java/org/finos/waltz/data/data_type/DataTypeUtilities.java @@ -1,9 +1,12 @@ -package org.finos.waltz.jobs.tools; +package org.finos.waltz.data.data_type; +import org.finos.waltz.common.Checks; import org.finos.waltz.common.SetUtilities; import org.finos.waltz.model.EntityKind; import org.finos.waltz.model.EntityLifecycleStatus; import org.finos.waltz.model.EntityReference; +import org.finos.waltz.model.datatype.DataTypeMigrationResult; +import org.finos.waltz.model.datatype.ImmutableDataTypeMigrationResult; import org.finos.waltz.schema.Tables; import org.finos.waltz.schema.tables.DataType; import org.finos.waltz.schema.tables.DataTypeUsage; @@ -14,7 +17,6 @@ import org.finos.waltz.schema.tables.PhysicalSpecDataType; import org.finos.waltz.schema.tables.PhysicalSpecification; import org.finos.waltz.schema.tables.records.LogicalFlowRecord; -import org.finos.waltz.service.DIConfiguration; import org.jooq.Condition; import org.jooq.DSLContext; import org.jooq.impl.DSL; @@ -22,9 +24,7 @@ import org.jooq.lambda.tuple.Tuple2; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.Map; @@ -34,11 +34,12 @@ import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; import static org.finos.waltz.model.EntityReference.mkRef; +import static org.finos.waltz.schema.Tables.DATA_TYPE; public class DataTypeUtilities { private static final Logger LOG = LoggerFactory.getLogger(DataTypeUtilities.class); - private static final DataType dataType = Tables.DATA_TYPE; + private static final DataType dataType = DATA_TYPE; private static final LogicalFlow logicalFlow = Tables.LOGICAL_FLOW; private static final LogicalFlowDecorator logicalFlowDecorator = Tables.LOGICAL_FLOW_DECORATOR; private static final FlowClassificationRule flowClassificationRule = Tables.FLOW_CLASSIFICATION_RULE; @@ -106,6 +107,15 @@ private static long removeDataType(DSLContext dsl, } + private static boolean removeDataType(DSLContext dsl, + long fromId) { + return dsl + .delete(dataType) + .where(dataType.ID.eq(fromId)) + .execute() > 0; + } + + public static void migrate(DSLContext dsl, String fromCode, String toCode, @@ -132,20 +142,41 @@ public static void migrate(DSLContext dsl, // 4) update flow_classification_rules set data_type_id = toId where data_type_id = fromId // x) delete from dataType where code = 'fromCode' - migrateDataTypeUsage(dsl, fromId, toId); - migrateFlowClassificationRules(dsl, fromId, toId); - migrateLogicalFlowDecorator(dsl, fromId, toId); - migratePhysicalSpecDataType(dsl, fromId, toId); + migrate(dsl, fromId, toId, deleteOldDataType); + + } + + private static void verifyDataTypeHasNoChildren(DSLContext dsl, Long fromId) { + int childCount = dsl.fetchCount(DATA_TYPE, DATA_TYPE.PARENT_ID.eq(fromId)); + Checks.checkTrue(childCount == 0, "Data Type, %d has %d children", fromId, childCount); + } + public static DataTypeMigrationResult migrate(DSLContext dsl, Long fromId, Long toId, boolean deleteOldDataType) { if (deleteOldDataType) { - removeDataType(dsl, fromCode); + verifyDataTypeHasNoChildren(dsl, fromId); } + int dtuCount = migrateDataTypeUsage(dsl, fromId, toId); + int crCount = migrateFlowClassificationRules(dsl, fromId, toId); + int lfCount = migrateLogicalFlowDecorator(dsl, fromId, toId); + int psCount = migratePhysicalSpecDataType(dsl, fromId, toId); + boolean dataTypeRemoved = deleteOldDataType + ? removeDataType(dsl, fromId) + : false; + + return ImmutableDataTypeMigrationResult + .builder() + .usageCount(dtuCount) + .classificationRuleCount(crCount) + .logicalFlowDataTypeCount(lfCount) + .physicalSpecDataTypeCount(psCount) + .dataTypeRemoved(dataTypeRemoved) + .build(); } - private static void migratePhysicalSpecDataType(DSLContext dsl, - Long fromId, - Long toId) { + private static int migratePhysicalSpecDataType(DSLContext dsl, + Long fromId, + Long toId) { PhysicalSpecDataType physicSpec = physicalSpecDataType.as("physicSpec"); Condition notAlreadyExists = DSL .notExists(DSL @@ -167,12 +198,13 @@ private static void migratePhysicalSpecDataType(DSLContext dsl, .execute(); LOG.info("Migrate Phys Spec Data Type Usage: {} -> {}, updated: {}, removed: {}", fromId, toId, updateCount, rmCount); + return updateCount + rmCount; } - private static void migrateLogicalFlowDecorator(DSLContext dsl, - Long fromId, - Long toId) { + private static int migrateLogicalFlowDecorator(DSLContext dsl, + Long fromId, + Long toId) { LogicalFlowDecorator decorator = logicalFlowDecorator.as("decorator"); Condition notAlreadyExists = DSL.notExists(DSL @@ -197,12 +229,14 @@ private static void migrateLogicalFlowDecorator(DSLContext dsl, .execute(); LOG.info("Migrate Logical Flow Decorator: {} -> {}, updated: {}, removed: {}", fromId, toId, updateCount, rmCount); + + return updateCount + rmCount; } - private static void migrateFlowClassificationRules(DSLContext dsl, - Long fromId, - Long toId) { + private static int migrateFlowClassificationRules(DSLContext dsl, + Long fromId, + Long toId) { FlowClassificationRule authSrc = flowClassificationRule.as("authSrc"); @@ -228,12 +262,14 @@ private static void migrateFlowClassificationRules(DSLContext dsl, .execute(); LOG.info("Migrate Flow Classification Rules: {} -> {}, updated: {}, removed: {}", fromId, toId, updateCount, rmCount); + return updateCount + rmCount; + } - private static void migrateDataTypeUsage(DSLContext dsl, - Long fromId, - Long toId) { + private static int migrateDataTypeUsage(DSLContext dsl, + Long fromId, + Long toId) { DataTypeUsage dtu = dataTypeUsage.as("dtu"); Condition condition = DSL.notExists(DSL @@ -257,6 +293,8 @@ private static void migrateDataTypeUsage(DSLContext dsl, .execute(); LOG.info("Migrate DataType Usage: {} -> {}, updated: {}, removed: {}", fromId, toId, updateCount, rmCount); + + return updateCount + rmCount; } public static List findLogicalFlowIdsForDataType(DSLContext dsl, Long datatype, Set logicalFlowIds) { @@ -366,26 +404,4 @@ public static long markDataTypeAsConcrete(DSLContext dsl, .where(dataType.CODE.in(dataTypeCodes)) .execute(); } - - - public static void main(String[] args) throws IOException { - - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(DIConfiguration.class); - DSLContext dsl = ctx.getBean(DSLContext.class); - - String party = "DataTypeCode1"; - String allocation = "DataTypeCode2"; - String instrumentIdentifier = "DataTypeCode3"; - String prospect = "DataTypeCode4"; - String dealEvent = "DataTypeCode5"; - String instrumentStatic = "DataTypeCode6"; - - dsl.transaction(context -> { - DSLContext tx = context.dsl(); - migrate(tx, instrumentIdentifier, instrumentStatic, false); - migrate(tx, prospect, party, false); - migrate(tx, allocation, dealEvent, false); - //throw new RuntimeException("BoooM!"); - }); - } } diff --git a/waltz-model/src/main/java/org/finos/waltz/model/datatype/DataTypeMigrationResult.java b/waltz-model/src/main/java/org/finos/waltz/model/datatype/DataTypeMigrationResult.java new file mode 100644 index 0000000000..923cebbd6e --- /dev/null +++ b/waltz-model/src/main/java/org/finos/waltz/model/datatype/DataTypeMigrationResult.java @@ -0,0 +1,14 @@ +package org.finos.waltz.model.datatype; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.immutables.value.Value; + +@Value.Immutable +@JsonSerialize(as=ImmutableDataTypeMigrationResult.class) +public interface DataTypeMigrationResult { + long usageCount(); + long classificationRuleCount(); + long logicalFlowDataTypeCount(); + long physicalSpecDataTypeCount(); + boolean dataTypeRemoved(); +} diff --git a/waltz-ng/client/data-types/components/maintain/DataTypeMaintain.svelte b/waltz-ng/client/data-types/components/maintain/DataTypeMaintain.svelte index 70d0cadc2b..64ac6610e3 100644 --- a/waltz-ng/client/data-types/components/maintain/DataTypeMaintain.svelte +++ b/waltz-ng/client/data-types/components/maintain/DataTypeMaintain.svelte @@ -2,38 +2,107 @@ import ViewLink from "../../../common/svelte/ViewLink.svelte"; import PageHeader from "../../../common/svelte/PageHeader.svelte"; - //import {actorStore} from "../../../svelte-stores/actor-store"; - //import {termSearch} from "../../../common"; import _ from "lodash"; - //import SearchInput from "../../../common/svelte/SearchInput.svelte"; - import EntityLink from "../../../common/svelte/EntityLink.svelte"; - import DataExtractLink from "../../../common/svelte/DataExtractLink.svelte"; - import EntitySearchSelector from "../../../common/svelte/EntitySearchSelector.svelte"; import EntityLabel from "../../../common/svelte/EntityLabel.svelte"; - import DataTypePicker from "../../../common/svelte/entity-pickers/DataTypePicker.svelte"; - import DataTypeTreeNode from "../../../common/svelte/DataTypeTreeNode.svelte"; import DataTypeTreeSelector from "../../../common/svelte/DataTypeTreeSelector.svelte"; + import toasts from "../../../svelte-stores/toast-store"; + import { dataTypeStore } from "../../../svelte-stores/data-type-store"; + import {displayError} from "../../../common/error-utils"; + import SubSection from "../../../common/svelte/SubSection.svelte"; + import Icon from "../../../common/svelte/Icon.svelte"; + + const Modes = { + MIGRATE_PICKER : "MIGRATE_PICKER", + MIGRATE_OPTIONS : "MIGRATE_OPTIONS", + MIGRATE_CONFIRM : "MIGRATE_CONFIRM", + MIGRATE_RESULT : "MIGRATE_RESULT", + WAITING : "WAITING", + MIGRATE_ERROR : "MIGRATE_ERROR" + }; + + let mode = Modes.MIGRATE_PICKER; let sourceDataType = null; let targetDataType = null; let canApply = false; + let removeSource = false; + let migrateResult = null; function onSourceDataTypeSelect(evt) { - console.log("Hi Dad", evt.detail); sourceDataType = evt.detail; } function onTargetDataTypeSelect(evt) { const dataType = evt.detail; if (!dataType.concrete){ - console.log("No way jose") + toasts.warning("You must select a concrete data type as the merge target"); + return; + } + if (dataType.deprecated){ + toasts.warning("You cannot select a deprecated data type as the merge target"); + return; + } + if (dataType.id === sourceDataType.id){ + toasts.warning("You cannot migrate from and to the same data type"); return; } - console.log("Hi Mum", dataType); targetDataType = dataType; + mode = Modes.MIGRATE_OPTIONS; } - $: canApply = targetDataType && targetDataType.concrete && !targetDataType.deprecrated + function onTargetDataTypeChange() { + targetDataType = null; + mode = Modes.MIGRATE_PICKER; + } + + function doMigrate() { + mode = Modes.WAITING; + dataTypeStore + .migrate(sourceDataType.id, targetDataType.id, removeSource) + .then(r => { + migrateResult = r.data; + mode = Modes.MIGRATE_RESULT; + }) + .catch(e => { + displayError("Could not migrate", e); + mode = Modes.MIGRATE_ERROR; + }); + } + + function onMigrate() { + mode = Modes.MIGRATE_CONFIRM; + } + + function onConfirmationCancel() { + mode = Modes.MIGRATE_OPTIONS; + } + + function onDoneMigrate() { + mode = Modes.MIGRATE_PICKER; + sourceDataType = null; + targetDataType = null; + removeSource = false; + migrateResult = null; + } + + $: canApply = _.isEmpty(errors); + + $: { + if(sourceDataType) { + if (!_.isEmpty(sourceDataType.children) && removeSource) { + toasts.warning('Cannot delete a data type that has children'); + canApply = false; + } else { + canApply = true; + } + } + }; + + $: errors = _.compact([ + sourceDataType ? null : 'NO_DATA_TYPE_SOURCE', + targetDataType ? null : 'NO_DATA_TYPE_TARGET', + ]); +
    -

    - Hello World -

    +
    + Select a data type you wish to modify. +
    -
    - From - - {#if sourceDataType} - - - {:else} - + From + - {/if}
    -
    - Migrate » -
    -
    - To +
    + {#if sourceDataType} + +
    + Actions +
    +
    + Selected Data Type: +
    + Migrate +
    +
    + This action migrates data type usage from the source data type to a destination data type. + You may optionally remove the source data type when the migration is completed. +
    + {#if mode === Modes.MIGRATE_PICKER} +
    Select a data type to merge into, this must be concrete and non-deprecated
    + + {/if} + {#if mode === Modes.MIGRATE_OPTIONS} +
    If you choose to remove the source data type, be aware this cannot be undone
    +
    + To + +
    + +
    + + +
    + + + {/if} + {#if mode === Modes.MIGRATE_CONFIRM} +
    + Are you sure you wish to migrate from to ? + {#if removeSource} +
    + Once migration is complete the source data type will be removed + {/if} +
    + + +
    + {/if} + {#if mode === Modes.WAITING} +

    Please wait...

    + {/if} + {#if mode === Modes.MIGRATE_RESULT} + + + + + + + + - {#if targetDataType} - - - {:else} - - {/if} + + + + + + + + + + + + + +
    Logical Flow Data Types Changed{migrateResult.logicalFlowDataTypeCount}
    Physical Specification Data Types Changed{migrateResult.physicalSpecDataTypeCount}
    Classification Rules Changed{migrateResult.classificationRuleCount}
    Data Type Usages Changed{migrateResult.usageCount}
    Source Data Type Removed?{migrateResult.dataTypeRemoved}
    + + {/if} +
    +
    +
    +
    + {:else} + +
    + Pending changes +
    +
    + Waiting for Selection... +
    +
    + {/if}
    -

    {canApply}

    - -
    +
    diff --git a/waltz-ng/client/data-types/pages/maintain/data-type-maintain.html b/waltz-ng/client/data-types/pages/maintain/data-type-maintain.html index 8dffd57002..aa1bb86255 100644 --- a/waltz-ng/client/data-types/pages/maintain/data-type-maintain.html +++ b/waltz-ng/client/data-types/pages/maintain/data-type-maintain.html @@ -17,5 +17,5 @@ --> - + \ No newline at end of file diff --git a/waltz-ng/client/svelte-stores/data-type-store.js b/waltz-ng/client/svelte-stores/data-type-store.js index f7d247633b..03386f3c69 100644 --- a/waltz-ng/client/svelte-stores/data-type-store.js +++ b/waltz-ng/client/svelte-stores/data-type-store.js @@ -52,13 +52,21 @@ export function mkDataTypeStore() { `api/data-types/suggested/entity/${ref.kind}/${ref.id}`, null, {force}); - } + }; + + const migrate = (sourceDataTypeId, targetDataTypeId, removeSource = false) => { + return remote.execute( + "POST", + `api/data-types/migrate/${sourceDataTypeId}/to/${targetDataTypeId}?removeSource=${removeSource}`, + null); + }; return { findAll, getById, findByParentId, - findSuggestedByRef + findSuggestedByRef, + migrate }; } diff --git a/waltz-service/src/main/java/org/finos/waltz/service/data_type/DataTypeService.java b/waltz-service/src/main/java/org/finos/waltz/service/data_type/DataTypeService.java index 26798bf2a8..48780e8803 100644 --- a/waltz-service/src/main/java/org/finos/waltz/service/data_type/DataTypeService.java +++ b/waltz-service/src/main/java/org/finos/waltz/service/data_type/DataTypeService.java @@ -27,6 +27,7 @@ import org.finos.waltz.model.EntityReference; import org.finos.waltz.model.IdSelectionOptions; import org.finos.waltz.model.datatype.DataType; +import org.finos.waltz.model.datatype.DataTypeMigrationResult; import org.finos.waltz.model.entity_search.EntitySearchOptions; import org.jooq.Record1; import org.jooq.Select; @@ -68,12 +69,16 @@ public DataTypeService(DataTypeDao dataTypeDao, this.logicalFlowDao = logicalFlowDao; } + public DataTypeMigrationResult migrate(Long fromId, Long toId, boolean deleteOldDataType) { + return dataTypeDao.migrate(fromId, toId, deleteOldDataType); + } public List findAll() { return dataTypeDao.findAll(); } + public DataType getDataTypeById(long dataTypeId) { return dataTypeDao.getById(dataTypeId); } diff --git a/waltz-web/src/main/java/org/finos/waltz/web/endpoints/api/DataTypesEndpoint.java b/waltz-web/src/main/java/org/finos/waltz/web/endpoints/api/DataTypesEndpoint.java index 31c8e2fccc..8ffe0544b4 100644 --- a/waltz-web/src/main/java/org/finos/waltz/web/endpoints/api/DataTypesEndpoint.java +++ b/waltz-web/src/main/java/org/finos/waltz/web/endpoints/api/DataTypesEndpoint.java @@ -18,7 +18,10 @@ package org.finos.waltz.web.endpoints.api; +import org.finos.waltz.model.datatype.DataTypeMigrationResult; +import org.finos.waltz.model.user.SystemRole; import org.finos.waltz.service.data_type.DataTypeService; +import org.finos.waltz.service.user.UserRoleService; import org.finos.waltz.web.DatumRoute; import org.finos.waltz.web.ListRoute; import org.finos.waltz.web.WebUtilities; @@ -28,11 +31,9 @@ import org.finos.waltz.model.entity_search.EntitySearchOptions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import spark.Request; -import static org.finos.waltz.web.WebUtilities.getEntityReference; -import static org.finos.waltz.web.WebUtilities.getId; -import static org.finos.waltz.web.WebUtilities.mkPath; -import static org.finos.waltz.web.WebUtilities.readBody; +import static org.finos.waltz.web.WebUtilities.*; import static org.finos.waltz.web.endpoints.EndpointUtilities.*; import static java.lang.Long.parseLong; import static org.finos.waltz.common.Checks.checkNotNull; @@ -43,12 +44,15 @@ public class DataTypesEndpoint implements Endpoint { private static final String BASE_URL = WebUtilities.mkPath("api", "data-types"); - private final DataTypeService service; + private final DataTypeService dataTypeService; + private final UserRoleService userRoleService; @Autowired - public DataTypesEndpoint(DataTypeService service) { - checkNotNull(service, "service must not be null"); - this.service = service; + public DataTypesEndpoint(DataTypeService dataTypeService, UserRoleService userRoleService) { + checkNotNull(dataTypeService, "dataTypeService must not be null"); + checkNotNull(userRoleService, "userRoleService must not be null"); + this.userRoleService = userRoleService; + this.dataTypeService = dataTypeService; } @@ -59,30 +63,45 @@ public void register() { String getDataTypeByCodePath = mkPath(BASE_URL, "code", ":code"); String findSuggestedByEntityRefPath = mkPath(BASE_URL, "suggested", "entity", ":kind", ":id"); String findByParentIdPath = mkPath(BASE_URL, "parent-id", ":id"); + String migratePath = mkPath(BASE_URL, "migrate", ":sourceDataTypeId", "to", ":targetDataTypeId"); ListRoute searchRoute = (request, response) -> - service.search(EntitySearchOptions + dataTypeService.search(EntitySearchOptions .mkForEntity(EntityKind.DATA_TYPE, readBody(request, String.class))); DatumRoute getDataTypeByIdRoute = (request, response) -> - service.getDataTypeById(parseLong(request.params("id"))); + dataTypeService.getDataTypeById(parseLong(request.params("id"))); DatumRoute getDataTypeByCodeRoute = (request, response) -> - service.getDataTypeByCode(request.params("code")); + dataTypeService.getDataTypeByCode(request.params("code")); ListRoute findSuggestedByEntityRefRoute = (req, res) -> - service.findSuggestedByEntityRef(getEntityReference(req)); + dataTypeService.findSuggestedByEntityRef(getEntityReference(req)); ListRoute findByParentIdRoute = (req, res) -> - service.findByParentId(getId(req)); + dataTypeService.findByParentId(getId(req)); + DatumRoute migrateRoute = (request, response) -> { + ensureUserHasMigrateAdminRights(request); + long sourceDataTypeId = getLong(request, "sourceDataTypeId"); + long targetDataTypeId = getLong(request, "targetDataTypeId"); + boolean removeSource = Boolean.parseBoolean(request.queryParams("removeSource")); + return dataTypeService.migrate(sourceDataTypeId, targetDataTypeId, removeSource); + }; - getForList(BASE_URL, (request, response) -> service.findAll()); + getForList(BASE_URL, (request, response) -> dataTypeService.findAll()); postForList(searchPath, searchRoute); getForDatum(getDataTypeByIdPath, getDataTypeByIdRoute); getForDatum(getDataTypeByCodePath, getDataTypeByCodeRoute); getForList(findSuggestedByEntityRefPath, findSuggestedByEntityRefRoute); getForList(findByParentIdPath, findByParentIdRoute); + postForDatum(migratePath, migrateRoute); + } + + // -- HELPERS --- + + private void ensureUserHasMigrateAdminRights(Request request) { + requireRole(userRoleService, request, SystemRole.ADMIN); }