MauroDataMapper/mdm-ui#851 describes the use case where:
A Mauro item contains a hyperlink to another Mauro item e.g. a Data Class refers to a Data Element. This is done by Mauro paths.
Someone renames a Mauro item with a new label
This then invalidates any hyperlink containing a Mauro path, because the path includes the old label.
To fix any broken links, all Mauro items referenced in description fields or metadata must also be updated as part of the source item rename, with the new path correctly inserted.
@jamesrwelch has some proof of concept code which uses a Grails interceptor to capture when a domain item is modified so the plugin knows when a label has changed. It then works out the old and new path for potential links, then locates any Mauro item that contains the old path and does a string replacement.
This should be expanded to ensure that any Mauro domain type is supported and that the following actions are supported:
Trigger Actions
Renaming an item
Attribute terminologies and terms
Code sets
Data sets and components of data sets
Classes
Attributes
Data Elements
Data set constraints (terms)
NHS Business Definitions (terms)
Supporting Information (terms)
Note: the root folders where all these live would not be expected to be renamed e.g. the "Supporting Information" terminology won't be renamed, but the terms inside it could be.
Moving an item
Sub-folders
Data set models within other folders
What gets modified
Descriptions
Metadata
TODO: @jamesrwelch to clarify what possible metadata values might contain HTML
Features
If an item being renamed contains the old path as a link in itself e.g. its own description field, modify that synchronously to return the most up to date information in the HTTP response
For any other items, these should be located and updated as an asynchronous operation e.g. a separate thread of an async job. This will allow the HTTP response to be returned and the user can continue while a batch of work continues on the server in the background.
Any Mauro item update should handle errors correctly and carefully - if one update fails, the entire batch must not fail. Although this probably cannot be wrapped up in a single transaction, each update could be wrapped in a try/catch block to ensure as much consistency as possible.
Endpoints
Unlikely to be an exhaustive list, here are some endpoints involved in changing labels/descriptions of items in the model. What often seems to occur is that the identifiers are also passed in the payload during the update action, however reading the body payload will empty the stream so should not be done in an interceptor.
MauroDataMapper/mdm-ui#851 describes the use case where:
To fix any broken links, all Mauro items referenced in description fields or metadata must also be updated as part of the source item rename, with the new path correctly inserted.
Dependencies
The following issues must be completed first:
Grails Interceptor
@jamesrwelch has some proof of concept code which uses a Grails interceptor to capture when a domain item is modified so the plugin knows when a label has changed. It then works out the old and new path for potential links, then locates any Mauro item that contains the old path and does a string replacement.
This should be expanded to ensure that any Mauro domain type is supported and that the following actions are supported:
Trigger Actions
Renaming an item
Note: the root folders where all these live would not be expected to be renamed e.g. the "Supporting Information" terminology won't be renamed, but the terms inside it could be.
Moving an item
What gets modified
Features
Endpoints
Unlikely to be an exhaustive list, here are some endpoints involved in changing labels/descriptions of items in the model. What often seems to occur is that the identifiers are also passed in the payload during the
update
action, however reading the body payload will empty the stream so should not be done in an interceptor.VersionFolder
/api/versionedFolders/{{model_id}}
versionedFolder
Folder
/api/folders/{{folder_id}}
folder
Data Standard
/api/dataModels/{{model_id}}
dataModel
DataClass
/api/dataModels/{{model id}}/dataClasses/{{class_id}}
dataClass
DataElement
/api/dataModels/{{model_id}}/dataClasses/{{class_id}}/dataElements/{{dataitem_id}}
dataElement
Note that all the above URLs are all used in a PUT request, also, payload as documented in Postman does not appear to match what actually gets passed.