From c5a398c2e02ecfb64204f36e844de01b38aed0b2 Mon Sep 17 00:00:00 2001 From: "A.M.S.I Attanayake" Date: Wed, 11 Jun 2025 09:42:02 +0530 Subject: [PATCH 1/3] Fix parse error with special characters - This PR is fix the [error of parsing special chars](https://github.com/ballerina-platform/ballerina-library/issues/8000) --- .../fhir/ballerina/packagegen/tool/utils/CommonUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/fhir-to-bal-lib/src/main/java/org/wso2/healthcare/fhir/ballerina/packagegen/tool/utils/CommonUtil.java b/native/fhir-to-bal-lib/src/main/java/org/wso2/healthcare/fhir/ballerina/packagegen/tool/utils/CommonUtil.java index 11d9c283..c6a31e0f 100644 --- a/native/fhir-to-bal-lib/src/main/java/org/wso2/healthcare/fhir/ballerina/packagegen/tool/utils/CommonUtil.java +++ b/native/fhir-to-bal-lib/src/main/java/org/wso2/healthcare/fhir/ballerina/packagegen/tool/utils/CommonUtil.java @@ -129,7 +129,8 @@ public static String toCamelCase(String str) { public static String validateCode(String code) { String newCode = code.trim().split(Pattern.quote(" "))[0]; return newCode.replaceAll(" *\\(.+?\\)", "") - .replace("+", ""); + .replace("+", "") + .replace("*", ""); } /** From 802a20651799003211ecd047f5f7aa7241859d93 Mon Sep 17 00:00:00 2001 From: "A.M.S.I Attanayake" Date: Wed, 11 Jun 2025 09:45:52 +0530 Subject: [PATCH 2/3] fix missed union for array elements for VTL 2.0 --- .../main/resources/templates/fhir_resource.vm | 169 +++++++++--------- 1 file changed, 89 insertions(+), 80 deletions(-) diff --git a/native/fhir-to-bal-lib/src/main/resources/templates/fhir_resource.vm b/native/fhir-to-bal-lib/src/main/resources/templates/fhir_resource.vm index 6515fca1..eafeef90 100644 --- a/native/fhir-to-bal-lib/src/main/resources/templates/fhir_resource.vm +++ b/native/fhir-to-bal-lib/src/main/resources/templates/fhir_resource.vm @@ -17,6 +17,8 @@ // AUTO-GENERATED FILE. // This file is auto-generated by Ballerina. +#set($tab = " ") + #foreach($import in $imports) #if($import) import $import.toString(); @@ -31,77 +33,81 @@ public const RESOURCE_NAME_${util.resolveSpecialCharacters($resourceName.toUpper # + resourceType - The type of the resource describes #foreach($element in $resourceElements) # + $util.resolveSpecialCharacters($util.resolveKeywordConflict($element.getName())) - $element.getDescription() -#if($sliceElements.get($element.getPath())) -# * $element.getName() Slicings -#foreach($sliceElement in $sliceElements.get($element.getPath())) -#if ($sliceElement.getMax() == $INT_MAX) -#set($max = "*") -#else -#set($max = $sliceElement.getMax()) -#end -# $foreach.count) $sliceElement.getDataType(): $sliceElement.getSummary() -# - min = $sliceElement.getMin() -# - max = $max -# -#end -#end + #if($sliceElements.get($element.getPath())) + # * $element.getName() Slicings + #foreach($sliceElement in $sliceElements.get($element.getPath())) + #if ($sliceElement.getMax() == $INT_MAX) + #set($max = "*") + #else + #set($max = $sliceElement.getMax()) + #end + # $foreach.count) $sliceElement.getDataType(): $sliceElement.getSummary() + # - min = $sliceElement.getMin() + # - max = $max + # + #end + #end #end + @${importIdentifier}ResourceDefinition { resourceType: "${resourceType}", baseType: ${importIdentifier}DomainResource, profile: "${profile}", elements: { #foreach($element in ${annotationElements}) - "${element.getName()}" : { + "${element.getName()}" : { name: "${element.getName()}", dataType: #if(!$dataTypes.contains($element.getDataType()))${importIdentifier}$util.resolveSpecialCharacters($element.getDataType())#else$util.resolveSpecialCharacters($element.getDataType())#end, min: ${element.getMin()}, max: ${element.getMax()}, isArray: ${element.isArray()}, - #if($element.getValueSet()) - path: "${element.getPath()}", + #if($element.getValueSet()) + path: "${element.getPath()}", valueSet: "${element.getValueSet()}" - #else - path: "${element.getPath()}" - #end - }#if ($foreach.count != $annotationElements.size()),#end + #else + path: "${element.getPath()}" + #end + }#if ($foreach.count != $annotationElements.size()),#end #end -}, + }, + serializers: { 'xml: ${importIdentifier}fhirResourceXMLSerializer, 'json: ${importIdentifier}fhirResourceJsonSerializer } } + public type $util.resolveSpecialCharacters($resourceName) record {| *${importIdentifier}DomainResource; RESOURCE_NAME_${util.resolveSpecialCharacters($resourceName.toUpperCase())} resourceType = RESOURCE_NAME_${util.resolveSpecialCharacters($resourceName.toUpperCase())}; -#foreach($element in $resourceElements) -#set($min = 1) -#set($max = 1) -#set($separator = ",") -## Here we should add constraint:Array only for the Array elements and min or max is 1 -#if( ${util.isConstrainedArrayElement($element)} ) - @constraint:Array { -#if( $element.getMin() > 0 ) + #foreach($element in $resourceElements) + #set($min = 1) + #set($max = 1) + #set($separator = ",") + ## Here we should add constraint:Array only for the Array elements and min or max is 1 + #if( ${util.isConstrainedArrayElement($element)} ) +@constraint:Array { + #if( $element.getMin() > 0 ) minLength: { value: $min$separator message: "Validation failed for $.$element.getPath() constraint. This field must be an array containing at least one item." }#if( $element.getMax() > 0 )$separator#end -#end + #end -#if( $element.getMax() > 0 ) + #if( $element.getMax() > 0 ) maxLength: { value: $max$separator message: "Validation failed for $.$element.getPath() constraint. This field must be an array containing at most one item." } -#end + #end } -#end - #foreach($profileEntry in $element.getProfiles().entrySet())#if(!$dataTypes.contains($profileEntry.value.getProfileType()))#if(!$profileEntry.value.getPrefix())${importIdentifier}#else$profileEntry.value.getPrefix():#end#end$util.resolveSpecialCharacters($profileEntry.value.getProfileType())#if($element.isArray()) []#end#if($velocityCount != $element.getProfiles().size())#end#end $util.resolveKeywordConflict($util.resolveSpecialCharacters($element.getName()))#if(!$element.isRequired())?#end; -#end +$tab#end + #set($isDataTypeSet = false) + #foreach($profileEntry in $element.getProfiles().entrySet())#if(!$dataTypes.contains($profileEntry.value.getProfileType()))#if(!$profileEntry.value.getPrefix())${importIdentifier}#else$profileEntry.value.getPrefix():#end#end#if($element.isExtended())#foreach($key in $extendedElements.keySet())#if($key == $profileEntry.value.getProfileType() && $extendedElements.get($key).getPrimitiveExtendedType())$util.resolveSpecialCharacters($profileEntry.value.getProfileType()) | ${importIdentifier}$extendedElements.get($key).getPrimitiveExtendedType()#set($isDataTypeSet = true)#end#end#end#if(!$isDataTypeSet)$util.resolveSpecialCharacters($profileEntry.value.getProfileType())#end#if($element.isArray()) []#end#if($foreach.count != $element.getProfiles().size())|#end#end $util.resolveKeywordConflict($util.resolveSpecialCharacters($element.getName()))#if(!$element.isRequired())?#end; + #end ${importIdentifier}Element ...; |}; @@ -111,85 +117,88 @@ public type $util.resolveSpecialCharacters($resourceName) record {| # #foreach($element in $extendedElement.getAnnotation().getElements()) # + $util.resolveSpecialCharacters($util.resolveKeywordConflict($element.getName())) - $element.getDescription() -#if($element.hasSlicedElements()) -# * $element.getName() Slicing -#foreach($sliceElement in $element.getSlicedElements()) -# $foreach.count) $sliceElement.getName(): $sliceElement.getSummary() -# - min = $sliceElement.getMin() -# - max = $sliceElement.getMax() -# -#end -#end + #if($element.hasSlicedElements()) + # * $element.getName() Slicing + #foreach($sliceElement in $element.getSlicedElements()) + # $foreach.count) $sliceElement.getName(): $sliceElement.getSummary() + # - min = $sliceElement.getMin() + # - max = $sliceElement.getMax() + # + #end + #end #end + @${importIdentifier}DataTypeDefinition { name: "${extendedElement.getTypeName()}", baseType: $extendedElement.getAnnotation().getBaseType(), elements: { - #foreach($annotationElement in $extendedElement.getAnnotation().getElements()) - "${annotationElement.getName()}": { + #foreach($annotationElement in $extendedElement.getAnnotation().getElements()) + "${annotationElement.getName()}": { name: "${annotationElement.getName()}", dataType: #if(!$dataTypes.contains($annotationElement.getDataType()))${importIdentifier}$util.resolveSpecialCharacters($annotationElement.getDataType())#else$util.resolveSpecialCharacters($annotationElement.getDataType())#end, min: $annotationElement.getMin(), max: $annotationElement.getMax(), isArray: $annotationElement.isArray(), description: "$annotationElement.getDescription()", - #if($element.getValueSet()) - path: "${annotationElement.getPath()}", - valueSet: "${annotationElement.getValueSet()}" - #else - path: "${annotationElement.getPath()}" - #end - }#if ($foreach.count != $extendedElement.getAnnotation().getElements().size()),#end + #if($element.getValueSet()) + path: "${annotationElement.getPath()}", + valueSet: "${annotationElement.getValueSet()}" + #else + path: "${annotationElement.getPath()}" + #end + }#if ($foreach.count != $extendedElement.getAnnotation().getElements().size()), + #end + #end + }, - #end -}, serializers: { 'xml: ${importIdentifier}complexDataTypeXMLSerializer, 'json: ${importIdentifier}complexDataTypeJsonSerializer } } + public type $util.resolveSpecialCharacters($extendedElement.getTypeName()) record {| -#if ($extendedElement.getBaseType()) + #if ($extendedElement.getBaseType()) *#if(!$dataTypes.contains($extendedElement.getBaseType()))${importIdentifier}#end$extendedElement.getBaseType(); -#end + #end -#foreach($childElement in $extendedElement.getElements()) -#set($min = 1) -#set($max = 1) -#set($separator = ",") -## Here we should add constraint:Array only for the Array elements and min or max is 1 -#if( ${util.isConstrainedArrayElement($childElement)} ) - @constraint:Array { -#if( $childElement.getMin() > 0) + #foreach($childElement in $extendedElement.getElements()) + #set($min = 1) + #set($max = 1) + #set($separator = ",") + ## Here we should add constraint:Array only for the Array elements and min or max is 1 + #if( ${util.isConstrainedArrayElement($childElement)} ) +@constraint:Array { + #if( $childElement.getMin() > 0) minLength: { value: $min$separator message: "Validation failed for $.$childElement.getPath() constraint. This field must be an array containing at least one item." }#if( $childElement.getMax() > 0 )$separator#end -#end + #end -#if( $childElement.getMax() > 0) + #if( $childElement.getMax() > 0) maxLength: { value: $max$separator message: "Validation failed for $.$childElement.getPath() constraint. This field must be an array containing at most one item." } -#end + #end } -#end -#if($childElement.hasFixedValue()) - #if(!$dataTypes.contains($childElement.getDataType()))${importIdentifier}#end$util.resolveSpecialCharacters($childElement.getDataType())#if($childElement.isArray()) []#end $util.resolveSpecialCharacters($util.resolveKeywordConflict($childElement.getName()))#if(!$childElement.isRequired())?#end = #if($childElement.isArray()) [#end#foreach($value in $childElement.getFixedValue())$util.getTypedValue($value, $childElement.getDataType())#if($foreach.count != $childElement.getFixedValue().size()),#end#end#if($childElement.isArray())]#end; -#else - #if(!$dataTypes.contains($childElement.getDataType()))${importIdentifier}#end$util.resolveSpecialCharacters($childElement.getDataType())#if($childElement.isArray()) []#end $util.resolveSpecialCharacters($util.resolveKeywordConflict($childElement.getName()))#if(!$childElement.isRequired())?#end; -#end +$tab#end + #if($childElement.hasFixedValue()) + #if(!$dataTypes.contains($childElement.getDataType()))${importIdentifier}#end$util.resolveSpecialCharacters($childElement.getDataType())#if($childElement.isArray()) []#end $util.resolveSpecialCharacters($util.resolveKeywordConflict($childElement.getName()))#if(!$childElement.isRequired())?#end = #if($childElement.isArray()) [#end#foreach($value in $childElement.getFixedValue())$util.getTypedValue($value, $childElement.getDataType())#if($foreach.count != $childElement.getFixedValue().size()),#end#end#if($childElement.isArray())]#end; + #else + #if(!$dataTypes.contains($childElement.getDataType()))${importIdentifier}#end$util.resolveSpecialCharacters($childElement.getDataType())#if($childElement.isArray()) []#end $util.resolveSpecialCharacters($util.resolveKeywordConflict($childElement.getName()))#if(!$childElement.isRequired())?#end; + #end #end |}; + #elseif($extendedElement.getBalDataType().getType() == "enum") # $extendedElement.getTypeName() enum public enum $util.resolveSpecialCharacters($extendedElement.getTypeName()) { -#foreach($childElement in $extendedElement.getElements()) - CODE_$childElement.getRootElementName().toUpperCase()_$util.resolveSpecialCharacters($childElement.getName()).toUpperCase() = "$childElement.getName()"#if($foreach.count != $extendedElement.getElements().size()),$newline#end -#end - + #foreach($childElement in $extendedElement.getElements()) + CODE_$childElement.getRootElementName().toUpperCase()_$util.resolveSpecialCharacters($childElement.getName()).toUpperCase() = "$childElement.getName()"#if($foreach.count != $extendedElement.getElements().size()),#end + #end } #end -#end +#end \ No newline at end of file From 07ffec1c3409a7ecf00251eaf51895d4415c9b6c Mon Sep 17 00:00:00 2001 From: "A.M.S.I Attanayake" <59891156+Sanjana-Attanayake@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:31:42 +0530 Subject: [PATCH 3/3] add new_line --- .../src/main/resources/templates/fhir_resource.vm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/fhir-to-bal-lib/src/main/resources/templates/fhir_resource.vm b/native/fhir-to-bal-lib/src/main/resources/templates/fhir_resource.vm index eafeef90..4488eb2e 100644 --- a/native/fhir-to-bal-lib/src/main/resources/templates/fhir_resource.vm +++ b/native/fhir-to-bal-lib/src/main/resources/templates/fhir_resource.vm @@ -201,4 +201,4 @@ public enum $util.resolveSpecialCharacters($extendedElement.getTypeName()) { } #end -#end \ No newline at end of file +#end