From f249048f6194a53aa79c87fae9a8ca96d8c7fd7a Mon Sep 17 00:00:00 2001 From: James Welch Date: Wed, 6 Nov 2024 16:23:19 +0000 Subject: [PATCH 1/2] WIP --- .../core/container/FolderService.groovy | 89 ++++++++++++++++--- .../container/VersionedFolderService.groovy | 2 +- .../core/admin/ApiPropertyEnum.groovy | 3 +- .../core/controller/ModelController.groovy | 10 ++- .../core/model/CatalogueItemService.groovy | 14 ++- .../core/model/ModelService.groovy | 59 ++++++------ .../item/datatype/DataTypeController.groovy | 2 +- .../datamodel/DataModelService.groovy | 21 +++-- .../datamodel/item/DataClassService.groovy | 25 +++--- .../datamodel/item/DataElementService.groovy | 7 +- .../item/datatype/DataTypeService.groovy | 15 ++-- .../EnumerationValueService.groovy | 5 +- .../ReferenceDataModelService.groovy | 22 +++-- .../item/ReferenceDataElementService.groovy | 4 +- .../datatype/ReferenceDataTypeService.groovy | 5 +- .../ReferenceEnumerationValueService.groovy | 7 +- .../terminology/CodeSetService.groovy | 6 +- .../terminology/TerminologyService.groovy | 15 ++-- .../terminology/item/TermService.groovy | 5 +- 19 files changed, 218 insertions(+), 98 deletions(-) diff --git a/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/FolderService.groovy b/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/FolderService.groovy index 2152ce975..c5877cea4 100644 --- a/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/FolderService.groovy +++ b/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/FolderService.groovy @@ -30,7 +30,10 @@ import uk.ac.ox.softeng.maurodatamapper.core.diff.bidirectional.ObjectDiff import uk.ac.ox.softeng.maurodatamapper.core.facet.EditService import uk.ac.ox.softeng.maurodatamapper.core.facet.EditTitle import uk.ac.ox.softeng.maurodatamapper.core.facet.Rule +import uk.ac.ox.softeng.maurodatamapper.core.facet.SemanticLink import uk.ac.ox.softeng.maurodatamapper.core.facet.SemanticLinkType +import uk.ac.ox.softeng.maurodatamapper.core.model.CatalogueItem +import uk.ac.ox.softeng.maurodatamapper.core.model.Container import uk.ac.ox.softeng.maurodatamapper.core.model.ContainerService import uk.ac.ox.softeng.maurodatamapper.core.model.CopyPassType import uk.ac.ox.softeng.maurodatamapper.core.model.Model @@ -352,16 +355,18 @@ class FolderService extends ContainerService { UserSecurityPolicyManager userSecurityPolicyManager) { log.debug('Copying folder {}[{}]', original.id, original.label) long start = System.currentTimeMillis() + Map oldNewItemMap = [:] copyFolderPass(CopyPassType.FIRST_PASS, original, copiedFolder, label, copier, copyPermissions, modelBranchName, modelCopyDocVersion, - throwErrors, userSecurityPolicyManager) + throwErrors, userSecurityPolicyManager, oldNewItemMap) sessionFactory.currentSession.flush() if (clearSession) sessionFactory.currentSession.clear() + getAllSemanticLinks(oldNewItemMap, copier) copyFolderPass(CopyPassType.SECOND_PASS, original, copiedFolder, label, copier, copyPermissions, modelBranchName, modelCopyDocVersion, - throwErrors, userSecurityPolicyManager) + throwErrors, userSecurityPolicyManager, oldNewItemMap) sessionFactory.currentSession.flush() if (clearSession) sessionFactory.currentSession.clear() copyFolderPass(CopyPassType.THIRD_PASS, original, copiedFolder, label, copier, copyPermissions, modelBranchName, modelCopyDocVersion, - throwErrors, userSecurityPolicyManager) + throwErrors, userSecurityPolicyManager, oldNewItemMap) log.debug('Folder copy complete in {}', Utils.timeTaken(start)) get(copiedFolder.id) } @@ -370,7 +375,8 @@ class FolderService extends ContainerService { String label, User copier, boolean copyPermissions, String modelBranchName, Version modelCopyDocVersion, boolean throwErrors, - UserSecurityPolicyManager userSecurityPolicyManager) { + UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap) { log.debug('{} performing copy folder pass for {}[{}]', copyPassType, original.id, original.label) long start = System.currentTimeMillis() if (copyPassType == CopyPassType.FIRST_PASS) { @@ -400,7 +406,7 @@ class FolderService extends ContainerService { } else throw new ApiInvalidModelException('FS01', 'Copied Folder is invalid', copiedFolder.errors, messageSource) } copyFolderContents(original, copiedFolder, copier, copyPassType, copyPermissions, modelCopyDocVersion, modelBranchName, throwErrors, - userSecurityPolicyManager) + userSecurityPolicyManager, oldNewItemMap) log.debug('{} folder copy complete for {}[{}] in {}', copyPassType, original.id, original.label, Utils.timeTaken(start)) copiedFolder @@ -437,13 +443,14 @@ class FolderService extends ContainerService { boolean copyPermissions, Version copyDocVersion, String branchName, - boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager) { + boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap) { // If changing label then we need to prefix all the new models so the names dont introduce label conflicts as this situation arises in forking String labelSuffix = folderCopy.label == original.label ? '' : " (${folderCopy.label})" copyModelsInFolder(original, folderCopy, copier, copyPassType, labelSuffix, copyPermissions, copyDocVersion, branchName, - throwErrors, userSecurityPolicyManager) + throwErrors, userSecurityPolicyManager, oldNewItemMap) List folders = findAllByParentId(original.id) log.debug('{} copying {} sub folders inside folder', copyPassType, folders.size()) @@ -459,7 +466,7 @@ class FolderService extends ContainerService { } } copyFolderPass(copyPassType, childFolder, childCopy, childFolder.label, copier, copyPermissions, branchName, copyDocVersion, - throwErrors, userSecurityPolicyManager) + throwErrors, userSecurityPolicyManager, oldNewItemMap) } } @@ -469,7 +476,8 @@ class FolderService extends ContainerService { boolean copyPermissions, Version copyDocVersion, String branchName, - boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager) { + boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, boolean addRefinementLinks = true) { modelServices.each { service -> if (service.countByContainerId(originalFolder.id)) { @@ -489,7 +497,8 @@ class FolderService extends ContainerService { Model copiedModel = service.copyModel(workingModel, workingFolder, copier, copyPermissions, "${workingModel.label}${labelSuffix}", copyDocVersion, branchName, throwErrors, - userSecurityPolicyManager) + userSecurityPolicyManager, oldNewItemMap, addRefinementLinks) + oldNewItemMap[originalModel] = copiedModel log.debug('Validating and saving model copy {}', copiedModel.path) service.validate(copiedModel) if (copiedModel.hasErrors()) { @@ -664,4 +673,64 @@ class FolderService extends ContainerService { if (parentCache) parentCache.addDiffCache(folder.path, fDiffCache) fDiffCache } + + List getAllSemanticLinks(Map oldNewItemMap, User copier) { +/* + + List allContainedFolders = findAllContainersInside(folder.id) + List allModels = [] + modelServices.each {modelService -> + allModels.addAll(modelService.findAllByFolderIdInList(allContainedFolders.id)) + modelService.findAllTreeTypeModelItemsIn() + } + + + + */ + + + log.error('{}', oldNewItemMap) + Map idMap = [:] + oldNewItemMap.keySet().each { + idMap[it.id] = it + } + List semanticLinks = [] + Utils.executeInBatches(oldNewItemMap.keySet().id, {ids -> + semanticLinks.addAll(semanticLinkService.findAllByMultiFacetAwareItemIdInList(ids)) + }) + log.error('{}', semanticLinks.size()) + + List newSemanticLinks = [] + semanticLinks.each {oldSemanticLink -> + UUID oldSourceItemId = oldSemanticLink.multiFacetAwareItemId + UUID oldTargetItemId = oldSemanticLink.targetMultiFacetAwareItemId + + CatalogueItem newSourceItem = oldNewItemMap[idMap[oldSourceItemId]] + + if(idMap[oldTargetItemId]) { + CatalogueItem newTargetItem = oldNewItemMap[idMap[oldTargetItemId]] + + newSemanticLinks.add(semanticLinkService.createSemanticLink(copier, newSourceItem, newTargetItem, oldSemanticLink.linkType)) + +/* + newSourceItem.addToSemanticLinks(createdBy: copier.emailAddress, linkType: oldSemanticLink.linkType, + targetMultiFacetAwareItemId: newTargetItem.id, + targetMultiFacetAwareItemDomainType: newTargetItem.domainType, + unconfirmed: false) +*/ + } else { + newSemanticLinks.add(semanticLinkService.createSemanticLink(copier, newSourceItem, oldSemanticLink.targetMultiFacetAwareItem, oldSemanticLink.linkType)) +/* + newSourceItem.addToSemanticLinks(createdBy: copier.emailAddress, linkType: oldSemanticLink.linkType, + targetMultiFacetAwareItemId: oldSemanticLink.targetMultiFacetAwareItemId, + targetMultiFacetAwareItemDomainType: oldSemanticLink.targetMultiFacetAwareItemDomainType, + unconfirmed: false) +*/ + } + //newSourceItem.save(flush: true, validate: false) + } + System.err.println("Saving semantic links: " + newSemanticLinks.size()) + SemanticLink.saveAll(newSemanticLinks) + newSemanticLinks + } } diff --git a/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/VersionedFolderService.groovy b/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/VersionedFolderService.groovy index 19d54e2b0..993df21d2 100644 --- a/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/VersionedFolderService.groovy +++ b/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/VersionedFolderService.groovy @@ -1308,7 +1308,7 @@ class VersionedFolderService extends ContainerService implement getModelIdentifier(targetVersionedFolder)) as Folder def copiedModel = modelService.copyModelAndValidateAndSave(modelToCopy, parentFolder, userSecurityPolicyManager.user, true, modelToCopy.label, modelToCopy.documentationVersion, - targetVersionedFolder.branchName, false, userSecurityPolicyManager) + targetVersionedFolder.branchName, false, userSecurityPolicyManager, [:]) copiedModel.addMergeEdit(userSecurityPolicyManager.user, mergeEditDescription) } diff --git a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/admin/ApiPropertyEnum.groovy b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/admin/ApiPropertyEnum.groovy index d892c8c02..28f421930 100644 --- a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/admin/ApiPropertyEnum.groovy +++ b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/admin/ApiPropertyEnum.groovy @@ -42,7 +42,8 @@ enum ApiPropertyEnum { SECURITY_RESTRICT_CLASSIFIER_CREATE('security.restrict.classifier.create'), SECURITY_HIDE_EXCEPTIONS('security.hide.exception'), FEATURE_COPY_ANNOTATIONS_TO_NEW_VERSION('feature.copy_annotations_to_new_version'), - FEATURE_ATTACHMENT_SIZE_LIMIT('feature.attachment_size_limit_mb') + FEATURE_ATTACHMENT_SIZE_LIMIT('feature.attachment_size_limit_mb'), + CREATE_REFINEMENT_LINKS_BETWEEN_VERSIONS('feature.create_refinement_links_between_versions') String key diff --git a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/controller/ModelController.groovy b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/controller/ModelController.groovy index 7925012cf..e90a1e2a2 100644 --- a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/controller/ModelController.groovy +++ b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/controller/ModelController.groovy @@ -439,12 +439,12 @@ abstract class ModelController extends CatalogueItemController< AsyncJob asyncJob = getModelService().asyncCreateNewDocumentationVersion(instance, currentUser, createNewVersionData.copyPermissions, - currentUserSecurityPolicyManager) + currentUserSecurityPolicyManager, [:]) return respond(asyncJob, view: '/asyncJob/show', status: HttpStatus.ACCEPTED) } T copy = getModelService(). - createNewDocumentationVersion(instance, currentUser, createNewVersionData.copyPermissions, currentUserSecurityPolicyManager) as T + createNewDocumentationVersion(instance, currentUser, createNewVersionData.copyPermissions, currentUserSecurityPolicyManager, [:]) as T if (!validateResource(copy, 'create')) return @@ -842,6 +842,12 @@ abstract class ModelController extends CatalogueItemController< if (result.any {it.hasErrors()}) { log.debug('Errors found in imported models') + result.each { + if(it.hasErrors()) { + System.err.println(it.label) + System.err.println(it.errors) + } + } transactionStatus.setRollbackOnly() respond(getMultiErrorResponseMap(result), view: '/error', status: UNPROCESSABLE_ENTITY) return diff --git a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/CatalogueItemService.groovy b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/CatalogueItemService.groovy index c109c79cc..bd057c4c9 100644 --- a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/CatalogueItemService.groovy +++ b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/CatalogueItemService.groovy @@ -215,7 +215,10 @@ abstract class CatalogueItemService implements MdmDomai } copy.addToRules(copiedRule) } - semanticLinks.each {link -> + +/* This will be carried out in another pass now + +semanticLinks.each {link -> if (link.targetMultiFacetAwareItem) { copy.addToSemanticLinks(createdBy: copier.emailAddress, linkType: link.linkType, targetMultiFacetAwareItem: link.targetMultiFacetAwareItem, @@ -228,6 +231,8 @@ abstract class CatalogueItemService implements MdmDomai } } + + */ copy } @@ -345,8 +350,11 @@ abstract class CatalogueItemService implements MdmDomai // default no-op } - void setCatalogueItemRefinesCatalogueItem(CatalogueItem source, CatalogueItem target, User catalogueUser) { - source.addToSemanticLinks(linkType: SemanticLinkType.REFINES, createdBy: catalogueUser.emailAddress, targetMultiFacetAwareItem: target) + void setCatalogueItemRefinesCatalogueItem(CatalogueItem source, CatalogueItem target, User catalogueUser, boolean addRefinementLinks = true) { + // Temporarily disable this + if(addRefinementLinks) { + source.addToSemanticLinks(linkType: SemanticLinkType.REFINES, createdBy: catalogueUser.emailAddress, targetMultiFacetAwareItem: target) + } } void checkBreadcrumbTreeAfterSavingCatalogueItem(K catalogueItem) { diff --git a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/ModelService.groovy b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/ModelService.groovy index 0623c6d99..f7994a4b9 100644 --- a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/ModelService.groovy +++ b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/ModelService.groovy @@ -21,6 +21,8 @@ import uk.ac.ox.softeng.maurodatamapper.api.exception.ApiBadRequestException import uk.ac.ox.softeng.maurodatamapper.api.exception.ApiInternalException import uk.ac.ox.softeng.maurodatamapper.api.exception.ApiInvalidModelException import uk.ac.ox.softeng.maurodatamapper.api.exception.ApiNotYetImplementedException +import uk.ac.ox.softeng.maurodatamapper.core.admin.ApiProperty +import uk.ac.ox.softeng.maurodatamapper.core.admin.ApiPropertyEnum import uk.ac.ox.softeng.maurodatamapper.core.async.AsyncJob import uk.ac.ox.softeng.maurodatamapper.core.async.AsyncJobService import uk.ac.ox.softeng.maurodatamapper.core.authority.Authority @@ -178,7 +180,9 @@ abstract class ModelService Version copyDocVersion, String branchName, boolean throwErrors, - UserSecurityPolicyManager userSecurityPolicyManager) + UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, + boolean addRefinementLinks = true) abstract Set getExporterProviderServices() @@ -374,18 +378,21 @@ abstract class ModelService } K copyModelAsNewBranchModel(K original, User copier, boolean copyPermissions, String label, String branchName, boolean throwErrors, - UserSecurityPolicyManager userSecurityPolicyManager) { - copyModel(original, copier, copyPermissions, label, Version.from('1'), branchName, throwErrors, userSecurityPolicyManager) + UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, boolean addRefinementLinks = true) { + copyModel(original, copier, copyPermissions, label, Version.from('1'), branchName, throwErrors, userSecurityPolicyManager, oldNewItemMap, addRefinementLinks) } K copyModelAsNewForkModel(K original, User copier, boolean copyPermissions, String label, boolean throwErrors, - UserSecurityPolicyManager userSecurityPolicyManager) { - copyModel(original, copier, copyPermissions, label, Version.from('1'), original.branchName, throwErrors, userSecurityPolicyManager) + UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, boolean addRefinementLinks = true) { + copyModel(original, copier, copyPermissions, label, Version.from('1'), original.branchName, throwErrors, userSecurityPolicyManager, oldNewItemMap, addRefinementLinks) } K copyModelAsNewDocumentationModel(K original, User copier, boolean copyPermissions, String label, Version copyDocVersion, String branchName, - boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager) { - copyModel(original, copier, copyPermissions, label, copyDocVersion, branchName, throwErrors, userSecurityPolicyManager) + boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, boolean addRefinementLinks = true) { + copyModel(original, copier, copyPermissions, label, copyDocVersion, branchName, throwErrors, userSecurityPolicyManager, oldNewItemMap, addRefinementLinks) } K copyModel(K original, @@ -395,26 +402,29 @@ abstract class ModelService Version copyDocVersion, String branchName, boolean throwErrors, - UserSecurityPolicyManager userSecurityPolicyManager) { + UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, + boolean addRefinementLinks = true) { Folder folder = proxyHandler.unwrapIfProxy(original.folder) as Folder - copyModel(original, folder, copier, copyPermissions, label, copyDocVersion, branchName, throwErrors, userSecurityPolicyManager) + copyModel(original, folder, copier, copyPermissions, label, copyDocVersion, branchName, throwErrors, userSecurityPolicyManager, oldNewItemMap, addRefinementLinks) } AsyncJob asyncCreateNewDocumentationVersion(K model, User user, boolean copyPermissions, - UserSecurityPolicyManager userSecurityPolicyManager, Map additionalArguments = [:]) { + UserSecurityPolicyManager userSecurityPolicyManager, Map additionalArguments = [:], Map oldNewItemMap) { asyncJobService.createAndSaveAsyncJob("Create new documentation model of ${model.path}", userSecurityPolicyManager.user.emailAddress) { model.attach() model.authority.attach() model.folder.attach() K doc = createNewDocumentationVersion(model, user, copyPermissions, - userSecurityPolicyManager, additionalArguments) as K + userSecurityPolicyManager, additionalArguments, oldNewItemMap) as K fullValidateAndSaveOfModel(doc, user) } } K createNewDocumentationVersion(K model, User user, boolean copyPermissions, - UserSecurityPolicyManager userSecurityPolicyManager, Map additionalArguments = [:]) { + UserSecurityPolicyManager userSecurityPolicyManager, Map additionalArguments = [:], + Map oldNewItemMap) { if (!newVersionCreationIsAllowed(model)) return model K newDocVersion = copyModelAsNewDocumentationModel(model, @@ -424,7 +434,7 @@ abstract class ModelService Version.nextMajorVersion(model.documentationVersion), model.branchName, additionalArguments.throwErrors as boolean, - userSecurityPolicyManager,) + userSecurityPolicyManager, oldNewItemMap) setModelIsNewDocumentationVersionOfModel(newDocVersion, model, user) if (additionalArguments.moveDataFlows) { throw new ApiNotYetImplementedException('DMSXX', 'DataModel moving of DataFlows') @@ -450,9 +460,11 @@ abstract class ModelService UserSecurityPolicyManager userSecurityPolicyManager, Map additionalArguments = [:]) { if (!newVersionCreationIsAllowed(model)) return model + ApiProperty createRefinementLinksProperty = apiPropertyService.findByApiPropertyEnum(ApiPropertyEnum.CREATE_REFINEMENT_LINKS_BETWEEN_VERSIONS) + boolean createRefinementLinks = createRefinementLinksProperty?.value?.toBoolean() K newForkModel = copyModelAsNewForkModel(model, user, copyPermissions, label, additionalArguments.throwErrors as boolean, - userSecurityPolicyManager) + userSecurityPolicyManager, [:], createRefinementLinks) setModelIsNewForkModelOfModel(newForkModel, model, user) if (additionalArguments.copyDataFlows) { throw new ApiNotYetImplementedException('DMSXX', 'DataModel copying of DataFlows') @@ -521,7 +533,7 @@ abstract class ModelService model.label, VersionAwareConstraints.DEFAULT_BRANCH_NAME, additionalArguments.throwErrors as boolean, - userSecurityPolicyManager) + userSecurityPolicyManager, [:]) setModelIsNewBranchModelVersionOfModel(newMainBranchModelVersion, model, user) if (additionalArguments.moveDataFlows) { @@ -551,7 +563,7 @@ abstract class ModelService model.label, branchName, additionalArguments.throwErrors as boolean, - userSecurityPolicyManager) + userSecurityPolicyManager, [:]) setModelIsNewBranchModelVersionOfModel(newBranchModelVersion, model, user) @@ -1171,9 +1183,10 @@ abstract class ModelService Version copyDocVersion, String branchName, boolean throwErrors, - UserSecurityPolicyManager userSecurityPolicyManager) { + UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap) { Model copiedModel = copyModel(original, folderToCopyInto, copier, copyPermissions, label, copyDocVersion, - branchName, throwErrors, userSecurityPolicyManager) + branchName, throwErrors, userSecurityPolicyManager, oldNewItemMap) fullValidateAndSaveOfModel(copiedModel, copier) } @@ -1183,15 +1196,7 @@ abstract class ModelService * @param originalModel */ void updateCopiedCrossModelLinks(K copiedModel, K originalModel) { - log.debug('Updating cross model links for [{}]', Path.from(copiedModel)) - - // TODO - // Find all SLs which were copied - // These will all point to the same target as the original model, - // However this method is designed to repoint them to the branched model which exists inside the same VF as this copied model - // ie VF A has Models B & C, VF D is a branch of A with models E & F, if SLs exist from B to C then SLs now exist from E to C - // we need to update them to E to F. - // If a model G exists outside VF A or D with links from B to G then SLs exist from E to G, these remain as they are + } Path getFullPathForModel(Model model) { diff --git a/mdm-plugin-datamodel/grails-app/controllers/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeController.groovy b/mdm-plugin-datamodel/grails-app/controllers/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeController.groovy index 4eaa350a5..d8cc574cf 100644 --- a/mdm-plugin-datamodel/grails-app/controllers/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeController.groovy +++ b/mdm-plugin-datamodel/grails-app/controllers/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeController.groovy @@ -71,7 +71,7 @@ class DataTypeController extends CatalogueItemController { if (!original) return notFound(params.dataTypeId) DataType copy try { - copy = dataTypeService.copyDataType(dataModel, original, currentUser, currentUserSecurityPolicyManager, false, copyInformation) + copy = dataTypeService.copyDataType(dataModel, original, currentUser, currentUserSecurityPolicyManager, false, copyInformation, [:]) } catch (ApiInvalidModelException ex) { transactionStatus.setRollbackOnly() respond ex.errors, view: 'create' // STATUS CODE 422 diff --git a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/DataModelService.groovy b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/DataModelService.groovy index 3e54160e1..29de76213 100644 --- a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/DataModelService.groovy +++ b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/DataModelService.groovy @@ -671,21 +671,24 @@ class DataModelService extends ModelService implements SummaryMetadat @Override DataModel copyModelAsNewForkModel(DataModel original, User copier, boolean copyPermissions, String label, boolean throwErrors, - UserSecurityPolicyManager userSecurityPolicyManager) { + UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, boolean addRefinementLinks = true) { Folder folder = proxyHandler.unwrapIfProxy(original.folder) as Folder copyModel(original, folder, copier, copyPermissions, label, Version.from('1'), original.branchName, throwErrors, - userSecurityPolicyManager, false) + userSecurityPolicyManager, false, oldNewItemMap, addRefinementLinks) } @Override DataModel copyModel(DataModel original, Folder folderToCopyInto, User copier, boolean copyPermissions, String label, Version copyDocVersion, - String branchName, boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager) { + String branchName, boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, boolean addRefinementLinks = true) { copyModel(original, folderToCopyInto, copier, copyPermissions, label, copyDocVersion, branchName, throwErrors, - userSecurityPolicyManager, true) + userSecurityPolicyManager, true, oldNewItemMap, addRefinementLinks) } DataModel copyModel(DataModel original, Folder folderToCopyInto, User copier, boolean copyPermissions, String label, Version copyDocVersion, - String branchName, boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager, boolean copySummaryMetadata) { + String branchName, boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager, boolean copySummaryMetadata, + Map oldNewItemMap, boolean addRefinementLinks = true) { long start = System.currentTimeMillis() log.debug('Creating a new copy of {} with branch name {}', original.label, branchName) DataModel copy = new DataModel(author: original.author, organisation: original.organisation, modelType: original.modelType, finalised: false, @@ -704,7 +707,7 @@ class DataModelService extends ModelService implements SummaryMetadat log.warn('Permission copying is not yet implemented') } - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) if (copy.validate()) { save(copy, validate: false) @@ -723,14 +726,16 @@ class DataModelService extends ModelService implements SummaryMetadat // Copy all the datatypes dataTypes.sort().each {dt -> - dataTypeService.copyDataType(copy, dt, copier, userSecurityPolicyManager, copySummaryMetadata, dataTypeCache) + DataType newDt = dataTypeService.copyDataType(copy, dt, copier, userSecurityPolicyManager, copySummaryMetadata, dataTypeCache, oldNewItemMap) + oldNewItemMap[dt] = newDt } Map oldNewClasses = [:] // Copy all the dataclasses (this will also match up the reference types) rootDataClasses.sort().each {dc -> - DataClass newClass = dataClassService.copyDataClass(copy, dc, copier, userSecurityPolicyManager, null, copySummaryMetadata, dataClassCache) + DataClass newClass = dataClassService.copyDataClass(copy, dc, copier, userSecurityPolicyManager, null, copySummaryMetadata, dataClassCache, oldNewItemMap) oldNewClasses[dc] = newClass + oldNewItemMap[dc] = newClass } diff --git a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataClassService.groovy b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataClassService.groovy index 769f2d863..74046b69f 100644 --- a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataClassService.groovy +++ b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataClassService.groovy @@ -824,7 +824,7 @@ WHERE userSecurityPolicyManager, parentDataClassId ? get(parentDataClassId) : null, false, - copyInformation) + copyInformation, [:]) log.debug('Copied required DataClass, now checking for reference classes which haven\'t been matched or added') matchUpAndAddMissingReferenceTypeClasses(copiedDataModel, original.dataModel, copier, userSecurityPolicyManager) copiedDataClass @@ -834,18 +834,21 @@ WHERE DataClass copy(Model copiedDataModel, DataClass original, CatalogueItem parentDataClass, UserSecurityPolicyManager userSecurityPolicyManager) { copyDataClass(copiedDataModel as DataModel, original, userSecurityPolicyManager.user, userSecurityPolicyManager, parentDataClass as DataClass, - false, null) + false, null, [:]) } - DataClass copyDataClass(DataModel copiedDataModel, DataClass original, User copier, UserSecurityPolicyManager userSecurityPolicyManager) { - copyDataClass(copiedDataModel, original, copier, userSecurityPolicyManager, null, false, null) + DataClass copyDataClass(DataModel copiedDataModel, DataClass original, User copier, UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap) { + copyDataClass(copiedDataModel, original, copier, userSecurityPolicyManager, null, false, null, oldNewItemMap) } DataClass copyDataClass(DataModel copiedDataModel, DataClass original, User copier, UserSecurityPolicyManager userSecurityPolicyManager, DataClass parentDataClass, boolean copySummaryMetadata, - CopyInformation copyInformation) { + CopyInformation copyInformation, + Map oldNewItemMap, + boolean addRefinementLinks = true) { if (!original) throw new ApiInternalException('DCSXX', 'Cannot copy non-existent DataClass') @@ -855,7 +858,7 @@ WHERE ) copy = copyModelItemInformation(original, copy, copier, userSecurityPolicyManager, copySummaryMetadata, copyInformation) - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) copiedDataModel.addToDataClasses(copy) @@ -882,16 +885,18 @@ WHERE List dataClasses = DataClass.byParentDataClassId(original.id).join('classifiers').list() CopyInformation dataClassCache = cacheFacetInformationForCopy(dataClasses.collect {it.id}, new CopyInformation(copyIndex: true)) dataClasses.sort().each {child -> - copyDataClass(copiedDataModel, child, copier, userSecurityPolicyManager, copy, copySummaryMetadata, dataClassCache) + DataClass newDC = copyDataClass(copiedDataModel, child, copier, userSecurityPolicyManager, copy, copySummaryMetadata, dataClassCache, oldNewItemMap) + oldNewItemMap[child] = newDC } copy.dataElements = [] List dataElements = DataElement.byDataClassId(original.id).join('classifiers').list() CopyInformation dataElementCache = cacheFacetInformationForCopy(dataElements.collect {it.id}, new CopyInformation(copyIndex: true)) dataElements.sort().each {element -> - copy.addToDataElements( - dataElementService - .copyDataElement(copiedDataModel, element, copier, userSecurityPolicyManager, copySummaryMetadata, dataElementCache)) + DataElement newDe = dataElementService + .copyDataElement(copiedDataModel, element, copier, userSecurityPolicyManager, copySummaryMetadata, dataElementCache) + copy.addToDataElements(newDe) + oldNewItemMap[element] = newDe } List importedDataClasses = findAllByImportingDataClassId(original.id) diff --git a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataElementService.groovy b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataElementService.groovy index 64b5aad38..9f45f8b02 100644 --- a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataElementService.groovy +++ b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataElementService.groovy @@ -414,19 +414,20 @@ WHERE (de.dataClass.dataModel.id = :dataModelId)''', 'de', filters) DataElement copyDataElement(DataModel copiedDataModel, DataElement original, User copier, UserSecurityPolicyManager userSecurityPolicyManager, boolean copySummaryMetadata = false, - CopyInformation copyInformation = new CopyInformation()) { + CopyInformation copyInformation = new CopyInformation(), + boolean addRefinementLinks = true) { DataElement copy = new DataElement(minMultiplicity: original.minMultiplicity, maxMultiplicity: original.maxMultiplicity) copy = copyModelItemInformation(original, copy, copier, userSecurityPolicyManager, copySummaryMetadata, copyInformation) - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) DataType dataType = copiedDataModel.findDataTypeByLabel(original.dataType.label) // If theres no DataType then copy the original's DataType into the DataModel if (!dataType) { dataType = dataTypeService.copyDataType(copiedDataModel, original.dataType, copier, - userSecurityPolicyManager) + userSecurityPolicyManager, [:]) } dataType.addToDataElements(copy) diff --git a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeService.groovy b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeService.groovy index 0c2e48644..acc2eee5b 100644 --- a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeService.groovy +++ b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeService.groovy @@ -35,6 +35,7 @@ import uk.ac.ox.softeng.maurodatamapper.datamodel.item.DataClass import uk.ac.ox.softeng.maurodatamapper.datamodel.item.DataClassService import uk.ac.ox.softeng.maurodatamapper.datamodel.item.DataElement import uk.ac.ox.softeng.maurodatamapper.datamodel.item.DataElementService +import uk.ac.ox.softeng.maurodatamapper.datamodel.item.datatype.enumeration.EnumerationValue import uk.ac.ox.softeng.maurodatamapper.datamodel.item.datatype.enumeration.EnumerationValueService import uk.ac.ox.softeng.maurodatamapper.datamodel.provider.DefaultDataTypeProvider import uk.ac.ox.softeng.maurodatamapper.datamodel.rest.transport.DefaultDataType @@ -436,23 +437,24 @@ WHERE @Override DataType copy(Model copiedDataModel, DataType original, CatalogueItem nonModelParent, UserSecurityPolicyManager userSecurityPolicyManager) { - copyDataType(copiedDataModel as DataModel, original, userSecurityPolicyManager.user, userSecurityPolicyManager) + copyDataType(copiedDataModel as DataModel, original, userSecurityPolicyManager.user, userSecurityPolicyManager, [:]) } DataType copyDataType(DataModel copiedDataModel, DataType original, User copier, UserSecurityPolicyManager userSecurityPolicyManager, - boolean copySummaryMetadata = false, CopyInformation copyInformation = new CopyInformation()) { + boolean copySummaryMetadata = false, CopyInformation copyInformation = new CopyInformation(), + Map oldNewItemMap, boolean addRefinementLinks = true) { - DataType copy = createNewDataTypeFromOriginal(copiedDataModel, original, userSecurityPolicyManager) + DataType copy = createNewDataTypeFromOriginal(copiedDataModel, original, userSecurityPolicyManager, oldNewItemMap) copy = copyModelItemInformation(original, copy, copier, userSecurityPolicyManager, copySummaryMetadata, copyInformation) - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) copiedDataModel.addToDataTypes(copy) copy } - DataType createNewDataTypeFromOriginal(DataModel copiedDataModel, DataType original, UserSecurityPolicyManager userSecurityPolicyManager) { + DataType createNewDataTypeFromOriginal(DataModel copiedDataModel, DataType original, UserSecurityPolicyManager userSecurityPolicyManager, Map oldNewItemMap) { DataType copy String domainType = original.domainType @@ -464,8 +466,9 @@ WHERE copy = new EnumerationType() CopyInformation copyInformation = new CopyInformation(copyIndex: true) original.enumerationValues.sort().each {ev -> - copy.addToEnumerationValues( + EnumerationValue newEv = copy.addToEnumerationValues( enumerationValueService.copyEnumerationValue(copiedDataModel, ev, copy, userSecurityPolicyManager.user, userSecurityPolicyManager, copyInformation)) + oldNewItemMap[ev] = newEv } break case DataType.REFERENCE_DOMAIN_TYPE: diff --git a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/enumeration/EnumerationValueService.groovy b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/enumeration/EnumerationValueService.groovy index 72075b485..09cdabc7d 100644 --- a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/enumeration/EnumerationValueService.groovy +++ b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/enumeration/EnumerationValueService.groovy @@ -183,11 +183,12 @@ class EnumerationValueService extends ModelItemService impleme } EnumerationValue copyEnumerationValue(DataModel copiedDataModel, EnumerationValue original, EnumerationType enumerationTypeToCopyInto, - User copier, UserSecurityPolicyManager userSecurityPolicyManager, CopyInformation copyInformation = null) { + User copier, UserSecurityPolicyManager userSecurityPolicyManager, CopyInformation copyInformation = null, + boolean addRefinementLinks = true) { EnumerationValue copy = new EnumerationValue(key: original.key, value: original.value, category: original.category) copy = copyModelItemInformation(original, copy, copier, userSecurityPolicyManager, copyInformation) - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) EnumerationType enumerationType = enumerationTypeToCopyInto ?: copiedDataModel.findEnumerationTypeByLabel(original.enumerationType.label) enumerationType.addToEnumerationValues(copy) diff --git a/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/ReferenceDataModelService.groovy b/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/ReferenceDataModelService.groovy index a956a35d8..0462b428f 100644 --- a/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/ReferenceDataModelService.groovy +++ b/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/ReferenceDataModelService.groovy @@ -72,6 +72,7 @@ import org.hibernate.search.mapper.orm.session.SearchSession import org.springframework.beans.factory.annotation.Autowired import java.time.OffsetDateTime +import javax.xml.catalog.Catalog @Slf4j @Transactional @@ -445,22 +446,25 @@ class ReferenceDataModelService extends ModelService impleme } ReferenceDataModel copyModelAsNewForkModel(ReferenceDataModel original, User copier, boolean copyPermissions, String label, boolean throwErrors, - UserSecurityPolicyManager userSecurityPolicyManager) { + UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, boolean addRefinementLinks = true) { Folder folder = proxyHandler.unwrapIfProxy(original.folder) as Folder copyModel(original, folder, copier, copyPermissions, label, Version.from('1'), original.branchName, throwErrors, userSecurityPolicyManager, - false) + false, oldNewItemMap, addRefinementLinks) } ReferenceDataModel copyModel(ReferenceDataModel original, Folder folderToCopyTo, User copier, boolean copyPermissions, String label, Version copyDocVersion, String branchName, boolean throwErrors, - UserSecurityPolicyManager userSecurityPolicyManager) { - copyModel(original, folderToCopyTo, copier, copyPermissions, label, copyDocVersion, branchName, throwErrors, userSecurityPolicyManager, true) + UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, boolean addRefinementLinks = true) { + copyModel(original, folderToCopyTo, copier, copyPermissions, label, copyDocVersion, branchName, throwErrors, userSecurityPolicyManager, true, oldNewItemMap, addRefinementLinks) } ReferenceDataModel copyModel(ReferenceDataModel original, Folder folderToCopyInto, User copier, boolean copyPermissions, String label, Version copyDocVersion, String branchName, - boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager, boolean copySummaryMetadata) { + boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager, boolean copySummaryMetadata, + Map oldNewItemMap, boolean addRefinementLinks = true) { ReferenceDataModel copy = new ReferenceDataModel(author: original.author, organisation: original.organisation, modelType: original.modelType, finalised: false, @@ -480,7 +484,7 @@ class ReferenceDataModelService extends ModelService impleme } - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) if (copy.validate()) { save(copy, validate: false) @@ -496,7 +500,8 @@ class ReferenceDataModelService extends ModelService impleme if (original.referenceDataTypes) { // Copy all the referencedatatypes original.referenceDataTypes.sort().each {dt -> - referenceDataTypeService.copyReferenceDataType(copy, dt, copier, userSecurityPolicyManager, copySummaryMetadata, referenceDataTypeCopyInformation) + ReferenceDataType newRdt = referenceDataTypeService.copyReferenceDataType(copy, dt, copier, userSecurityPolicyManager, copySummaryMetadata, referenceDataTypeCopyInformation) + oldNewItemMap[dt] = newRdt } } @@ -505,7 +510,8 @@ class ReferenceDataModelService extends ModelService impleme // Copy all the referencedataelements original.referenceDataElements.sort().each {de -> log.debug("copy element ${de}") - referenceDataElementService.copyReferenceDataElement(copy, de, copier, userSecurityPolicyManager, copySummaryMetadata, referenceDataElementCopyInformation) + ReferenceDataElement newRde = referenceDataElementService.copyReferenceDataElement(copy, de, copier, userSecurityPolicyManager, copySummaryMetadata, referenceDataElementCopyInformation) + oldNewItemMap[de] = newRde } } diff --git a/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/ReferenceDataElementService.groovy b/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/ReferenceDataElementService.groovy index 1242b3fa1..6607be786 100644 --- a/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/ReferenceDataElementService.groovy +++ b/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/ReferenceDataElementService.groovy @@ -265,12 +265,12 @@ class ReferenceDataElementService extends ModelItemService ReferenceDataElement copyReferenceDataElement(ReferenceDataModel copiedReferenceDataModel, ReferenceDataElement original, User copier, UserSecurityPolicyManager userSecurityPolicyManager, boolean copySummaryMetadata = false, - CopyInformation copyInformation = null) { + CopyInformation copyInformation = null, boolean addRefinementLinks = true) { ReferenceDataElement copy = new ReferenceDataElement(minMultiplicity: original.minMultiplicity, maxMultiplicity: original.maxMultiplicity) copy = copyModelItemInformation(original, copy, copier, userSecurityPolicyManager, copySummaryMetadata, copyInformation) - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) ReferenceDataType referenceDataType = copiedReferenceDataModel.findReferenceDataTypeByLabel(original.referenceDataType.label) diff --git a/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/datatype/ReferenceDataTypeService.groovy b/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/datatype/ReferenceDataTypeService.groovy index c6e7a6e0f..e23228822 100644 --- a/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/datatype/ReferenceDataTypeService.groovy +++ b/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/datatype/ReferenceDataTypeService.groovy @@ -213,7 +213,8 @@ class ReferenceDataTypeService extends ModelItemService imple } ReferenceDataType copyReferenceDataType(ReferenceDataModel copiedReferenceDataModel, ReferenceDataType original, User copier, - UserSecurityPolicyManager userSecurityPolicyManager, boolean copySummaryMetadata = false, CopyInformation copyInformation = null) { + UserSecurityPolicyManager userSecurityPolicyManager, boolean copySummaryMetadata = false, CopyInformation copyInformation = null, + boolean addRefinementLinks = true) { ReferenceDataType copy String domainType = original.domainType @@ -236,7 +237,7 @@ class ReferenceDataTypeService extends ModelItemService imple } copy = copyModelItemInformation(original, copy, copier, userSecurityPolicyManager, copySummaryMetadata, copyInformation) - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) copiedReferenceDataModel.addToReferenceDataTypes(copy) diff --git a/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/datatype/enumeration/ReferenceEnumerationValueService.groovy b/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/datatype/enumeration/ReferenceEnumerationValueService.groovy index dc92e10ae..b2c98236f 100644 --- a/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/datatype/enumeration/ReferenceEnumerationValueService.groovy +++ b/mdm-plugin-referencedata/grails-app/services/uk/ac/ox/softeng/maurodatamapper/referencedata/item/datatype/enumeration/ReferenceEnumerationValueService.groovy @@ -148,14 +148,15 @@ class ReferenceEnumerationValueService extends ModelItemService { } CodeSet copyModel(CodeSet original, Folder folderToCopyTo, User copier, boolean copyPermissions, String label, Version copyDocVersion, - String branchName, boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager) { + String branchName, boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, boolean addRefinementLinks = true) { long start = System.currentTimeMillis() log.debug('Creating a new copy of {} with branch name {}', original.label, branchName) CodeSet copy = new CodeSet(author: original.author, @@ -241,7 +243,7 @@ class CodeSetService extends ModelService { } - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) if (copy.validate()) { save(copy, validate: false) diff --git a/mdm-plugin-terminology/grails-app/services/uk/ac/ox/softeng/maurodatamapper/terminology/TerminologyService.groovy b/mdm-plugin-terminology/grails-app/services/uk/ac/ox/softeng/maurodatamapper/terminology/TerminologyService.groovy index 44c0e4511..cdb04c94f 100644 --- a/mdm-plugin-terminology/grails-app/services/uk/ac/ox/softeng/maurodatamapper/terminology/TerminologyService.groovy +++ b/mdm-plugin-terminology/grails-app/services/uk/ac/ox/softeng/maurodatamapper/terminology/TerminologyService.groovy @@ -27,6 +27,7 @@ import uk.ac.ox.softeng.maurodatamapper.core.diff.CachedDiffable import uk.ac.ox.softeng.maurodatamapper.core.diff.DiffCache import uk.ac.ox.softeng.maurodatamapper.core.diff.Diffable import uk.ac.ox.softeng.maurodatamapper.core.facet.EditTitle +import uk.ac.ox.softeng.maurodatamapper.core.model.CatalogueItem import uk.ac.ox.softeng.maurodatamapper.core.model.Container import uk.ac.ox.softeng.maurodatamapper.core.model.Model import uk.ac.ox.softeng.maurodatamapper.core.model.ModelItem @@ -436,7 +437,8 @@ class TerminologyService extends ModelService { } Terminology copyModel(Terminology original, Folder folderToCopyTo, User copier, boolean copyPermissions, String label, Version copyVersion, - String branchName, boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager) { + String branchName, boolean throwErrors, UserSecurityPolicyManager userSecurityPolicyManager, + Map oldNewItemMap, boolean addRefinementLinks = true) { long start = System.currentTimeMillis() log.debug('Creating a new copy of {} with branch name {}', original.label, branchName) Terminology copy = new Terminology(author: original.author, @@ -454,7 +456,7 @@ class TerminologyService extends ModelService { log.warn('Permission copying is not yet implemented') } - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) if (copy.validate()) { save(copy, validate: false) @@ -480,19 +482,22 @@ class TerminologyService extends ModelService { // Copy all the TermRelationshipType termRelationshipTypes.each {trt -> - termRelationshipTypeService.copyTermRelationshipType(copy, trt, copier) + TermRelationshipType newTrt = termRelationshipTypeService.copyTermRelationshipType(copy, trt, copier) + oldNewItemMap[trt] = newTrt } // Copy all the terms originalTerms.each {term -> - termService.copyTerm(copy, term, copier, userSecurityPolicyManager, termsCachedInformation) + Term newTerm = termService.copyTerm(copy, term, copier, userSecurityPolicyManager, termsCachedInformation) + oldNewItemMap[term] = newTerm } // Copy all the term relationships // We need all the terms to exist so we can create the links // Only copy source relationships as this will propagate the target relationships termRelationships.each {relationship -> - termRelationshipService.copyTermRelationship(copy, relationship, new TreeMap(copy.terms.collectEntries {[it.code, it]}), copier) + TermRelationship newTr = termRelationshipService.copyTermRelationship(copy, relationship, new TreeMap(copy.terms.collectEntries {[it.code, it]}), copier) + oldNewItemMap[relationship] = newTr } log.debug('Copy of terminology took {}', Utils.timeTaken(start)) copy diff --git a/mdm-plugin-terminology/grails-app/services/uk/ac/ox/softeng/maurodatamapper/terminology/item/TermService.groovy b/mdm-plugin-terminology/grails-app/services/uk/ac/ox/softeng/maurodatamapper/terminology/item/TermService.groovy index f8e9105f1..da374d51c 100644 --- a/mdm-plugin-terminology/grails-app/services/uk/ac/ox/softeng/maurodatamapper/terminology/item/TermService.groovy +++ b/mdm-plugin-terminology/grails-app/services/uk/ac/ox/softeng/maurodatamapper/terminology/item/TermService.groovy @@ -153,6 +153,7 @@ class TermService extends ModelItemService { } List findAllByTerminologyId(UUID terminologyId, Map paginate = [:]) { + System.err.println(paginate) Term.withFilter(Term.byTerminologyId(terminologyId), paginate).list(paginate) } @@ -212,13 +213,13 @@ class TermService extends ModelItemService { copy } - Term copyTerm(Term original, User copier, UserSecurityPolicyManager userSecurityPolicyManager, CopyInformation copyInformation = null) { + Term copyTerm(Term original, User copier, UserSecurityPolicyManager userSecurityPolicyManager, CopyInformation copyInformation = null, boolean addRefinementLinks = true) { if (!original) throw new ApiInternalException('DCSXX', 'Cannot copy non-existent Term') Term copy = new Term(createdBy: copier.emailAddress, code: original.code, definition: original.definition, url: original.url, isParent: original.isParent, depth: original.depth) copy = copyCatalogueItemInformation(original, copy, copier, userSecurityPolicyManager, copyInformation) - setCatalogueItemRefinesCatalogueItem(copy, original, copier) + setCatalogueItemRefinesCatalogueItem(copy, original, copier, addRefinementLinks) copy } From a41868306f0e064ecaad4eb3307ccd0147998524 Mon Sep 17 00:00:00 2001 From: James Welch Date: Thu, 7 Nov 2024 22:27:40 +0000 Subject: [PATCH 2/2] Fixes for failing tests --- .../core/container/FolderService.groovy | 39 ++++--------------- .../core/admin/ApiPropertyEnum.groovy | 2 +- .../core/model/ModelService.groovy | 2 +- .../item/datatype/DataTypeService.groovy | 5 ++- .../DataModelServiceIntegrationSpec.groovy | 6 +-- .../DataClassServiceIntegrationSpec.groovy | 12 +++--- .../item/datatype/DataTypeServiceSpec.groovy | 6 +-- .../admin/ApiPropertyFunctionalSpec.groovy | 9 +++-- 8 files changed, 31 insertions(+), 50 deletions(-) diff --git a/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/FolderService.groovy b/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/FolderService.groovy index c5877cea4..0712dd8ad 100644 --- a/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/FolderService.groovy +++ b/mdm-core/grails-app/services/uk/ac/ox/softeng/maurodatamapper/core/container/FolderService.groovy @@ -675,20 +675,6 @@ class FolderService extends ContainerService { } List getAllSemanticLinks(Map oldNewItemMap, User copier) { -/* - - List allContainedFolders = findAllContainersInside(folder.id) - List allModels = [] - modelServices.each {modelService -> - allModels.addAll(modelService.findAllByFolderIdInList(allContainedFolders.id)) - modelService.findAllTreeTypeModelItemsIn() - } - - - - */ - - log.error('{}', oldNewItemMap) Map idMap = [:] oldNewItemMap.keySet().each { @@ -709,27 +695,18 @@ class FolderService extends ContainerService { if(idMap[oldTargetItemId]) { CatalogueItem newTargetItem = oldNewItemMap[idMap[oldTargetItemId]] - newSemanticLinks.add(semanticLinkService.createSemanticLink(copier, newSourceItem, newTargetItem, oldSemanticLink.linkType)) - -/* - newSourceItem.addToSemanticLinks(createdBy: copier.emailAddress, linkType: oldSemanticLink.linkType, - targetMultiFacetAwareItemId: newTargetItem.id, - targetMultiFacetAwareItemDomainType: newTargetItem.domainType, - unconfirmed: false) -*/ } else { - newSemanticLinks.add(semanticLinkService.createSemanticLink(copier, newSourceItem, oldSemanticLink.targetMultiFacetAwareItem, oldSemanticLink.linkType)) -/* - newSourceItem.addToSemanticLinks(createdBy: copier.emailAddress, linkType: oldSemanticLink.linkType, - targetMultiFacetAwareItemId: oldSemanticLink.targetMultiFacetAwareItemId, - targetMultiFacetAwareItemDomainType: oldSemanticLink.targetMultiFacetAwareItemDomainType, - unconfirmed: false) -*/ + newSemanticLinks.add(new SemanticLink(createdBy: copier.emailAddress, linkType: oldSemanticLink.linkType, + targetMultiFacetAwareItemId: oldSemanticLink.targetMultiFacetAwareItemId, + targetMultiFacetAwareItemDomainType: oldSemanticLink.targetMultiFacetAwareItemDomainType, + ).with { + setMultiFacetAwareItem(newSourceItem) + it + }) + } - //newSourceItem.save(flush: true, validate: false) } - System.err.println("Saving semantic links: " + newSemanticLinks.size()) SemanticLink.saveAll(newSemanticLinks) newSemanticLinks } diff --git a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/admin/ApiPropertyEnum.groovy b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/admin/ApiPropertyEnum.groovy index 28f421930..463e66f0b 100644 --- a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/admin/ApiPropertyEnum.groovy +++ b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/admin/ApiPropertyEnum.groovy @@ -43,7 +43,7 @@ enum ApiPropertyEnum { SECURITY_HIDE_EXCEPTIONS('security.hide.exception'), FEATURE_COPY_ANNOTATIONS_TO_NEW_VERSION('feature.copy_annotations_to_new_version'), FEATURE_ATTACHMENT_SIZE_LIMIT('feature.attachment_size_limit_mb'), - CREATE_REFINEMENT_LINKS_BETWEEN_VERSIONS('feature.create_refinement_links_between_versions') + FEATURE_CREATE_REFINEMENT_LINKS_BETWEEN_VERSIONS('feature.create_refinement_links') String key diff --git a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/ModelService.groovy b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/ModelService.groovy index f7994a4b9..d3b62c2f2 100644 --- a/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/ModelService.groovy +++ b/mdm-core/src/main/groovy/uk/ac/ox/softeng/maurodatamapper/core/model/ModelService.groovy @@ -460,7 +460,7 @@ abstract class ModelService UserSecurityPolicyManager userSecurityPolicyManager, Map additionalArguments = [:]) { if (!newVersionCreationIsAllowed(model)) return model - ApiProperty createRefinementLinksProperty = apiPropertyService.findByApiPropertyEnum(ApiPropertyEnum.CREATE_REFINEMENT_LINKS_BETWEEN_VERSIONS) + ApiProperty createRefinementLinksProperty = apiPropertyService.findByApiPropertyEnum(ApiPropertyEnum.FEATURE_CREATE_REFINEMENT_LINKS_BETWEEN_VERSIONS) boolean createRefinementLinks = createRefinementLinksProperty?.value?.toBoolean() K newForkModel = copyModelAsNewForkModel(model, user, copyPermissions, label, additionalArguments.throwErrors as boolean, diff --git a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeService.groovy b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeService.groovy index acc2eee5b..017225373 100644 --- a/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeService.groovy +++ b/mdm-plugin-datamodel/grails-app/services/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeService.groovy @@ -466,8 +466,9 @@ WHERE copy = new EnumerationType() CopyInformation copyInformation = new CopyInformation(copyIndex: true) original.enumerationValues.sort().each {ev -> - EnumerationValue newEv = copy.addToEnumerationValues( - enumerationValueService.copyEnumerationValue(copiedDataModel, ev, copy, userSecurityPolicyManager.user, userSecurityPolicyManager, copyInformation)) + EnumerationValue newEv = + enumerationValueService.copyEnumerationValue(copiedDataModel, ev, copy, userSecurityPolicyManager.user, userSecurityPolicyManager, copyInformation) + copy.addToEnumerationValues(newEv) oldNewItemMap[ev] = newEv } break diff --git a/mdm-plugin-datamodel/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/DataModelServiceIntegrationSpec.groovy b/mdm-plugin-datamodel/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/DataModelServiceIntegrationSpec.groovy index 0a37961f1..3b184125b 100644 --- a/mdm-plugin-datamodel/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/DataModelServiceIntegrationSpec.groovy +++ b/mdm-plugin-datamodel/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/DataModelServiceIntegrationSpec.groovy @@ -205,7 +205,7 @@ class DataModelServiceIntegrationSpec extends BaseDataModelIntegrationSpec { } protected UUID createAndSaveNewBranchModel(String branchName, DataModel base) { - DataModel dataModel = dataModelService.createNewBranchModelVersion(branchName, base, admin, false, adminSecurityPolicyManager) + DataModel dataModel = dataModelService.createNewBranchModelVersion(branchName, base, admin, false, adminSecurityPolicyManager, [:]) if (dataModel.hasErrors()) { GormUtils.outputDomainErrors(messageSource, dataModel) Assert.fail('Could not create new branch version') @@ -429,7 +429,7 @@ class DataModelServiceIntegrationSpec extends BaseDataModelIntegrationSpec { def result = dataModelService.createNewDocumentationVersion(dataModel, editor, true, editorSecurityPolicyManager, [ moveDataFlows: false, throwErrors : true - ]) + ], [:]) then: checkAndSaveNewVersion(result) @@ -927,7 +927,7 @@ class DataModelServiceIntegrationSpec extends BaseDataModelIntegrationSpec { DataModel copiedDataModel = dataModelService .copyModel(dataModel, testFolder, editor, false, dataModel.label + ' copy', Version.from('1'), dataModel.branchName, true, - editorSecurityPolicyManager) + editorSecurityPolicyManager, [:]) then: copiedDataModel.childDataClasses.size() == 5 diff --git a/mdm-plugin-datamodel/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataClassServiceIntegrationSpec.groovy b/mdm-plugin-datamodel/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataClassServiceIntegrationSpec.groovy index b28f7f8f6..de8a14012 100644 --- a/mdm-plugin-datamodel/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataClassServiceIntegrationSpec.groovy +++ b/mdm-plugin-datamodel/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/item/DataClassServiceIntegrationSpec.groovy @@ -336,7 +336,7 @@ class DataClassServiceIntegrationSpec extends BaseDataModelIntegrationSpec { when: DataClass original = dataClassService.get(vsimple.id) - DataClass copy = dataClassService.copyDataClass(copyModel, original, editor, userSecurityPolicyManager) + DataClass copy = dataClassService.copyDataClass(copyModel, original, editor, userSecurityPolicyManager, [:]) then: checkAndSave(copyModel) @@ -389,7 +389,7 @@ class DataClassServiceIntegrationSpec extends BaseDataModelIntegrationSpec { when: DataClass original = dataClassService.get(content.id) - DataClass copy = dataClassService.copyDataClass(copyModel, original, editor, userSecurityPolicyManager) + DataClass copy = dataClassService.copyDataClass(copyModel, original, editor, userSecurityPolicyManager, [:]) then: checkAndSave(copyModel) @@ -453,7 +453,7 @@ class DataClassServiceIntegrationSpec extends BaseDataModelIntegrationSpec { DataModel copyModel = new DataModel(label: 'copy', createdBy: StandardEmailAddress.INTEGRATION_TEST, folder: testFolder, authority: testAuthority) checkAndSave(copyModel) sessionFactory.currentSession.flush() - dataClassService.copyDataClass(copyModel, dataModel.childDataClasses.find {it.label == 'dc1'}, editor, userSecurityPolicyManager) + dataClassService.copyDataClass(copyModel, dataModel.childDataClasses.find {it.label == 'dc1'}, editor, userSecurityPolicyManager, [:]) expect: check(copyModel) @@ -464,7 +464,7 @@ class DataClassServiceIntegrationSpec extends BaseDataModelIntegrationSpec { sessionFactory.currentSession.clear() copyModel = dataModelService.get(copyModel.id) DataClass original = dataClassService.get(complex.id) - DataClass copy = dataClassService.copyDataClass(copyModel, original, editor, userSecurityPolicyManager) + DataClass copy = dataClassService.copyDataClass(copyModel, original, editor, userSecurityPolicyManager, [:]) then: check(copyModel) @@ -554,7 +554,7 @@ class DataClassServiceIntegrationSpec extends BaseDataModelIntegrationSpec { when: DataClass original = dataClassService.get(parentClass.id) - dataClassService.copyDataClass(copyModel, original, editor, userSecurityPolicyManager) + dataClassService.copyDataClass(copyModel, original, editor, userSecurityPolicyManager, [:]) then: checkAndSave(copyModel) @@ -602,7 +602,7 @@ class DataClassServiceIntegrationSpec extends BaseDataModelIntegrationSpec { when: DataClass original = parentClass.dataClasses.sort().first() - dataClassService.copyDataClass(dataModel, original, editor, userSecurityPolicyManager, parentClass, false, new CopyInformation(copyLabel: 'Child Copied Class')) + dataClassService.copyDataClass(dataModel, original, editor, userSecurityPolicyManager, parentClass, false, new CopyInformation(copyLabel: 'Child Copied Class'), [:]) then: original.idx == 0 diff --git a/mdm-plugin-datamodel/src/test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeServiceSpec.groovy b/mdm-plugin-datamodel/src/test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeServiceSpec.groovy index 56fe77f22..a92a5194b 100644 --- a/mdm-plugin-datamodel/src/test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeServiceSpec.groovy +++ b/mdm-plugin-datamodel/src/test/groovy/uk/ac/ox/softeng/maurodatamapper/datamodel/item/datatype/DataTypeServiceSpec.groovy @@ -191,7 +191,7 @@ class DataTypeServiceSpec extends CatalogueItemServiceSpec implements ServiceUni checkAndSave(copyModel) when: - DataType copy = service.copyDataType(copyModel, original, editor, userSecurityPolicyManager) + DataType copy = service.copyDataType(copyModel, original, editor, userSecurityPolicyManager, [:]) then: checkAndSave(copyModel) @@ -225,7 +225,7 @@ class DataTypeServiceSpec extends CatalogueItemServiceSpec implements ServiceUni checkAndSave(copyModel) when: - DataType copy = service.copyDataType(copyModel, original, editor, userSecurityPolicyManager) + DataType copy = service.copyDataType(copyModel, original, editor, userSecurityPolicyManager, [:]) then: checkAndSave(copyModel) @@ -262,7 +262,7 @@ class DataTypeServiceSpec extends CatalogueItemServiceSpec implements ServiceUni checkAndSave(copyModel) when: - DataType copy = service.copyDataType(copyModel, original, editor, userSecurityPolicyManager) + DataType copy = service.copyDataType(copyModel, original, editor, userSecurityPolicyManager, [:]) checkAndSave(copyModel) then: diff --git a/mdm-testing-functional/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/testing/functional/core/admin/ApiPropertyFunctionalSpec.groovy b/mdm-testing-functional/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/testing/functional/core/admin/ApiPropertyFunctionalSpec.groovy index 303245337..eb088671e 100644 --- a/mdm-testing-functional/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/testing/functional/core/admin/ApiPropertyFunctionalSpec.groovy +++ b/mdm-testing-functional/src/integration-test/groovy/uk/ac/ox/softeng/maurodatamapper/testing/functional/core/admin/ApiPropertyFunctionalSpec.groovy @@ -223,7 +223,8 @@ class ApiPropertyFunctionalSpec extends FunctionalSpec implements CsvComparer, X ApiPropertyEnum.SECURITY_RESTRICT_ROOT_FOLDER, ApiPropertyEnum.SECURITY_HIDE_EXCEPTIONS, ApiPropertyEnum.FEATURE_COPY_ANNOTATIONS_TO_NEW_VERSION, - ApiPropertyEnum.FEATURE_ATTACHMENT_SIZE_LIMIT + ApiPropertyEnum.FEATURE_ATTACHMENT_SIZE_LIMIT, + ApiPropertyEnum.FEATURE_CREATE_REFINEMENT_LINKS_BETWEEN_VERSIONS ]) } .each {ape -> @@ -245,7 +246,8 @@ class ApiPropertyFunctionalSpec extends FunctionalSpec implements CsvComparer, X ApiPropertyEnum.SECURITY_RESTRICT_ROOT_FOLDER, ApiPropertyEnum.SECURITY_HIDE_EXCEPTIONS, ApiPropertyEnum.FEATURE_COPY_ANNOTATIONS_TO_NEW_VERSION, - ApiPropertyEnum.FEATURE_ATTACHMENT_SIZE_LIMIT + ApiPropertyEnum.FEATURE_ATTACHMENT_SIZE_LIMIT, + ApiPropertyEnum.FEATURE_CREATE_REFINEMENT_LINKS_BETWEEN_VERSIONS ]) } .each {ape -> @@ -272,7 +274,8 @@ class ApiPropertyFunctionalSpec extends FunctionalSpec implements CsvComparer, X ApiPropertyEnum.SECURITY_RESTRICT_ROOT_FOLDER, ApiPropertyEnum.SECURITY_HIDE_EXCEPTIONS, ApiPropertyEnum.FEATURE_COPY_ANNOTATIONS_TO_NEW_VERSION, - ApiPropertyEnum.FEATURE_ATTACHMENT_SIZE_LIMIT + ApiPropertyEnum.FEATURE_ATTACHMENT_SIZE_LIMIT, + ApiPropertyEnum.FEATURE_CREATE_REFINEMENT_LINKS_BETWEEN_VERSIONS ]) } .each {ape ->