Skip to content

Generator does not handle negative durations in ISO-8601 format #701

@JayPi4c

Description

@JayPi4c

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

  1. Download the latest development opt of KDS_Medikationseintrag from 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
  2. run generator to create classes for template (java -jar generator.jar -opt KDS_Medikationseintrag_revision_24.opt -out . -package com.example)
  3. 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 -:

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;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions