diff --git a/.travis.yml b/.travis.yml
index e7a68b42e0..dde58a2c47 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,11 +14,8 @@ addons:
artifacts:
paths:
- $HOME/reports
- apt:
- packages:
- - mysql-server-5.6
- - mysql-client-core-5.6
- - mysql-client-5.6
+services:
+ - mysql
env:
- TEST_SUITE=functional
- TEST_SUITE=unit_and_integration
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/catalogue.coffee b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/catalogue.coffee
index 92a37512ec..f320dcdbae 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/catalogue.coffee
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/catalogue.coffee
@@ -27,6 +27,7 @@ angular.module('mc.core.ui.bs.catalogue', ['mc.core.catalogue']).config ['catalo
catalogueProvider.setIcon 'mapping', "fa fa-fw fa-superscript"
catalogueProvider.setIcon 'validationRule', "fa fa-fw fa-university"
catalogueProvider.setIcon 'dataModelPolicy', "fa fa-fw fa-check-square-o"
+ catalogueProvider.setIcon 'tag', "fa fa-fw fa-tag"
# this should be generated automatically in the future
@@ -44,6 +45,7 @@ angular.module('mc.core.ui.bs.catalogue', ['mc.core.catalogue']).config ['catalo
catalogueProvider.setInstanceOf 'model', 'catalogueElement'
catalogueProvider.setInstanceOf 'dataElement', 'catalogueElement'
catalogueProvider.setInstanceOf 'validationRule', 'catalogueElement'
+ catalogueProvider.setInstanceOf 'tag', 'catalogueElement'
catalogueProvider.setInstanceOf 'enumeratedType', 'dataType'
catalogueProvider.setInstanceOf 'referenceType', 'dataType'
@@ -145,6 +147,14 @@ angular.module('mc.core.ui.bs.catalogue', ['mc.core.catalogue']).config ['catalo
return 0.5 if list.base.indexOf("/asset") >= 0
+ return 0
+ ]
+ catalogueProvider.addContainsCandidateTest ['list', 'element', 'extra', (list, newElement, extra) ->
+ return 0 unless list
+ return 0 unless list.base
+
+ return 0.5 if list.base.indexOf("/tag/forDataModel") >= 0 and newElement.isInstanceOf('dataElement')
+
return 0
]
]
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/catalogueElementProperties.coffee b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/catalogueElementProperties.coffee
index 8846602c4b..a40ac67680 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/catalogueElementProperties.coffee
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/catalogueElementProperties.coffee
@@ -53,6 +53,7 @@ angular.module('mc.core.ui.bs.catalogueElementProperties', []).config ['catalogu
catalogueElementPropertiesProvider.configureProperty 'ext', label: 'Metadata'
catalogueElementPropertiesProvider.configureProperty 'contextFor', label: 'Rules'
catalogueElementPropertiesProvider.configureProperty 'involvedIn', label: 'Rules'
+ catalogueElementPropertiesProvider.configureProperty 'tags', label: 'Data Elements'
catalogueElementPropertiesProvider.configureProperty 'childOf', label: 'Parents', columns: nameAndIdent()
catalogueElementPropertiesProvider.configureProperty 'isContextFor', label: 'Data Classes', columns: nameAndIdent()
catalogueElementPropertiesProvider.configureProperty 'containedIn', label: 'Data Classes', columns: nameAndIdAndMetadata()
@@ -240,6 +241,7 @@ angular.module('mc.core.ui.bs.catalogueElementProperties', []).config ['catalogu
catalogueElementPropertiesProvider.configureProperty 'originalDataModels', hidden: true
catalogueElementPropertiesProvider.configureProperty 'internalModelCatalogueId', hidden: true
catalogueElementPropertiesProvider.configureProperty 'versionNumber', hidden: true
+ catalogueElementPropertiesProvider.configureProperty 'isTaggedBy', hidden: true
catalogueElementPropertiesProvider.configureProperty '$$relationship', tabDefinition: [ '$element', '$name', ($element, $name) ->
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/columns.coffee b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/columns.coffee
index e35030b535..7d15bb4899 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/columns.coffee
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/columns.coffee
@@ -90,6 +90,7 @@ angular.module('mc.core.ui.bs.columns', ['mc.util.names']).config ['columnsProvi
columnsProvider.registerColumns 'org.modelcatalogue.core.DataClass', modelIdNameAndDescriptionColumns()
columnsProvider.registerColumns 'org.modelcatalogue.core.DataElement', modelIdNameAndDescriptionColumns()
columnsProvider.registerColumns 'org.modelcatalogue.core.ValidationRule', modelIdNameAndDescriptionColumns()
+ columnsProvider.registerColumns 'org.modelcatalogue.core.Tags', modelIdNameAndDescriptionColumns()
# special
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/detailSections.coffee b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/detailSections.coffee
index 13210489f2..2dc2b1f292 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/detailSections.coffee
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/detailSections.coffee
@@ -470,4 +470,59 @@ x in ['apple', 'banana', 'cherry']
]
}
}
+
+ detailSectionsProvider.register {
+ title: 'Tags'
+ position: 70
+ types: [
+ 'dataElement'
+ ]
+ keys: []
+ template: '/mc/core/ui/detail-sections/tableData.html'
+ actions: [
+ {
+ label: 'Add Tag'
+ name: 'add'
+ icon: 'fa fa-plus-circle text-success'
+ action: (messages, element) ->
+ messages.prompt('Add Tag', '',
+ {
+ type: 'create-new-relationship'
+ element: element
+ relationshipTypeName: 'tag'
+ direction: "destinationToSource"
+ }
+ )
+ }
+ ]
+
+ getList: (element) ->
+ return @result if @result
+
+ @result =
+ base: element.isTaggedBy.base
+ itemType: element.isTaggedBy.itemType
+
+ element.isTaggedBy(null, max: LIST_MAX).then (list) =>
+ @result = list
+ return @result
+ reorder: reorderInDetail('isTaggedBy')
+ data: {
+ columns:
+ [
+ {
+ header: 'Name'
+ value: "ext.get('name') || ext.get('Name') || relation.name "
+ classes: 'col-md-6'
+ href: 'relation.href()'
+ }
+ {
+ header: 'Description'
+ value: "relation.description"
+ classes: 'col-md-6'
+ textEllipsis: true
+ }
+ ]
+ }
+ }
]
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/index.coffee b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/index.coffee
index d8a33d0402..c28b9bed38 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/index.coffee
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/index.coffee
@@ -58,6 +58,7 @@ angular.module('mc.core.ui.bs', [
'mc.core.ui.bs.modalPromptBasicEdit'
'mc.core.ui.bs.modalPromptMeasurementUnitEdit'
'mc.core.ui.bs.modalPromptEnumeratedTypeEdit'
+ 'mc.core.ui.bs.modalPromptTagEdit'
'mc.core.ui.bs.modalPromptActionParametersEdit'
'mc.core.ui.bs.modalPromptModel'
'mc.core.ui.bs.modalPromptRelationshipTypeEdit'
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/modals/modalPromptTagEdit.coffee b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/modals/modalPromptTagEdit.coffee
new file mode 100644
index 0000000000..cffa5869f1
--- /dev/null
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/bs/modals/modalPromptTagEdit.coffee
@@ -0,0 +1,67 @@
+angular.module('mc.core.ui.bs.modalPromptTagEdit', ['mc.util.messages', 'mc.core.ui.bs.withClassificationCtrlMixin']).config ['messagesProvider', (messagesProvider)->
+ factory = [ '$uibModal', '$q', 'messages', ($uibModal, $q, messages) ->
+ (title, body, args) ->
+ if not args?.element? and not args?.create?
+ messages.error('Cannot create relationship dialog.', 'The element to be edited is missing.')
+ return $q.reject('Missing element argument!')
+
+ dialog = $uibModal.open {
+ windowClass: 'basic-edit-modal-prompt'
+ size: 'lg'
+ template: '''
+
+
+
+ '''
+ controller: ['$scope', 'messages', '$controller', '$uibModalInstance', ($scope, messages, $controller, $uibModalInstance) ->
+ $scope.pending = {dataModel: null}
+ $scope.newEntity = -> {dataModels: $scope.copy?.dataModels ? []}
+ $scope.copy = angular.copy(args.element ? $scope.newEntity())
+ $scope.original = args.element ? {}
+ $scope.messages = messages.createNewMessages()
+ $scope.create = args.create
+ $scope.currentDataModel = args.currentDataModel
+
+ angular.extend(this, $controller('withClassificationCtrlMixin', {$scope: $scope}))
+ angular.extend(this, $controller('saveAndCreateAnotherCtrlMixin', {$scope: $scope, $uibModalInstance: $uibModalInstance}))
+
+ $scope.hasChanged = ->
+ $scope.copy.name != $scope.original.name\
+ or $scope.copy.description != $scope.original.description\
+ or $scope.copy.modelCatalogueId != $scope.original.modelCatalogueId
+
+ ]
+
+ }
+
+ dialog.result
+ ]
+
+ messagesProvider.setPromptFactory 'edit-tag', factory
+]
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/catalogueElementView.coffee b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/catalogueElementView.coffee
index e7cb1415e2..70c4593677 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/catalogueElementView.coffee
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/catalogueElementView.coffee
@@ -235,6 +235,7 @@ angular.module('mc.core.ui.catalogueElementView', ['mc.core.catalogueElementEnha
or $scope.element?.isInstanceOf('measurementUnit')\
or $scope.element?.isInstanceOf('dataElement')\
or $scope.element?.isInstanceOf('validationRule')\
+ or $scope.element?.isInstanceOf('tag')\
)\
and ($scope.element?.status == 'DRAFT' or security.hasRole('SUPERVISOR'))
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/metadataEditor.coffee b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/metadataEditor.coffee
index 425b663f4d..ad84ce82de 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/metadataEditor.coffee
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/metadataEditor.coffee
@@ -59,12 +59,13 @@ angular.module('mc.core.ui.metadataEditor', ['mc.core.ui.metadataEditors']).dire
$scope.handledKeys = []
onObjectChanged = (object) ->
- if object and not isOrderedMap(object)
- $log.error "Object", object, "is not ordered map"
- return
+ if object
+ unless isOrderedMap(object)
+ $log.error "Object", object, "is not ordered map"
+ return
- object.clearIfOnlyContainsPlaceholder()
- object.addPlaceholderIfEmpty()
+ object.clearIfOnlyContainsPlaceholder()
+ object.addPlaceholderIfEmpty()
onObjectChanged($scope.object)
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/states/controllers/DataModelTreeCtrl.coffee b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/states/controllers/DataModelTreeCtrl.coffee
index 1ebaa8fe28..f91a0c1db0 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/states/controllers/DataModelTreeCtrl.coffee
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/states/controllers/DataModelTreeCtrl.coffee
@@ -12,6 +12,12 @@ angular.module('mc.core.ui.states.controllers.DataModelTreeCtrl', ['ui.router',
if element.resource
if element.getDataModelId() == currentDataModel?.id
+ if element.tagId
+ if element.tagId == 'none'
+ $state.go 'mc.resource.list', dataModelId: currentDataModel?.id, resource: 'dataElement', status: 'active', tag: 'none'
+ return
+ $state.go 'mc.resource.show.property', dataModelId: currentDataModel?.id, resource: 'tag', id: element.tagId, property: 'tags'
+ return
if element.resource == 'catalogueElement' && element.name == 'Deprecated Items'
$state.go 'mc.resource.list', dataModelId: currentDataModel?.id, resource: element.resource, status: 'deprecated'
return
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/states/mc.resource.list.state.coffee b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/states/mc.resource.list.state.coffee
index fcc40af37a..484ff92edf 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/states/mc.resource.list.state.coffee
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/javascripts/modelcatalogue/core/ui/states/mc.resource.list.state.coffee
@@ -5,7 +5,7 @@ angular.module('mc.core.ui.states.mc.resource.list', ['mc.core.ui.states.control
DEFAULT_ITEMS_PER_PAGE = 25
$stateProvider.state 'mc.resource.list', {
- url: '/all?page&order&sort&status&q&max&classification&display'
+ url: '/all?page&order&sort&status&q&max&classification&display&tag'
views:
"":
@@ -31,6 +31,7 @@ angular.module('mc.core.ui.states.mc.resource.list', ['mc.core.ui.states.control
params.status = $stateParams.status
params.max = $stateParams.max ? DEFAULT_ITEMS_PER_PAGE
params.classification = $stateParams.classification ? undefined
+ params.tag = $stateParams.tag ? undefined
if $stateParams.dataModelId and $stateParams.dataModelId != 'catalogue'
params.dataModel = $stateParams.dataModelId
@@ -43,4 +44,4 @@ angular.module('mc.core.ui.states.mc.resource.list', ['mc.core.ui.states.control
}
-])
\ No newline at end of file
+])
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.1/metadataregistry.xsd b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.1/metadataregistry.xsd
index 9f0b4c044e..e8cffafb81 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.1/metadataregistry.xsd
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.1/metadataregistry.xsd
@@ -1,8 +1,8 @@
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry.xsd b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry.xsd
new file mode 100644
index 0000000000..a98dcfebbc
--- /dev/null
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry.xsd
@@ -0,0 +1,396 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The Reference can must always contain at least "ref" attribute or "name". If the "dataModel" is
+ provided the name will be searched only within this data model. Also if element of this type
+ is used inside element of type "DataModel" it is assumed that the element should be searched by name
+ within the surrounding data model. This does not apply on elements having the "ref" attribute
+ provided. In that case the element is resolved by the ID. The type of the catalogue element can
+ be provided to distinguish between elements having same name and data model but different types
+ (this is quite common for value domains and it's data types)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CatalogueElement is either a in-lined definition of the element or a reference to the existing element.
+ If "ref" attribute is set, any other attributes or nested elements are ignored.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry_asset.xsd b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry_asset.xsd
new file mode 100644
index 0000000000..ed1205736d
--- /dev/null
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry_asset.xsd
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry_validator.xsd b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry_validator.xsd
new file mode 100644
index 0000000000..49276bfe5a
--- /dev/null
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry_validator.xsd
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry_violation.xsd b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry_violation.xsd
new file mode 100644
index 0000000000..c375c8ae0d
--- /dev/null
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/schema/2.2/metadataregistry_violation.xsd
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/assets/other/xsl/transform2CatalogueSchema.xsl b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/xsl/transform2CatalogueSchema.xsl
index 99a645438e..08187541fe 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/assets/other/xsl/transform2CatalogueSchema.xsl
+++ b/ModelCatalogueCorePluginTestApp/grails-app/assets/other/xsl/transform2CatalogueSchema.xsl
@@ -1,7 +1,7 @@
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/conf/BootStrap.groovy b/ModelCatalogueCorePluginTestApp/grails-app/conf/BootStrap.groovy
index 997fbe1341..3b0cd604d3 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/conf/BootStrap.groovy
+++ b/ModelCatalogueCorePluginTestApp/grails-app/conf/BootStrap.groovy
@@ -50,7 +50,7 @@ class BootStrap {
if (Environment.current in [Environment.DEVELOPMENT, Environment.TEST] && !System.getenv('MC_BLANK_DEV')) {
TestDataHelper.initFreshDb(sessionFactory, 'initTestDatabase.sql') {
initCatalogueService.initCatalogue(true)
- initDataModelPolicies()
+ initPoliciesAndTags()
initSecurity(false)
setupStuff()
}
@@ -59,7 +59,7 @@ class BootStrap {
}
} else {
initCatalogueService.initDefaultRelationshipTypes()
- initDataModelPolicies()
+ initPoliciesAndTags()
initSecurity(!System.getenv('MC_BLANK_DEV'))
}
@@ -417,7 +417,7 @@ class BootStrap {
// createRequestmapIfMissing('/api/modelCatalogue/core/relationshipTypes/**', 'ROLE_ADMIN')
}
- def initDataModelPolicies() {
+ def initPoliciesAndTags() {
catalogueBuilder.build {
dataModelPolicy(name: 'Unique of Kind') {
check dataClass property 'name' is 'unique'
@@ -439,6 +439,19 @@ class BootStrap {
check dataType property 'name' is 'unique' otherwise 'Data type\'s name is not unique for {2}'
check dataType property 'name' apply regex: /[^_ -]+/ otherwise 'Name of {2} contains illegal characters ("_", "-" or " ")'
}
+ dataModel(name: 'Clinical Tags') {
+ tag(name: 'Registration, consent and demographic data essential for the management of the participant')
+ tag(name: 'Sample tracking data essential for processing and tracking the sample from collection through to sequencing')
+ tag(name: 'Clinical data essential for diagnostics purposes')
+ tag(name: 'Clinical data essential for research')
+ tag(name: 'Clinical data for research')
+ tag(name: 'Highly Sensitive PI data')
+ tag(name: 'Sensitive PI data')
+ tag(name: 'Highly Sensitive data')
+ tag(name: 'Sensitive data')
+ tag(name: 'Internal data')
+ tag(name: 'External data')
+ }
}
}
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/conf/BuildConfig.groovy b/ModelCatalogueCorePluginTestApp/grails-app/conf/BuildConfig.groovy
index 42172244ed..201e6e49ff 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/conf/BuildConfig.groovy
+++ b/ModelCatalogueCorePluginTestApp/grails-app/conf/BuildConfig.groovy
@@ -68,7 +68,7 @@ grails.project.dependency.resolution = {
// compile 'io.reactivex:rxgroovy:1.0.3'
- String mcToolkitVersion = '2.1.0.2'
+ String mcToolkitVersion = '2.2.0'
compile "org.modelcatalogue:mc-core-api:$mcToolkitVersion"
compile "org.modelcatalogue:mc-builder-api:$mcToolkitVersion"
compile "org.modelcatalogue:mc-datatype-validation:$mcToolkitVersion"
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/conf/Config.groovy b/ModelCatalogueCorePluginTestApp/grails-app/conf/Config.groovy
index 0952d17a5c..5306c0c780 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/conf/Config.groovy
+++ b/ModelCatalogueCorePluginTestApp/grails-app/conf/Config.groovy
@@ -4,6 +4,7 @@ import org.modelcatalogue.core.CatalogueElement
import org.modelcatalogue.core.DataClass
import org.modelcatalogue.core.DataElement
import org.modelcatalogue.core.DataModel
+import org.modelcatalogue.core.Tag
import org.modelcatalogue.core.ValidationRule
import org.modelcatalogue.core.security.User
@@ -244,10 +245,10 @@ log4j.main = {
// debug 'org.springframework.security'
// debug 'org.grails.plugins.elasticsearch'
- //if (Environment.current == Environment.DEVELOPMENT || Environment.current == Environment.CUSTOM) {
- // trace 'org.hibernate.type'
- // trace 'org.hibernate.stat'
- // debug 'org.hibernate.SQL'
+// if (Environment.current == Environment.DEVELOPMENT || Environment.current == Environment.CUSTOM) {
+// trace 'org.hibernate.type'
+// trace 'org.hibernate.stat'
+// debug 'org.hibernate.SQL'
// }
info 'org.modelcatalogue'
@@ -434,4 +435,5 @@ modelcatalogue.defaults.relationshiptypes = [
[name: "classificationFilter", sourceToDestination: "used as filter by", destinationToSource: "filtered by", sourceClass: DataModel, destinationClass: User, system: true, sourceToDestinationDescription: "Classification can be used as filter by multiple users. This is done using the classification filter in bottom left corner.", destinationToSourceDescription: "User can filter by multiple classifications. To use exclusion filter instead of inclusion, set metadata \$exclude to any non-null value."],
[name: "ruleContext", destinationToSource: "provides context for", sourceToDestination: "applied within context", sourceClass: ValidationRule, destinationClass: DataClass, versionSpecific: true, destinationToSourceDescription: "Data class can provide context for multiple validation rules", sourceToDestinationDescription: "Validation rule is applied within context of data class."],
[name: "involvedness", destinationToSource: "is involved in", sourceToDestination: "involves", sourceClass: ValidationRule, destinationClass: DataElement, versionSpecific: true, destinationToSourceDescription: "Data element can be involved in multiple validation rules", sourceToDestinationDescription: "Validation rule can involve multiple data elements"],
+ [name: "tag", sourceToDestination: "tags", destinationToSource: "is tagged by", sourceClass: Tag, destinationClass: DataElement, versionSpecific: false, sourceToDestinationDescription: "Applies Tag on particular Data Element", destinationToSourceDescription: "Data Elements can be tagged by multiple Tags"],
]
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/conf/DataSource.groovy b/ModelCatalogueCorePluginTestApp/grails-app/conf/DataSource.groovy
index d410ae3a64..c173767275 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/conf/DataSource.groovy
+++ b/ModelCatalogueCorePluginTestApp/grails-app/conf/DataSource.groovy
@@ -14,9 +14,28 @@ environments {
driverClassName = "org.h2.Driver"
username = "sa"
password = ""
- dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
- url = "jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"
+ dbCreate = "update" // one of 'create', 'create-drop', 'update', 'validate', ''
+ url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"
}
+ /**dataSource {
+ driverClassName = "com.mysql.jdbc.Driver"
+ dialect='org.hibernate.dialect.MySQL5InnoDBDialect'
+ url = "jdbc:mysql://localhost:3306/basic?autoReconnect=true&useUnicode=yes"
+ username = 'metadata'
+ password = 'metadata'
+ dbCreate = "update"
+ properties {
+ maxActive = -1
+ minEvictableIdleTimeMillis=1800000
+ timeBetweenEvictionRunsMillis=1800000
+ numTestsPerEvictionRun=3
+ testOnBorrow=true
+ testWhileIdle=true
+ testOnReturn=false
+ validationQuery="SELECT 1"
+ jdbcInterceptors="ConnectionState"
+ }
+ }**/
}
test {
if (System.getenv('TRAVIS') && System.getenv('TEST_SUITE') == 'functional') {
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/conf/ModelCatalogueCorePluginUrlMappings.groovy b/ModelCatalogueCorePluginTestApp/grails-app/conf/ModelCatalogueCorePluginUrlMappings.groovy
index 8d4f138e00..154fe28776 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/conf/ModelCatalogueCorePluginUrlMappings.groovy
+++ b/ModelCatalogueCorePluginTestApp/grails-app/conf/ModelCatalogueCorePluginUrlMappings.groovy
@@ -22,7 +22,7 @@ class ModelCatalogueCorePluginUrlMappings {
def legacyElements = [model: 'dataClass', classification: 'dataModel']
def resources = ['batch', 'relationshipType', 'csvTransformation', 'dataModelPolicy' ]
- def catalogueElements = ['asset', 'dataElement', 'dataClass', 'catalogueElement', 'dataType', 'enumeratedType', 'referenceType', 'primitiveType', 'measurementUnit', 'user', 'dataModel', 'classification', 'model', 'validationRule']
+ def catalogueElements = ['asset', 'dataElement', 'dataClass', 'catalogueElement', 'dataType', 'enumeratedType', 'referenceType', 'primitiveType', 'measurementUnit', 'user', 'dataModel', 'classification', 'model', 'validationRule', 'tag']
def allElements = catalogueElements + resources
for (String elementName in allElements) {
@@ -30,6 +30,11 @@ class ModelCatalogueCorePluginUrlMappings {
if (elementName in legacyElements.keySet()) {
controllerName = legacyElements[elementName]
}
+
+ if (controllerName == 'tag') {
+ "/api/modelCatalogue/core/$elementName/forDataModel/$dataModelId"(controller: controllerName, action: 'forDataModel', method: HttpMethod.GET)
+ }
+
"/api/modelCatalogue/core/$elementName" (controller: controllerName, action: 'index', method: HttpMethod.GET)
"/api/modelCatalogue/core/$elementName" (controller: controllerName, action: 'save', method: HttpMethod.POST)
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/conf/spring/resources.groovy b/ModelCatalogueCorePluginTestApp/grails-app/conf/spring/resources.groovy
index b51b82daaa..ecadb0e9f1 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/conf/spring/resources.groovy
+++ b/ModelCatalogueCorePluginTestApp/grails-app/conf/spring/resources.groovy
@@ -41,6 +41,7 @@ import org.modelcatalogue.core.util.marshalling.ReferenceTypeMarshaller
import org.modelcatalogue.core.util.marshalling.RelationshipMarshallers
import org.modelcatalogue.core.util.marshalling.RelationshipTypeMarshaller
import org.modelcatalogue.core.util.marshalling.RelationshipsMarshaller
+import org.modelcatalogue.core.util.marshalling.TagMarshaller
import org.modelcatalogue.core.util.marshalling.UserMarshaller
import org.modelcatalogue.core.util.marshalling.ValidationRuleMarshaller
import org.modelcatalogue.core.xml.render.RelationshipsXmlRenderer
@@ -112,7 +113,8 @@ beans = {
new ChangeMarshaller(),
new ValidationRuleMarshaller(),
new ProgressMonitorMarshaller(),
- new DataModelPolicyMarshaller()
+ new DataModelPolicyMarshaller(),
+ new TagMarshaller()
]
}
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/controllers/org/modelcatalogue/core/DataElementController.groovy b/ModelCatalogueCorePluginTestApp/grails-app/controllers/org/modelcatalogue/core/DataElementController.groovy
index 6365052712..5b3b6e59ac 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/controllers/org/modelcatalogue/core/DataElementController.groovy
+++ b/ModelCatalogueCorePluginTestApp/grails-app/controllers/org/modelcatalogue/core/DataElementController.groovy
@@ -2,6 +2,7 @@ package org.modelcatalogue.core
import grails.util.Environment
import org.hibernate.SessionFactory
+import org.modelcatalogue.core.util.DataModelFilter
import org.modelcatalogue.core.util.lists.ListWithTotalAndType
import org.modelcatalogue.core.util.lists.ListWrapper
import org.modelcatalogue.core.util.lists.Lists
@@ -33,13 +34,53 @@ class DataElementController extends AbstractCatalogueElementController getAllEffectiveItems(Integer max) {
- if (!params.long("dataModel") || sessionFactory.currentSession.connection().metaData.databaseProductName != 'MySQL') {
+ if (isDatabaseFallback()) {
return super.getAllEffectiveItems(max)
}
return Lists.wrap(params, "/${resourceName}/", dataElementService.findAllDataElementsInModel(params, DataModel.get(params.long('dataModel'))))
}
+ private boolean isDatabaseFallback() {
+ !params.long("dataModel") || sessionFactory.currentSession.connection().metaData.databaseProductName != 'MySQL'
+ }
+
+ @Override
+ protected Closure buildAdditionalIndexCriteria() {
+ if (!hasAdditionalIndexCriteria()) {
+ return super.buildAdditionalIndexCriteria()
+ }
+
+ if (params.tag in ['none', 'null', 'undefined']) {
+ // TODO: this is far to be optimal solution
+ return {
+ not {
+ inList 'id', Relationship.where { relationshipType == RelationshipType.tagType }.distinct('destination').list()*.id
+ }
+ }
+ }
+
+ Long tagID = params.long('tag')
+
+ Tag tag = Tag.get(tagID)
+
+ if (!tag) {
+ return super.buildAdditionalIndexCriteria()
+ }
+
+ return {
+ incomingRelationships {
+ eq 'source', tag
+ eq 'relationshipType', RelationshipType.tagType
+ }
+ }
+ }
}
diff --git a/ModelCatalogueCorePluginTestApp/grails-app/controllers/org/modelcatalogue/core/DataModelController.groovy b/ModelCatalogueCorePluginTestApp/grails-app/controllers/org/modelcatalogue/core/DataModelController.groovy
index 7df50f8574..9d09ddc634 100644
--- a/ModelCatalogueCorePluginTestApp/grails-app/controllers/org/modelcatalogue/core/DataModelController.groovy
+++ b/ModelCatalogueCorePluginTestApp/grails-app/controllers/org/modelcatalogue/core/DataModelController.groovy
@@ -110,11 +110,12 @@ class DataModelController extends AbstractCatalogueElementController
List