From 9a081beb7364c4c188311081b205e2ffb8ca8d9a Mon Sep 17 00:00:00 2001 From: Pablo Pazos Date: Fri, 10 May 2024 01:37:01 -0300 Subject: [PATCH] fixed rm validator removing redundant existence 0..1 + occurrence 1..1 check --- gradle.properties | 2 +- opt.sh | 2 +- review_20240509090104_000001_1.json | 273 ++++++++++++++++++ .../openehr/validation/RmValidator2.groovy | 16 +- 4 files changed, 290 insertions(+), 3 deletions(-) create mode 100644 review_20240509090104_000001_1.json diff --git a/gradle.properties b/gradle.properties index 64c05f1..027215e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ -version = 1.9.30 +version = 1.9.31 group = com.cabolabs \ No newline at end of file diff --git a/opt.sh b/opt.sh index 49791d3..bd507b9 100755 --- a/opt.sh +++ b/opt.sh @@ -1 +1 @@ -java -cp "./lib/*:$GROOVY_HOME/lib/*:build/libs/opt-1.9.28.jar" com.cabolabs.openehr.opt.Main $1 $2 $3 $4 $5 $6 $7 +java -cp "./lib/*:$GROOVY_HOME/lib/*:build/libs/opt-1.9.30.jar" com.cabolabs.openehr.opt.Main $1 $2 $3 $4 $5 $6 $7 diff --git a/review_20240509090104_000001_1.json b/review_20240509090104_000001_1.json new file mode 100644 index 0000000..05548c4 --- /dev/null +++ b/review_20240509090104_000001_1.json @@ -0,0 +1,273 @@ +{ + "_type": "COMPOSITION", + "name": { + "_type": "DV_TEXT", + "value": "Review" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-COMPOSITION.review.v1" + }, + "template_id": { + "value": "Review" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-COMPOSITION.review.v1", + "language": { + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "ISO_639-1" + }, + "code_string": "en" + }, + "territory": { + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "ISO_3166-1" + }, + "code_string": "UY" + }, + "category": { + "value": "event", + "defining_code": { + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "openehr" + }, + "code_string": "433" + } + }, + "composer": { + "_type": "PARTY_IDENTIFIED", + "external_ref": { + "id": { + "_type": "HIER_OBJECT_ID", + "value": "b71d3cc0-9208-4c43-b9f1-17d68d1d4e7f" + }, + "namespace": "DEMOGRAPHIC", + "type": "PERSON" + }, + "name": "Dr. Yamamoto" + }, + "context": { + "start_time": { + "value": "2024-05-09T21:01:04.462-03:00" + }, + "setting": { + "value": "home", + "defining_code": { + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "openehr" + }, + "code_string": "225" + } + } + }, + "content": [ + { + "_type": "OBSERVATION", + "name": { + "_type": "DV_TEXT", + "value": "Glasgow coma scale" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-OBSERVATION.glasgow_coma_scale.v1" + }, + "template_id": { + "value": "Review" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-OBSERVATION.glasgow_coma_scale.v1", + "language": { + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "ISO_639-1" + }, + "code_string": "en" + }, + "encoding": { + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "IANA_character-sets" + }, + "code_string": "UTF-8" + }, + "subject": { + "_type": "PARTY_SELF" + }, + "protocol": { + "_type": "ITEM_TREE", + "name": { + "_type": "DV_TEXT", + "value": "Tree" + }, + "archetype_node_id": "at0038", + "items": [ + + ] + }, + "data": { + "_type": "HISTORY", + "name": { + "_type": "DV_TEXT", + "value": "Event Series" + }, + "archetype_node_id": "at0001", + "origin": { + "value": "2024-05-09T21:01:04.575-03:00" + }, + "events": [ + { + "_type": "POINT_EVENT", + "name": { + "_type": "DV_TEXT", + "value": "Point in time" + }, + "archetype_node_id": "at0002", + "time": { + "value": "2024-05-09T21:01:04.582-03:00" + }, + "data": { + "_type": "ITEM_TREE", + "name": { + "_type": "DV_TEXT", + "value": "Tree" + }, + "archetype_node_id": "at0003", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Best eye response (E)" + }, + "archetype_node_id": "at0009", + "value": { + "_type": "DV_ORDINAL", + "value": 1, + "symbol": { + "value": "None", + "defining_code": { + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "local" + }, + "code_string": "at0010" + } + } + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Best verbal response (V)" + }, + "archetype_node_id": "at0007", + "value": { + "_type": "DV_ORDINAL", + "value": 1, + "symbol": { + "value": "None", + "defining_code": { + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "local" + }, + "code_string": "at0014" + } + } + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Best motor response (M)" + }, + "archetype_node_id": "at0008", + "value": { + "_type": "DV_ORDINAL", + "value": 1, + "symbol": { + "value": "None", + "defining_code": { + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "local" + }, + "code_string": "at0019" + } + } + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Total score" + }, + "archetype_node_id": "at0026", + "value": { + "_type": "DV_COUNT", + "magnitude": 8 + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "EVM profile" + }, + "archetype_node_id": "at0030", + "value": { + "_type": "DV_TEXT", + "value": "cHTdI YlBYGUOlIuzb.Z,ZtjQPm jrAXDJyeCPwJZ.bP,nhyYQJi.RJgv.TvjmAEchjzTXUNazFMNzDxkveXxripfIbdSoKQeBUUuFNRJegCjbX.mPGeLnsKICCHoDgnrOuS,lbfFE,IfNV Rjks,RSGVGQKECAsPQggOycDTaMwwmwfHdzJYYkZGBTJWvkRuxksVDLagkqrWnoS.Jigz WeXQNNFBNs StleYvQYDJrWhaekBZkYGfrALNrBdwWrfVHPrQcmwOtpmhLLFiQTcOJmPhUqasHHbjBFZcyGh,C" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Comment" + }, + "archetype_node_id": "at0037", + "value": { + "_type": "DV_TEXT", + "value": "XVmwN,EczozNBWn lv glpDrloFJKoxgTJKYwfkXViGkOeoXmCZfM oLRcw,HIFIsqmzIpXmYJORkTogNy.CcOOoDvEwPyhjyABPzhsNiMcxlsHnUHNtQKkHomWmPgxkxOmWIR,JECLzTKw.YMWOTxEaRIVAAaUIpvOGhvOloFVus,THA.HkSudY hkcVNSkMLnOoSX.MMfv.qcmna.RaBNNKBwgWsmGxjTE,hAwM.uTsWzfotGZLupckBlEcmXF,tQsPqGoyoqTJpNeEeU.UyEdpEUY,bqaXEIxjzmcCzep" + } + } + ] + }, + "state": { + "_type": "ITEM_TREE", + "name": { + "_type": "DV_TEXT", + "value": "Tree" + }, + "archetype_node_id": "at0040", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Confounding factors" + }, + "archetype_node_id": "at0041", + "value": { + "_type": "DV_TEXT", + "value": "QdIeLOiTXfcdkpDDgdqJaIQSdmOMO,ydDjUsSlZRnQ.MnBhYbItCGhxrvRHYhhUBheKdFtuXju QrMtIDX,TR,YsOeyxPJuQctocTslqdPSHTgJlOwMZIVQfHCvmlKtrxqponlZWMIkGtXVVdOoYHiZLAjoXu XINCiJZZDUjKNEuzIwDxWyhBakHEdTlfRcEkbFyRHXymyPWKRTlGwOXakJKsbcYEKJRTjb.Vqn,PNLOMboeQkFuZqbpWPgLYpmodowbIeG,He sWMVjRcOzwNbXwDMcZSWcgsE.FoaGsSd" + } + } + ] + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/src/main/groovy/com/cabolabs/openehr/validation/RmValidator2.groovy b/src/main/groovy/com/cabolabs/openehr/validation/RmValidator2.groovy index 786ce8f..ab1e53a 100644 --- a/src/main/groovy/com/cabolabs/openehr/validation/RmValidator2.groovy +++ b/src/main/groovy/com/cabolabs/openehr/validation/RmValidator2.groovy @@ -2445,6 +2445,9 @@ class RmValidator2 { ) } + // NOTE: if value is null and existence lower is zero, there is no need to check occurrences, because occurrences come after existence. The issue is if the data is null, existence 0..1 and occurrence 1..1, then occurrences will fail. So in the case of null data + existence has 0 => do not check occurrences. + + /* // occurrences // For a null value, the occurrences constraints should be checked on the parent object, // because with a null value, the dataPath can't be retrieved to set it on the error report. @@ -2462,6 +2465,7 @@ class RmValidator2 { // for multiple alternatives, a null value will always validate since all occurrences.lower == 0, // when there are multiple alternatives for a single attribute, since lower == 1 would make that // node the only alternative, and there are many, so there is no need for an else here. + */ } } @@ -2519,7 +2523,10 @@ class RmValidator2 { { // existence: the only way of violating existence is with 1..1 so // it's checked only if the value is null - if (c_attr.existence && !c_attr.existence.has(0)) + if (!c_attr.existence) return + + + if (!c_attr.existence.has(0)) { report.addError( object.dataPath +'/'+ attribute_name, @@ -2528,6 +2535,11 @@ class RmValidator2 { ) } + + // NOTE: if value is null and existence lower is zero, there is no need to check occurrences, because occurrences come after existence. The issue is if the data is null, existence 0..1 and occurrence 1..1, then occurrences will fail. So in the case of null data + existence has 0 => do not check occurrences. + + /* + // occurrences // For a null value, the occurrences constraints should be checked on the parent object, // because with a null value, the dataPath can't be retrieved to set it on the error report. @@ -2549,6 +2561,8 @@ class RmValidator2 { // for multiple alternatives, a null value will always validate since all occurrences.lower == 0, // when there are multiple alternatives for a single attribute, since lower == 1 would make that // node the only alternative, and there are many, so there is no need for an else here. + + */ } }