diff --git a/ballerina/tests/xsd_choice_array_test_with_parse_type.bal b/ballerina/tests/xsd_choice_array_test_with_parse_type.bal index f8abc0f..9ee4490 100644 --- a/ballerina/tests/xsd_choice_array_test_with_parse_type.bal +++ b/ballerina/tests/xsd_choice_array_test_with_parse_type.bal @@ -56,6 +56,9 @@ function testXsdChoiceArrayWithXmlValue() returns error? { v = parseAsType(xmlValue); test:assertTrue(v is error); test:assertEquals((v).message(), "'choice_XsdChoiceArrayWithXmlValue' occurs more than the max allowed times"); + xml|Error toXmlResult = toXml({choice_XsdChoiceArrayWithXmlValue: {age: [13, 14, 15], salary: [11.1, 14.1, 15.1]}}); + test:assertTrue(toXmlResult is error); + test:assertEquals((toXmlResult).message(), "'choice_XsdChoiceArrayWithXmlValue' occurs more than the max allowed times"); } @Name { @@ -109,11 +112,17 @@ function testXsdChoiceArrayWithXmlValue2() returns error? { v = parseAsType(xmlValue); test:assertTrue(v is error); test:assertEquals((v).message(), "'choice_XsdChoiceArrayWithXmlValue2_2' occurs more than the max allowed times"); + xml|Error toXmlResult = toXml({choice_XsdChoiceArrayWithXmlValue2: {age: [13], salary: []}, choice_XsdChoiceArrayWithXmlValue2_2: {age2: [13, 14, 15], salary2: [11.1]}}); + test:assertTrue(toXmlResult is error); + test:assertEquals((toXmlResult).message(), "'choice_XsdChoiceArrayWithXmlValue2_2' occurs more than the max allowed times"); xmlValue = xml `13131313`; v = parseAsType(xmlValue); test:assertTrue(v is error); test:assertEquals((v).message(), "'choice_XsdChoiceArrayWithXmlValue2' occurs more than the max allowed times"); + toXmlResult = toXml({choice_XsdChoiceArrayWithXmlValue2: {age: [13, 14, 15], salary: [11.1, 14.1, 15.1]}}); + test:assertTrue(toXmlResult is error); + test:assertEquals((toXmlResult).message(), "'choice_XsdChoiceArrayWithXmlValue2' occurs more than the max allowed times"); xmlValue = xml `1313`; v = parseAsType(xmlValue); diff --git a/ballerina/tests/xsd_choice_test_with_parse_type.bal b/ballerina/tests/xsd_choice_test_with_parse_type.bal index 1d66f68..8403928 100644 --- a/ballerina/tests/xsd_choice_test_with_parse_type.bal +++ b/ballerina/tests/xsd_choice_test_with_parse_type.bal @@ -57,6 +57,9 @@ function testXsdChoiceWithXmlValue() returns error? { test:assertEquals((v).message(), "'choice_XSDChoiceWithXmlValueRecord' occurs more than the max allowed times"); e = validate(XSDChoiceWithXmlValueRecord, xmlValue); test:assertEquals((e).message(), "Invalid XML found: ''choice_XSDChoiceWithXmlValueRecord' occurs more than the max allowed times'"); + xml|Error toXmlResult = toXml({choice_XSDChoiceWithXmlValueRecord: {age: 10, salary: 11.1}}); + test:assertTrue(toXmlResult is Error); + test:assertEquals((toXmlResult).message(), "'choice_XSDChoiceWithXmlValueRecord' occurs more than the max allowed times"); xmlValue = xml `11.111.1`; v = parseAsType(xmlValue); @@ -210,11 +213,17 @@ function testXsdChoiceWithXmlValue2() returns error? { v = parseAsType(xmlValue); test:assertTrue(v is Error); test:assertEquals((v).message(), "'choice_XSDChoiceWithXmlValueRecord2' occurs more than the max allowed times"); + xml|Error toXmlResult = toXml({choice_XSDChoiceWithXmlValueRecord2: {age: 10, salary: 11.1}, num: 3}); + test:assertTrue(toXmlResult is Error); + test:assertEquals((toXmlResult).message(), "'choice_XSDChoiceWithXmlValueRecord2' occurs more than the max allowed times"); xmlValue = xml `10311.1`; v = parseAsType(xmlValue); test:assertTrue(v is Error); test:assertEquals((v).message(), "'choice_XSDChoiceWithXmlValueRecord2' occurs more than the max allowed times"); + toXmlResult = toXml({num: 3, choice_XSDChoiceWithXmlValueRecord2: {age: 10, salary: 11.1}}); + test:assertTrue(toXmlResult is Error); + test:assertEquals((toXmlResult).message(), "'choice_XSDChoiceWithXmlValueRecord2' occurs more than the max allowed times"); } @Name { @@ -604,6 +613,9 @@ function testXsdChoiceWithXmlValue10() returns error? { test:assertEquals((v2).message(), "'choice_XSDChoiceWithXmlValueRecord10_1' occurs more than the max allowed times"); e = validate(XSDChoiceWithXmlValueRecord10, xmlValue); test:assertEquals((e).message(), "Invalid XML found: ''choice_XSDChoiceWithXmlValueRecord10_1' occurs more than the max allowed times'"); + xml|Error toXmlResult = toXml({choice_XSDChoiceWithXmlValueRecord10_1: {field1: {value1: {a: "1"}}, field2: {value2: {d: "1"}}}, choice_XSDChoiceWithXmlValueRecord10_2: {field5: {value2: {d: "2"}}}}); + test:assertTrue(toXmlResult is Error); + test:assertEquals((toXmlResult).message(), "'choice_XSDChoiceWithXmlValueRecord10_1' occurs more than the max allowed times"); xmlValue = xml `122`; v2 = parseAsType(xmlValue); @@ -618,4 +630,7 @@ function testXsdChoiceWithXmlValue10() returns error? { test:assertEquals((v2).message(), "'value2' occurs more than the max allowed times"); e = validate(XSDChoiceWithXmlValueRecord10, xmlValue); test:assertEquals((e).message(), "Invalid XML found: ''value2' occurs more than the max allowed times'"); + toXmlResult = toXml({choice_XSDChoiceWithXmlValueRecord10_1: {field2: {value2: {d: "1", e: "1"}}}, choice_XSDChoiceWithXmlValueRecord10_2: {field5: {value2: {d: "2"}}}}); + test:assertTrue(toXmlResult is Error); + test:assertEquals((toXmlResult).message(), "'value2' occurs more than the max allowed times"); } diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/ToXmlUtils.java b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/ToXmlUtils.java index 1efa5e7..541a23d 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/ToXmlUtils.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/ToXmlUtils.java @@ -18,6 +18,7 @@ package io.ballerina.lib.data.xmldata.utils; +import io.ballerina.lib.data.xmldata.xml.xsd.ChoiceInfo; import io.ballerina.lib.data.xmldata.xml.xsd.ElementInfo; import io.ballerina.lib.data.xmldata.xml.xsd.ModelGroupInfo; import io.ballerina.lib.data.xmldata.xml.xsd.SequenceInfo; @@ -165,6 +166,10 @@ public static BXml traverseRecordAndGenerateXml(Object jNode, BMap elementInfoRelatedFieldNames, + HashMap elementNamesMap) { + // TODO: Update this later for validate choices with multiple element occurences. + boolean isMeasurable = true; + int occurences = 0; + + for (Object key : jMap.getKeys()) { + String jsonKey = key.toString(); + Object value = jMap.get(key); + String localJsonKeyPart = jsonKey.contains(Constants.COLON) ? + jsonKey.substring(jsonKey.indexOf(Constants.COLON) + 1) : jsonKey; + String recordKey = elementNamesMap.getOrDefault(localJsonKeyPart, localJsonKeyPart); + ElementInfo elementInfo = elementInfoRelatedFieldNames.get(recordKey); + if (elementInfo != null && elementInfo.maxOccurs != 1) { + isMeasurable = false; + break; + } + + if (value instanceof BArray array) { + occurences += array.size(); + } else { + occurences++; + } + } + + if (isMeasurable && occurences > parentModelGroupInfo.getMaxOccurs()) { + throw DiagnosticLog.error(DiagnosticErrorCode.ELEMENT_OCCURS_MORE_THAN_MAX_ALLOWED_TIMES, + parentModelGroupInfo.getFieldName()); + } + + if (isMeasurable && occurences < parentModelGroupInfo.getMinOccurs()) { + throw DiagnosticLog.error(DiagnosticErrorCode.ELEMENT_OCCURS_LESS_THAN_MIN_REQUIRED_TIMES, + parentModelGroupInfo.getFieldName()); + } + } + private static HashMap getModelGroupRelatedFieldNames(Type expType, HashMap elementNamesMap) { Type referedType = TypeUtils.getReferredType(expType);