Java/Groovy Support of openEHR Operational Templates, Refernce Model, Data Generators and other tools for www.CaboLabs.com projects.
This will be used in CaboLabs apps like EHRGen, EHRServer, EMRApp and XML Rule Engine.
The build was tested with Gradle 6.4.1 installed from SDKMAN!.
This generates a fat jar with all dependencies to simplify CLI command execution.
$ cd openEHR-SDK
$ gradle clean fatJarNormal build without fat jar, for instance for running the tests.
$ cd openEHR-SDK
$ gradle clean buildBuild without running the tests (faster).
$ cd openEHR-SDK
$ gradle build -x testAlso tested with JDK 11.0.x and Groovy 3.0.x.
For running tests, there are many options, examples below:
- Run specific test case from a specific suite
- Run all tests from a specific suite
- Run all suites in a package
- Run all tests
$ cd openEHR-SDK
$ gradle test --tests com.cabolabs.openehr.opt.OPTParserTest.testCompleteOPT
$ gradle test --tests com.cabolabs.openehr.opt.OPTParserTest
$ gradle test --tests com.cabolabs.openehr.opt*
$ gradle testThe test report in HTML will be under ./build/reports/tests/test/index.html
Check the version of the build in gradle.properties, that should be x.y.z
$ java -jar build/libs/opt-x.y.z.jar uigen path_to_opt dest_folderOr shorthand (remember to update the x.y.z in the sdk.sh script):
$ ./sdk.sh uigen path_to_opt dest_folder$ java -jar build/libs/opt-x.y.z.jar ingen path_to_opt dest_folder [amount] [json|xml] [version|composition] [withParticipations]- amount: defines how many XML instances will be generated, default is 1
- format: 'json' or 'xml', default is 'json'
- object: type of openEHR object to generate, 'version' or 'composition', default is 'version'
- withParticipations: if included in the parameters, it will add participations to the composition
NOTE: If the 'semantic' keyword is specified as an argument, this tool will try to load the referenced OPT and validate against it's constraints. The OPT will be loaded from src/main/resources/opts/com.cabolabs.openehr_opt.namespaces.default so if you want to validate a new instance, you need to put the OPT there first.
Validate one instance:
$ java -jar build/libs/opt-x.y.z.jar inval path_to_xml_or_json_instance [semantic]Validate all instances in folder:
$ java -jar build/libs/opt-x.y.z.jar inval path_to_folder_with_xml_or_json_instances [semantic]Note: if the folder contains JSON and XML, it will validate both with the correct schema, but the files should have .json or .xml extensions for the mixed validation to work OK.
In both cases, the output is "file IS VALID" or the list of validation errors if the file is not valid against the schemas.
$ java -jar build/libs/opt-x.y.z.jar trans opt path_to_opt destination_folderTo transform a XML COMPOSITION to JSON:
$ java -jar build/libs/opt-x.y.z.jar trans composition path_to_compo.xml destination_folderTo transform a JSON COMPOSITION to JSON:
$ java -jar build/libs/opt-x.y.z.jar trans composition path_to_compo.json destination_folderNote: the transformation of COMPOSITIONS between foramts relies on the file extension, only .xml or .json files are allowed.
This is a very important tool that allows you to generate a full blown Operational Template from a single ADL archetype. A common use case is for demographic archetypes to quickly test templates based on them, also for single archetype models like FOLDER and EHR_STATUS.
$ java -jar build/libs/opt-x.y.z.jar adl2opt path_to_adl dest_pathdef inputStream = this.getClass().getResourceAsStream('/xsd/OperationalTemplateExtra.xsd')
def validator = new XmlValidation(inputStream)
def path = "someopt.opt"
def f = new File(path)
if (!f.exists())
{
println path +" doesn't exist"
System.exit(0)
}
validateXML(validator, f)
static boolean validateXML(validator, file)
{
boolean isValid = true
if (!validator.validate( file.text ))
{
println file.name +' NOT VALID'
println '====================================='
validator.errors.each {
println it
}
println '====================================='
isValid = false
}
else
{
println file.name +' VALID'
}
println ""
return isValid
}OperationalTemplate loadAndParse(String path)
{
def parser = new OperationalTemplateParser()
def optFile = new File(getClass().getResource(path).toURI())
def text = optFile.getText()
return parser.parse(text)
}To add the atttributes that are in the openEHR Reference Model but are not in the source OPT file, use the method complete():
def opt = loadAndParse("vital_signs.opt")
opt.complete()String path = "vital_signs.json"
File file = new File(getClass().getResource(path).toURI())
String json = file.text
def parser = new OpenEhrJsonParser()
Composition c = (Composition)parser.parseJson(json)Composition compo = ...
def serializer = new OpenEhrJsonSerializer()
String json = serializer.serialize(compo)String path = "vital_signs.xml"
File file = new File(getClass().getResource(path).toURI())
String xml = file.text
def parser = new OpenEhrXmlParser()
Composition c = (Composition)parser.parseLocatable(xml)Composition compo = ...
OpenEhrXmlSerializer marshal = new OpenEhrXmlSerializer()
String xml = marshal.serialize(compo)// setup OPT repository
String opt_repo_path = "opts"
OptRepository repo = new OptRepositoryFSImpl(getClass().getResource(opt_repo_path).toURI())
OptManager opt_manager = OptManager.getInstance()
opt_manager.init(repo)
// load COMPOSITION
Composition compo = ...
// the validator automatically gets the tempalte from the repo based on the template_id in the COMPOSITION
RmValidator validator = new RmValidator(opt_manager)
RmValidationReport report = validator.dovalidate(compo, OptManager.DEFAULT_NAMESPACE)
report.errors.each { error ->
println error
}String xml = ...
def parser = new OpenEhrXmlParser()
Composition c = (Composition)parser.parseLocatable(xml)
def serializer = new OpenEhrJsonSerializer()
String json = serializer.serialize(c)String json ...
def parser = new OpenEhrJsonParser()
Composition c = (Composition)parser.parseJson(json)
def serializer = new OpenEhrXmlSerializer()
String xml = serializer.serialize(c)def opt = loadAndParse('vital_signs.opt')
def igen = new JsonInstanceCanonicalGenerator2()
String json = igen.generateJSONVersionStringFromOPT(opt, true, true)def opt = loadAndParse('vital_signs.opt')
def igen = new XmlInstanceGenerator()
String xml = igen.generateXMLCompositionStringFromOPT(opt, true)