-
Notifications
You must be signed in to change notification settings - Fork 32
Generator does not handle negative durations in ISO-8601 format #701
Description
Before reporting an issue
- I have searched existing issues
- I have reproduced the issue with the latest release
Environment information
openEHR_SDK Version: v2.27.0
Java Runtime Version: 25
Operating System: Ubuntu 24.04.3 LTS
Steps to reproduce
- Download the latest development opt of
KDS_Medikationseintragfrom https://ckm.highmed.org/ckm/templates/1246.169.438
Opt file (as txt as GitHub does not support opt to be uploaded): KDS_Medikationseintrag_revision_24.txt - run generator to create classes for template (
java -jar generator.jar -opt KDS_Medikationseintrag_revision_24.opt -out . -package com.example) - See Exception.
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:672)
at java.base/java.lang.Integer.parseInt(Integer.java:778)
at org.ehrbase.openehr.sdk.webtemplate.parser.InputHandler.buildDurationConstrains(InputHandler.java:481)
at org.ehrbase.openehr.sdk.webtemplate.parser.InputHandler.addInputs(InputHandler.java:337)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseComplexObjectSingle(OPTParser.java:641)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCCOMPLEXOBJECT(OPTParser.java:369)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCOBJECT(OPTParser.java:870)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseComplexObjectSingle(OPTParser.java:446)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCCOMPLEXOBJECT(OPTParser.java:369)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCOBJECT(OPTParser.java:870)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseComplexObjectSingle(OPTParser.java:446)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCCOMPLEXOBJECT(OPTParser.java:369)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCOBJECT(OPTParser.java:870)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseComplexObjectSingle(OPTParser.java:446)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCCOMPLEXOBJECT(OPTParser.java:369)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCARCHETYPEROOT(OPTParser.java:269)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCOBJECT(OPTParser.java:860)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseComplexObjectSingle(OPTParser.java:446)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCCOMPLEXOBJECT(OPTParser.java:369)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCARCHETYPEROOT(OPTParser.java:269)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCOBJECT(OPTParser.java:860)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseComplexObjectSingle(OPTParser.java:446)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCCOMPLEXOBJECT(OPTParser.java:369)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCOBJECT(OPTParser.java:870)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseComplexObjectSingle(OPTParser.java:446)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCCOMPLEXOBJECT(OPTParser.java:369)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCOBJECT(OPTParser.java:870)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseComplexObjectSingle(OPTParser.java:446)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCCOMPLEXOBJECT(OPTParser.java:369)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCOBJECT(OPTParser.java:870)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseComplexObjectSingle(OPTParser.java:446)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCCOMPLEXOBJECT(OPTParser.java:369)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCARCHETYPEROOT(OPTParser.java:269)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCOBJECT(OPTParser.java:860)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseComplexObjectSingle(OPTParser.java:446)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCCOMPLEXOBJECT(OPTParser.java:369)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parseCARCHETYPEROOT(OPTParser.java:269)
at org.ehrbase.openehr.sdk.webtemplate.parser.OPTParser.parse(OPTParser.java:171)
at org.ehrbase.openehr.sdk.generator.ClassGeneratorRunner.main(ClassGeneratorRunner.java:71)
Expected behavior
Successfully generate classes for template.
Actual result
Exception is thrown without information about the section in the opt where to look for the error.
Further information
Upon further investigation I found the bug to be in the class InputHandler of the web-template module.
In the opt file, there is a section with a duration defined as follows:
<item xsi:type="C_DURATION">
<pattern>PTHMS</pattern>
<range>
<lower_included>true</lower_included>
<upper_included>true</upper_included>
<lower_unbounded>false</lower_unbounded>
<upper_unbounded>false</upper_unbounded>
<lower>-PT24H</lower>
<upper>PT24H</upper>
</range>
</item>Semantically this section is meant to denote a period from 24h in the past to 24h in the future.
Looking at the <lower> element, I see that the value is starting with -. The function Map<String, Integer> buildDurationConstrains(String constrain) in the InputHandler, however, does not handle the case in which a ISO-8601 period is starting with -:
openEHR_SDK/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/parser/InputHandler.java
Lines 462 to 487 in d4c8e31
| Map<String, Integer> buildDurationConstrains(String constrain) { | |
| if (StringUtils.isBlank(constrain)) { | |
| return Collections.emptyMap(); | |
| } | |
| Map<String, Integer> constrainMap = new HashMap<>(); | |
| boolean isDatePath = true; | |
| StringBuilder sb = new StringBuilder(); | |
| for (int i = 0; i < constrain.length(); i++) { | |
| char c = constrain.charAt(i); | |
| if (c == 'T') { | |
| isDatePath = false; | |
| } else if (CharUtils.isAsciiNumeric(c)) { | |
| sb.append(c); | |
| } else if (c != 'P') { | |
| String key = String.valueOf(c); | |
| if (!isDatePath && key.equals("M")) { | |
| key = key + "T"; | |
| } | |
| constrainMap.put(key, Integer.parseInt(sb.toString())); | |
| sb.delete(0, sb.length()); | |
| } | |
| } | |
| return constrainMap; | |
| } |