From 7ed1432b7d339f7f7ba5b14f89186a806c56a08d Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Wed, 21 Aug 2024 17:14:08 +0530 Subject: [PATCH 01/16] Add changes for support union --- .github/CODEOWNERS | 2 +- .../xmldata/compiler/CompilerPluginTest.java | 168 +++++------------- .../compiler/XmldataRecordFieldValidator.java | 54 +++--- .../xmldata/utils/DiagnosticErrorCode.java | 4 +- .../lib/data/xmldata/xml/XmlParser.java | 2 +- .../lib/data/xmldata/xml/XmlTraversal.java | 84 +++++++-- native/src/main/resources/error.properties | 6 + 7 files changed, 157 insertions(+), 163 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c5ebbcf..8d17e9c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,4 +4,4 @@ # See: https://help.github.com/articles/about-codeowners/ # These owners will be the default owners for everything in the repo. -* @hasithaa @prakanth97 +* @hasithaa @prakanth97 @SasinduDilshara diff --git a/compiler-plugin-test/src/test/java/io/ballerina/lib/data/xmldata/compiler/CompilerPluginTest.java b/compiler-plugin-test/src/test/java/io/ballerina/lib/data/xmldata/compiler/CompilerPluginTest.java index 81c1040..e4c0aca 100644 --- a/compiler-plugin-test/src/test/java/io/ballerina/lib/data/xmldata/compiler/CompilerPluginTest.java +++ b/compiler-plugin-test/src/test/java/io/ballerina/lib/data/xmldata/compiler/CompilerPluginTest.java @@ -55,78 +55,6 @@ public void testDuplicateFieldNegative2() { "invalid field: duplicate field found"); } - @Test - public void testUnsupportedUnionTypeNegative1() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_3").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 2); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - } - - @Test - public void testUnsupportedUnionTypeNegative2() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_4").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 2); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - } - - @Test - public void testUnsupportedTypeNegative1() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_5").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 4); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(3).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - } - - @Test - public void testUnsupportedTypeNegative2() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_7").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 8); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(3).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(4).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - Assert.assertEquals(errorDiagnosticsList.get(5).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(6).diagnosticInfo().messageFormat(), - "unsupported type: the record field does not support the expected type"); - Assert.assertEquals(errorDiagnosticsList.get(7).diagnosticInfo().messageFormat(), - "unsupported union type: union type does not support multiple non-primitive record types"); - } - @Test public void testChildRecordWithNameAnnotNegative() { DiagnosticResult diagnosticResult = @@ -157,27 +85,27 @@ public void testDuplicateFieldInInlineRecordsNegative() { "invalid field: duplicate field found"); } - @Test - public void testUnionTypeNegative() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_9").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 6); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "invalid field: duplicate field found"); - Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), - "invalid field: duplicate field found"); - Assert.assertEquals(errorDiagnosticsList.get(3).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - Assert.assertEquals(errorDiagnosticsList.get(4).diagnosticInfo().messageFormat(), - "invalid field: duplicate field found"); - Assert.assertEquals(errorDiagnosticsList.get(5).diagnosticInfo().messageFormat(), - "invalid field: duplicate field found"); - } +// @Test +// public void testUnionTypeNegative() { +// DiagnosticResult diagnosticResult = +// CompilerPluginTestUtils.loadPackage("sample_package_9").getCompilation().diagnosticResult(); +// List errorDiagnosticsList = diagnosticResult.diagnostics().stream() +// .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) +// .collect(Collectors.toList()); +// Assert.assertEquals(errorDiagnosticsList.size(), 6); +// Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), +// "invalid field: duplicate field found"); +// Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), +// "invalid field: duplicate field found"); +// Assert.assertEquals(errorDiagnosticsList.get(3).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// Assert.assertEquals(errorDiagnosticsList.get(4).diagnosticInfo().messageFormat(), +// "invalid field: duplicate field found"); +// Assert.assertEquals(errorDiagnosticsList.get(5).diagnosticInfo().messageFormat(), +// "invalid field: duplicate field found"); +// } @Test public void testCompilerPluginWithAProjectWithSubModule() { @@ -198,31 +126,31 @@ public void testCompilerPluginWithAProjectWithSubModule() { "invalid annotation attachment: child record does not allow name annotation"); } - @Test - public void testComplexUnionTypeCaseWhenUserDefinedModulePrefix() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_11").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 1); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - } - - @Test - public void testComplexUnionTypeCaseWhenUserDefinedModulePrefix2() { - DiagnosticResult diagnosticResult = - CompilerPluginTestUtils.loadPackage("sample_package_12").getCompilation().diagnosticResult(); - List errorDiagnosticsList = diagnosticResult.diagnostics().stream() - .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) - .collect(Collectors.toList()); - Assert.assertEquals(errorDiagnosticsList.size(), 3); - Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), - "invalid type: expected a record type"); - } +// @Test +// public void testComplexUnionTypeCaseWhenUserDefinedModulePrefix() { +// DiagnosticResult diagnosticResult = +// CompilerPluginTestUtils.loadPackage("sample_package_11").getCompilation().diagnosticResult(); +// List errorDiagnosticsList = diagnosticResult.diagnostics().stream() +// .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) +// .collect(Collectors.toList()); +// Assert.assertEquals(errorDiagnosticsList.size(), 1); +// Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// } + +// @Test +// public void testComplexUnionTypeCaseWhenUserDefinedModulePrefix2() { +// DiagnosticResult diagnosticResult = +// CompilerPluginTestUtils.loadPackage("sample_package_12").getCompilation().diagnosticResult(); +// List errorDiagnosticsList = diagnosticResult.diagnostics().stream() +// .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) +// .collect(Collectors.toList()); +// Assert.assertEquals(errorDiagnosticsList.size(), 3); +// Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), +// "invalid type: expected a record type"); +// } } diff --git a/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java b/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java index 170ed26..07150eb 100644 --- a/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java +++ b/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java @@ -179,15 +179,17 @@ private void validateExpectedType(TypeSymbol typeSymbol, Optional loca case TYPE_REFERENCE -> validateExpectedType(((TypeReferenceTypeSymbol) typeSymbol).typeDescriptor(), location, ctx); case UNION -> { - int nonErrorTypeCount = 0; + int recordCount = 0; for (TypeSymbol memberTSymbol : ((UnionTypeSymbol) typeSymbol).memberTypeDescriptors()) { if (getReferredTypeSymbol(memberTSymbol).typeKind() == TypeDescKind.ERROR) { continue; } - nonErrorTypeCount++; - validateExpectedType(memberTSymbol, location, ctx); + if (getReferredTypeSymbol(memberTSymbol).typeKind() == TypeDescKind.RECORD) { + validateExpectedType(memberTSymbol, location, ctx); + recordCount++; + } } - if (nonErrorTypeCount > 1) { + if (recordCount == 0) { reportDiagnosticInfo(ctx, location, XmldataDiagnosticCodes.EXPECTED_RECORD_TYPE); } } @@ -215,7 +217,7 @@ private boolean isNotValidExpectedType(TypeSymbol typeSymbol) { continue; } - if (isNotValidExpectedType(memberTSymbol)) { + if (!(getReferredTypeSymbol(memberTSymbol).typeKind() == TypeDescKind.RECORD)) { return true; } } @@ -323,7 +325,7 @@ private void processRecordFieldsType(RecordTypeSymbol recordTypeSymbol, SyntaxNo private void validateRecordFieldType(TypeSymbol typeSymbol, Optional location, SyntaxNodeAnalysisContext ctx) { switch (typeSymbol.typeKind()) { - case UNION -> validateUnionType((UnionTypeSymbol) typeSymbol, location, ctx); +// case UNION -> validateUnionType((UnionTypeSymbol) typeSymbol, location, ctx); case NIL, TUPLE -> reportDiagnosticInfo(ctx, location, XmldataDiagnosticCodes.UNSUPPORTED_TYPE); case ARRAY -> validateRecordFieldType(((ArrayTypeSymbol) typeSymbol).memberTypeDescriptor(), location, ctx); case TYPE_REFERENCE -> @@ -331,26 +333,26 @@ private void validateRecordFieldType(TypeSymbol typeSymbol, Optional l } } - private void validateUnionType(UnionTypeSymbol unionTypeSymbol, Optional location, - SyntaxNodeAnalysisContext ctx) { - int nonPrimitiveMemberCount = 0; - boolean isNilPresent = false; - List memberTypeSymbols = unionTypeSymbol.memberTypeDescriptors(); - for (TypeSymbol memberTypeSymbol : memberTypeSymbols) { - if (isPrimitiveType(memberTypeSymbol)) { - continue; - } - - if (memberTypeSymbol.typeKind() == TypeDescKind.NIL) { - isNilPresent = true; - } - nonPrimitiveMemberCount++; - } - - if (nonPrimitiveMemberCount > 1 || (memberTypeSymbols.size() > 1 && isNilPresent)) { - reportDiagnosticInfo(ctx, location, XmldataDiagnosticCodes.UNSUPPORTED_UNION_TYPE); - } - } +// private void validateUnionType(UnionTypeSymbol unionTypeSymbol, Optional location, +// SyntaxNodeAnalysisContext ctx) { +// int nonPrimitiveMemberCount = 0; +// boolean isNilPresent = false; +// List memberTypeSymbols = unionTypeSymbol.memberTypeDescriptors(); +// for (TypeSymbol memberTypeSymbol : memberTypeSymbols) { +// if (isPrimitiveType(memberTypeSymbol)) { +// continue; +// } +// +// if (memberTypeSymbol.typeKind() == TypeDescKind.NIL) { +// isNilPresent = true; +// } +// nonPrimitiveMemberCount++; +// } +// +// if (nonPrimitiveMemberCount > 1 || (memberTypeSymbols.size() > 1 && isNilPresent)) { +// reportDiagnosticInfo(ctx, location, XmldataDiagnosticCodes.UNSUPPORTED_UNION_TYPE); +// } +// } private boolean isPrimitiveType(TypeSymbol typeSymbol) { TypeDescKind kind = typeSymbol.typeKind(); diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java index 0d90190..7f09304 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DiagnosticErrorCode.java @@ -41,7 +41,9 @@ public enum DiagnosticErrorCode { UNSUPPORTED_TYPE("XML_ERROR_014", "unsupported.type"), STREAM_BROKEN("XML_ERROR_015", "stream.broken"), XML_PARSE_ERROR("XML_ERROR_016", "xml.parse.error"), - UNDEFINED_FIELD("XML_ERROR_0017", "undefined.field"); + UNDEFINED_FIELD("XML_ERROR_0017", "undefined.field"), + CANNOT_CONVERT_SOURCE_INTO_EXP_TYPE("XML_ERROR_0018", "cannot.convert.source.into.expected.type"), + FIELD_CANNOT_CAST_INTO_TYPE("XML_ERROR_0019", "field.cannot.convert.into.type"); String diagnosticId; String messageKey; diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java index 98a5a72..ddbffcf 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java @@ -113,7 +113,7 @@ public static Object parse(Reader reader, BMap options, Type ty } catch (BError e) { return e; } catch (Throwable e) { - return DiagnosticLog.error(DiagnosticErrorCode.XML_PARSE_ERROR, e.getMessage()); + throw DiagnosticLog.error(DiagnosticErrorCode.XML_PARSE_ERROR, e.getMessage()); } } diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java index 21a0f0e..cda93cd 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java @@ -33,6 +33,7 @@ import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.RecordType; import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.UnionType; import io.ballerina.runtime.api.types.XmlNodeType; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; @@ -83,30 +84,60 @@ static class XmlTree { private Object currentNode; public Object traverseXml(BXml xml, BMap options, Type type) { + XmlAnalyzerData analyzerData = new XmlAnalyzerData(); + DataUtils.updateOptions(options, analyzerData); + return traverseXml(xml, analyzerData, type); + } + + public Object traverseXml(BXml xml, XmlAnalyzerData analyzerData, Type type) { Type referredType = TypeUtils.getReferredType(type); switch (referredType.getTag()) { case TypeTags.RECORD_TYPE_TAG -> { - XmlAnalyzerData analyzerData = new XmlAnalyzerData(); - DataUtils.updateOptions(options, analyzerData); - RecordType recordType = (RecordType) referredType; - currentNode = ValueCreator.createRecordValue(recordType.getPackage(), recordType.getName()); - BXml nextXml = validateRootElement(xml, recordType, analyzerData); - Object resultRecordValue = traverseXml(nextXml, recordType, analyzerData); - DataUtils.validateRequiredFields(analyzerData); - return resultRecordValue; + return traverseXmlWithRecordAsExpectedType(xml, analyzerData, referredType); } case TypeTags.MAP_TAG -> { - MapType mapType = (MapType) referredType; - RecordType anonRecType = TypeCreator.createRecordType(Constants.ANON_TYPE, mapType.getPackage(), 0, - new HashMap<>(), mapType.getConstrainedType(), false, 0); - return traverseXml(xml, options, anonRecType); + return traverseXmlWithMapAsExpectedType(xml, referredType, analyzerData); + } + case TypeTags.UNION_TAG -> { + return traverseXmlToUnion(xml, analyzerData, type); } default -> { - return DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, Constants.RECORD_OR_MAP, - type.getName()); + throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, Constants.RECORD_OR_MAP, type); } } } + + private Object traverseXmlWithRecordAsExpectedType(BXml xml, + XmlAnalyzerData analyzerData, Type referredType) { + RecordType recordType = (RecordType) referredType; + currentNode = ValueCreator.createRecordValue(recordType.getPackage(), recordType.getName()); + BXml nextXml = validateRootElement(xml, recordType, analyzerData); + Object resultRecordValue = traverseXml(nextXml, recordType, analyzerData); + DataUtils.validateRequiredFields(analyzerData); + return resultRecordValue; + } + + private Object traverseXmlWithMapAsExpectedType(BXml xml, Type referredType, XmlAnalyzerData analyzerData) { + MapType mapType = (MapType) referredType; + RecordType anonRecType = TypeCreator.createRecordType(Constants.ANON_TYPE, mapType.getPackage(), 0, + new HashMap<>(), mapType.getConstrainedType(), false, 0); + return traverseXml(xml, analyzerData, anonRecType); + } + + private Object traverseXmlToUnion(BXml xml, XmlAnalyzerData options, Type type) { + UnionType unionType = (UnionType) type; + for (Type memberType: unionType.getMemberTypes()) { + try { + if (memberType.getTag() == TypeTags.ERROR_TAG) { + continue; + } + return traverseXml(xml, options, memberType); + } catch (Exception ex) { + // ignore + } + } + throw DiagnosticLog.error(DiagnosticErrorCode.CANNOT_CONVERT_SOURCE_INTO_EXP_TYPE, type); + } private Object traverseXml(BXml xml, Type type, XmlAnalyzerData analyzerData) { switch (xml.getNodeType()) { @@ -235,10 +266,16 @@ private void convertToFieldType(BXmlItem xmlItem, Field currentField, String fie case TypeTags.TYPE_REFERENCED_TYPE_TAG -> convertToFieldType(xmlItem, currentField, fieldName, TypeUtils.getReferredType(currentFieldType), mapValue, analyzerData); + case TypeTags.UNION_TAG -> traverseXml(xmlItem, analyzerData, currentFieldType); default -> traverseXml(xmlItem.getChildrenSeq(), currentFieldType, analyzerData); } } + private void convertFieldTypeToUnionType(BXmlItem xmlItem, Field currentField, String fieldName, + Type currentFieldType, BMap mapValue, XmlAnalyzerData analyzerData) { + + } + private void convertToArrayType(BXmlItem xmlItem, Field field, BMap mapValue, BString bCurrentFieldName, ArrayType arrayType, XmlAnalyzerData analyzerData) { Object temp = mapValue.get(bCurrentFieldName); @@ -276,10 +313,28 @@ private void convertToArrayMemberType(BXmlItem xmlItem, String fieldName, ArrayT case TypeTags.TYPE_REFERENCED_TYPE_TAG -> convertToArrayMemberType(xmlItem, fieldName, fieldType, TypeUtils.getReferredType(elementType), mapValue, analyzerData); + case TypeTags.UNION_TAG -> convertToUnionMemberType(xmlItem, fieldName, fieldType, + elementType, mapValue, analyzerData); default -> traverseXml(xmlItem.getChildrenSeq(), fieldType, analyzerData); } } + private void convertToUnionMemberType(BXmlItem xmlItem, String fieldName, ArrayType fieldType, + Type elementType, BMap mapValue, XmlAnalyzerData analyzerData) { + for (Type memberType: ((UnionType) elementType).getMemberTypes()) { + if (memberType.getTag() == TypeTags.ERROR_TAG) { + continue; + } + try { + convertToArrayMemberType(xmlItem, fieldName, fieldType, memberType, mapValue, analyzerData); + return; + } catch (Exception ex) { + // ignore + } + } + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldName, fieldType); + } + private void convertToRecordType(BXmlItem xmlItem, Type currentFieldType, String fieldName, RecordType elementType, BMap mapValue, XmlAnalyzerData analyzerData) { @@ -386,6 +441,7 @@ private void checkRestTypeAndConvert(BXmlItem xmlItem, String elemName, Type res checkRestTypeAndConvert(xmlItem, elemName, restType, ((ArrayType) restType).getElementType(), mapValue, analyzerData); } + case TypeTags.UNION_TAG -> traverseXml(xmlItem, analyzerData, elementType); default -> { BString bElementName = StringUtils.fromString(elemName); if (mapValue.containsKey(bElementName) && mapValue.get(bElementName) != null) { diff --git a/native/src/main/resources/error.properties b/native/src/main/resources/error.properties index bcb5cf9..1c4fe88 100644 --- a/native/src/main/resources/error.properties +++ b/native/src/main/resources/error.properties @@ -70,3 +70,9 @@ error.xml.parse.error=\ error.undefined.field=\ undefined field ''{0}'' in record ''{1}'' + +error.cannot.convert.source.into.expected.type=\ + source value cannot convert into ''{0}'' + +field.cannot.convert.into.type=\ + field ''{0}'' cannot convert into the type ''{1}'' From 1144ac1179aed51c59258d0ec093c47b7157df92 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Sun, 25 Aug 2024 21:03:14 +0530 Subject: [PATCH 02/16] Add initial tests for union types --- ballerina/tests/fromXml_test.bal | 8 +- ballerina/tests/union_type_test.bal | 466 ++++++++++++++++++ .../lib/data/xmldata/utils/DataUtils.java | 118 ++++- .../lib/data/xmldata/xml/XmlParser.java | 2 +- .../lib/data/xmldata/xml/XmlTraversal.java | 109 +++- native/src/main/resources/error.properties | 2 +- 6 files changed, 664 insertions(+), 41 deletions(-) create mode 100644 ballerina/tests/union_type_test.bal diff --git a/ballerina/tests/fromXml_test.bal b/ballerina/tests/fromXml_test.bal index f8f63ed..a5ae2f1 100644 --- a/ballerina/tests/fromXml_test.bal +++ b/ballerina/tests/fromXml_test.bal @@ -3340,13 +3340,13 @@ function testUnsupportedTypeNegative() { `; record {| record {|string a;|}|record {|string b;|} A; - |}|error err2 = parseAsType(xmlVal2); - test:assertEquals((err2).message(), "unsupported input type"); + |}|error val = parseAsType(xmlVal2); + test:assertEquals(val, {A: {a: "1"}}); record {| record {|string a;|}? A; - |}|error err3 = parseAsType(xmlVal2); - test:assertEquals((err3).message(), "unsupported input type"); + |}|error val2 = parseAsType(xmlVal2); + test:assertEquals(val2, {A: {a: "1"}}); } @Namespace { diff --git a/ballerina/tests/union_type_test.bal b/ballerina/tests/union_type_test.bal new file mode 100644 index 0000000..d19d4ca --- /dev/null +++ b/ballerina/tests/union_type_test.bal @@ -0,0 +1,466 @@ +import ballerina/data.xmldata; +// import ballerina/io; +import ballerina/test; + +xml x1 = xml `42`; + +type A11 record { + int[]|string \#content; +}; + +type A12 record {int[] \#content;}|record {int \#content;}; + +type A13 record {| + int[]|string...; +|}; + +type A14 record { + boolean|int \#content; +}; + +function testUnionTypes1() { + // // bug #3 + A11|error a11 = xmldata:parseAsType(x1); + test:assertEquals(a11, {"#content": "42"}); + + A12|error a12 = xmldata:parseAsType(x1); + test:assertEquals(a12, {"#content":42}); + + A13|error a13 = xmldata:parseAsType(x1); + test:assertEquals(a13, {"#content":"42"}); + + A14|error a14 = xmldata:parseAsType(x1); + test:assertEquals(a14, {"#content": 42}); +} + +xml x2 = xml `Sample Text`; + +type A21 record { + int[]|string \#content; + int|boolean|string a1; +}; + +type A22 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {int \#content; int a1;}; + +type A23 record{int \#content;}|record {string \#content; int|decimal a1;}; + +// type A24 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|float|string|int...;|}; + +type A25 record{int \#content;}|record {string \#content; int|decimal a1; int|decimal a2;}; + +type A26 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|boolean?|string?...;|}; + +function testUnionTypes2() { + A21|error a21 = xmldata:parseAsType(x2); + test:assertEquals(a21, {"#content":"Sample Text","a1":2024}); + + A22|error a22 = xmldata:parseAsType(x2); + test:assertTrue(a22 is xmldata:Error); + test:assertEquals(( a22).message(), "source value cannot convert into 'wso2/xml_data_dev:0:A22'"); + + // // bug #4 + // A23|error a23 = xmldata:parseAsType(x2); + // test:assertEquals(a23, {"#content":"Sample Text","a1":2024, "a2": 3.14}); + + // // bug #5 + // A24|error a24 = xmldata:parseAsType(x2); + // test:assertEquals(a24, {"a1":2024, "a2": 3.14}); + + A25|error a25 = xmldata:parseAsType(x2); + test:assertEquals(a25, {"#content":"Sample Text","a1":2024, "a2": 3.14}); + + A26|error a26 = xmldata:parseAsType(x2); + test:assertEquals(a26, {"#content":"Sample Text"}); +} + +xml x3 = xml `100`; + +type A31 record { + int[]|string B; +}; + +type A31P2 record { + @xmldata:Name { + value: "B" + } + string|int[] b; +}; + +type A32 record { + @xmldata:Name { + value: "B" + } + boolean|record{int \#content;}|int[] b; +}; + +type A33 record{string|int[] b1;}|record {|int|string B;|}; + +type A34 record { + record{int \#content; int b1;}|record{int \#content;}[]|record{int \#content;} B; +}; + +type A35 record {| + record{|boolean|string...;|}...; +|}; + +function testUnionTypes3() { + A31|error a31 = xmldata:parseAsType(x3); + test:assertEquals(a31, {"B":[100]}); + + A31P2|error a31p2 = xmldata:parseAsType(x3); + test:assertEquals(a31p2, {"b":"100"}); + + A32|error a32 = xmldata:parseAsType(x3); + test:assertEquals(a32, {"b":{"#content":100}}); + + A33|error a33 = xmldata:parseAsType(x3); + test:assertEquals(a33, {"B":100}); + + A34|error a34 = xmldata:parseAsType(x3); + test:assertEquals(a34, {"B":[{"#content":100}]}); + + A35|error a35 = xmldata:parseAsType(x3); + test:assertEquals(a35, {"B":{"#content":"100"}}); +} + +xml x4 = xml `Nested Content`; + +type A41 record {| + int|record{|string \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; +|}; + +type A41P2 record {| + int|record{|boolean \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; +|}; + +type A42 record {| + int|record{|int...;|}|record{string \#content; int[]|int b1;}|record{} B; +|}; + +type A43P2 record {|int[]|record{|string \#content;|} B;|}; +type A43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|A43P2; + +function testUnionTypes4() { + // // bug #2 + // A41|error a41 = xmldata:parseAsType(x4); + // test:assertEquals(a41, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); + + A41P2|error a41p2 = xmldata:parseAsType(x4); + test:assertEquals(a41p2, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); + + A42|error a42 = xmldata:parseAsType(x4); + test:assertEquals(a42, {"B":{"#content":"Nested Content","b1":99}}); + + A43|error a43 = xmldata:parseAsType(x4); + test:assertEquals(a43, {"B":{"#content":"Nested Content"}}); +} + +xml x5 = xml `123456`; + +type Ref record {|int...;|}; +type RefArr Ref[]; + +type A51 record {RefArr|int[] B;}; +type A52 record {int[]|RefArr B;}; +type A53 record {Ref|int[] B;}; +type A54 record {|Ref|int[]...;|}; +type A55 record {|Ref[]|int[]...;|}; +type A56 record {|(Ref|int)[]...;|}; +type A57 record {|(Ref|int)[] B;|}; +type A58 record {|(int|Ref)[]...;|}; + +function testUnionTypes5() { + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A51|error a51 = xmldata:parseAsType(x5); + // test:assertEquals(a51, {"B":[{"#content":123},{"#content":456}]}); + + A52|error a52 = xmldata:parseAsType(x5); + test:assertEquals(a52, {"B":[123,456]}); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A53|error a53 = xmldata:parseAsType(x5); + // test:assertEquals(a53, {); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A54|error a54 = xmldata:parseAsType(x5); + // test:assertEquals(a54, {}); + + // // bug #6 + // A55|error a55 = xmldata:parseAsType(x5); + // test:assertEquals(a55, {"B":[123,456]}); + + A56|error a56 = xmldata:parseAsType(x5); + test:assertEquals(a56, {"B":[{"#content":123},{"#content":456}]}); + + A57|error a57 = xmldata:parseAsType(x5); + test:assertEquals(a57, {"B":[{"#content":123},{"#content":456}]}); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A58|error a58 = xmldata:parseAsType(x5); + // test:assertEquals(a58, {"B":[{"#content":123},{"#content":456}]}); +} + +xml x6 = xml `ToyotaYamaha`; + +type A61 record {string C; record {|string \#content;|}[]|string B;}; +type A62 record {record {|boolean|record{(record{}|int[])[]|string \#content;}|string \#content;|}|string B; string C;}; +type A63 record {|record {|string \#content;|}[]|record {|string \#content;|}...;|}; +type A64 record {|record {|boolean|record{}|record{}[]|string \#content;|}[]|string B;|}; + +function testUnionTypes6() { + A61|error a61 = xmldata:parseAsType(x6); + test:assertEquals(a61, {"C":"Yamaha","B":[{"#content":"Toyota"}]}); + + A62|error a62 = xmldata:parseAsType(x6); + test:assertEquals(a62, {"B":"Toyota","C":"Yamaha"}); + + A63|error a63 = xmldata:parseAsType(x6); + test:assertEquals(a63, {"B":[{"#content":"Toyota"}],"C":[{"#content":"Yamaha"}]}); + + A64|error a64 = xmldata:parseAsType(x6); + test:assertEquals(a64, {"B":[{"#content":"Toyota"}]}); +} + +xml x7 = xml `BrickWaterAir`; + +type A71 record {record {|string...;|}[]|string[] B;}; +type A72 record {string[]|record {|string...;|}[] B;}; +type A73 record {record {|string \@content;|}|string[] B;}; +type A74 record {|record {|string...;|}|string[]...;|}; +type A75 record {|record {|string...;|}[]|string[]...;|}; +type A76 record {|(record {|string...;|}|string)[]...;|}; +type A77 record {|(record {|string...;|}|string)[] B;|}; +type A78 record {|(string|record {|string...;|})[]...;|}; + +function testUnionTypes7() { + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A71|error a71 = xmldata:parseAsType(x7); + // test:assertEquals(a71, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); + + A72|error a72 = xmldata:parseAsType(x7); + test:assertEquals(a72, {"B":["Brick","Water"],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); + + A73|error a73 = xmldata:parseAsType(x7); + test:assertTrue(a73 is xmldata:Error); + test:assertEquals((a73).message(), "unsupported input type"); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A74|error a74 = xmldata:parseAsType(x7); + // test:assertEquals(a74, {"B":{"#content":"Water"},"C":{"#content":"Air"}); + + // // bug #6 + // A75|error a75 = xmldata:parseAsType(x7); + // test:assertEquals(a75, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); + + // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A76|error a76 = xmldata:parseAsType(x7); + // test:assertEquals(a76, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); + + // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A77|error a77 = xmldata:parseAsType(x7); + // test:assertEquals(a77, {"B":[{"#content":"Brick"},{"#content":"Water"}]}); + + // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A78|error a78 = xmldata:parseAsType(x7); + // test:assertEquals(a78, {"B":{"#content":"Water"},"C":{"#content":"Air"}}); +} + +xml x8 = xml ` + + First + + + Second + Third + + + Fourth + Fifth + + `; + +type A81P2 record{string \#content;}[]; +type A81P1 record{string \#content;}; +type A81 record {record{|(A81P1|A81P2)[] C?;|}[] B;}; +type A81Part2 record {record{(A81P1|A81P2)[] C?;}[] B;}; +type A82P2 record{string \#content;}[][]; +type A82P1 record{string \#content;}[]; +type A82 record {record{|A82P1|A82P2 C?;|}[] B;}; +type A82Part2 record {record{A82P1|A82P2 C?;}[] B;}; +type A83P2 record{string \#content;}[]; +type A83P1 record{string \#content;}; +type A83 record {|record{|(A83P1|A83P2)[] C?;|}...;|}; +type A84P2 record{string \#content;}[]; +type A84P1 record{string \#content;}; +type A84 record {|record{|(A84P1|A84P2)[] C?;|}[]...;|}; +type A85 record{|record{}...;|}|record{|record{}[]...;|}; +type A86 record{|record{}[]...;|}|record{|record{}...;|}; + +function testUnionTypes8() { + A81|error a81 = xmldata:parseAsType(x8); + test:assertEquals(a81, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + + A81Part2|error a81p2 = xmldata:parseAsType(x8); + test:assertEquals(a81p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, + {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); + + A82|error a82 = xmldata:parseAsType(x8); + test:assertEquals(a82, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + + A82Part2|error a82p2 = xmldata:parseAsType(x8); + test:assertEquals(a82p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, + {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); + + A83|error a83 = xmldata:parseAsType(x8); + test:assertEquals(a83, {B: {}}); + + A84|error a84 = xmldata:parseAsType(x8); + test:assertEquals(a84, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + + A85|error a85 = xmldata:parseAsType(x8); + test:assertEquals(a85, {"B":{"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}}); + + A86|error a86 = xmldata:parseAsType(x8); + test:assertEquals(a86, {"B":[{"C":{"c1":"inner1","c2":"value","#content":"First"}},{"C":[{"c1":"inner2","c2":"value","#content":"Second"}, + {"c1":"inner3","c2":"value","#content":"Third"}]},{"D":{"d1":"inner4","d2":"value","#content":"Fourth"}, + "E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); +} + +xml x9 = xml ` + + 100 + 200 + 300 + + + 400 + 500 + 600 + + `; + +type A91P1 record{string[]|record{string \#content;}[] C;}; +type A91 record {A91P1[] B;}; +type A92P1 record{(string|record{string \#content;})[] C;}; +type A92 record {A92P1[] B;}; +type A93P1 record{record{string \#content;}[]|string[] C;}; +type A93 record {A93P1[] B;}; +type A94P1 record{|(record{string \#content;}|string)[]...;|}; +type A94 record {A94P1[] B;}; + +function testUnionTypes9() { + A91|error a91 = xmldata:parseAsType(x9); + test:assertEquals(a91, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); + + A92|error a92 = xmldata:parseAsType(x9); + test:assertEquals(a92, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); + + A93|error a93 = xmldata:parseAsType(x9); + test:assertEquals(a93, {"B":[{"C":[{"#content":"100"}, + {"#content":"200"},{"#content":"300"}]}, + {"C":[{"#content":"400"},{"#content":"500"}, + {"#content":"600"}]}]}); + + A94|error a94 = xmldata:parseAsType(x9); + test:assertEquals(a94, {"B":[{"C":[{"#content":"100"}, + {"#content":"200"},{"#content":"300"}]}, + {"C":[{"#content":"400"},{"#content":"500"}, + {"#content":"600"}]}]}); +} + +xml x10 = xml ` + + Deep Value1 + Deep Value2 + + + Deep Value3 + Deep Value4 + + `; + +type A101P1 record{string[]|record{string \#content;}[] C;}; +type A101 record {A101P1[] B;}; +type A102P1 record{(string|record{string \#content;})[] C;}; +type A102 record {A102P1[] B;}; +type A103P1 record{record{string \#content;}[]|string[] C;}; +type A103 record {A103P1[] B;}; +type A104P1 record{(record{string \#content;}|string)[] C;}; +type A104 record {A104P1[] B;}; + +function testUnionTypes10() { + A101|error a101 = xmldata:parseAsType(x10); + test:assertEquals(a101, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); + + A102|error a102 = xmldata:parseAsType(x10); + test:assertEquals(a102, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); + + A103|error a103 = xmldata:parseAsType(x10); + test:assertEquals(a103, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, + {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); + + A104|error a104 = xmldata:parseAsType(x10); + test:assertEquals(a104, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, + {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); +} + +public function main() { + testUnionTypes1(); + testUnionTypes2(); + testUnionTypes3(); + testUnionTypes4(); + testUnionTypes5(); + testUnionTypes6(); + testUnionTypes7(); + testUnionTypes8(); + testUnionTypes9(); + testUnionTypes10(); +} + +xml x11 = xml ` + + Deep Value1 + Deep Value2 + + + Deep Value1 + Deep Value2 + + `; + +xml x12 = xml ` + + Deep Value1 + Deep Value2 + + + Deep Value3 + Deep Value4 + + `; + +xml x13 = xml ` + + Deep Value1 + Deep Value2 + + + Deep Value1 + Deep Value2 + + + Deep Value1 + Deep Value2 + + `; + +xml x14 = xml ` + + Deep Value1 + Deep Value2 + + + Deep Value1 + Deep Value2 + + `; diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java index 5e59ab9..3940150 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java @@ -239,6 +239,7 @@ public static Object convertStringToExpType(BString value, Type expType) { result = FromString.fromStringWithType(value, PredefinedTypes.TYPE_JSON); case TypeTags.ARRAY_TAG -> result = convertStringToExpType(value, ((ArrayType) refferedType).getElementType()); + case TypeTags.UNION_TAG -> result = convertStringToUnionExpType(value, expType); default -> result = FromString.fromStringWithType(value, expType); } @@ -248,6 +249,19 @@ public static Object convertStringToExpType(BString value, Type expType) { return result; } + private static Object convertStringToUnionExpType(BString value, Type expType) { + for (Type memberType: ((UnionType) expType).getMemberTypes()) { + memberType = TypeUtils.getReferredType(memberType); + try { + return convertStringToExpType(value, memberType); + } catch (Exception ex) { + int a = 1; + // ignore + } + } + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, expType); + } + public static void validateRequiredFields(XmlAnalyzerData analyzerData) { for (Field field : analyzerData.fieldHierarchy.peek().getMembers().values()) { if (SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.REQUIRED)) { @@ -262,6 +276,19 @@ public static void validateRequiredFields(XmlAnalyzerData analyzerData) { } } + public static boolean isArrayValueAssignable(Type type) { + int typeTag = type.getTag(); + if (typeTag == TypeTags.UNION_TAG) { + for (Type memberType: ((UnionType) type).getMemberTypes()) { + memberType = TypeUtils.getReferredType(memberType); + if (isArrayValueAssignable(memberType.getTag())) { + return true; + } + } + } + return isArrayValueAssignable(typeTag); + } + public static boolean isArrayValueAssignable(int typeTag) { return typeTag == TypeTags.ARRAY_TAG || typeTag == TypeTags.ANYDATA_TAG || typeTag == TypeTags.JSON_TAG; } @@ -334,17 +361,11 @@ public static boolean isSupportedType(Type type) { private static boolean isSupportedUnionType(UnionType type) { for (Type memberType : type.getMemberTypes()) { - switch (memberType.getTag()) { - case TypeTags.RECORD_TYPE_TAG, TypeTags.OBJECT_TYPE_TAG, TypeTags.MAP_TAG, TypeTags.JSON_TAG, - TypeTags.ANYDATA_TAG, TypeTags.XML_TAG -> { - return false; - } - case TypeTags.UNION_TAG -> { - return !isSupportedUnionType(type); - } + if (isSupportedType(memberType)) { + return true; } } - return true; + return false; } public static void updateOptions(BMap options, XmlAnalyzerData analyzerData) { @@ -476,7 +497,8 @@ private static void processRecordField(Type fieldType, BMap ann switch (fieldType.getTag()) { case TypeTags.RECORD_TYPE_TAG -> processRecord(key, annotations, recordValue, value, (RecordType) fieldType); - case TypeTags.ARRAY_TAG -> processArray(fieldType, annotations, recordValue, entry); + case TypeTags.ARRAY_TAG -> processArray(TypeUtils.getReferredType(((ArrayType) fieldType) + .getElementType()), annotations, recordValue, entry); case TypeTags.TYPE_REFERENCED_TYPE_TAG -> { Type referredType = TypeUtils.getReferredType(fieldType); if (referredType.getTag() != TypeTags.RECORD_TYPE_TAG) { @@ -485,6 +507,17 @@ private static void processRecordField(Type fieldType, BMap ann } processTypeReferenceType(fieldType, annotations, recordValue, key, value); } + case TypeTags.UNION_TAG -> { + for (Type memberType: ((UnionType) fieldType).getMemberTypes()) { + try { + processRecordField(memberType, annotations, recordValue, entry, key, value); + return; + } catch (Exception ex) { + //ignore + } + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldType); + } + } default -> addPrimitiveValue(addFieldNamespaceAnnotation(key, key, annotations, recordValue), annotations, recordValue, value); } @@ -640,17 +673,26 @@ private static void addPrimitiveValue(QName qName, BMap annotat } @SuppressWarnings("unchecked") - private static void processArray(Type childType, BMap annotations, + private static void processArray(Type elementType, BMap annotations, BMap record, Map.Entry entry) { - Type elementType = TypeUtils.getReferredType(((ArrayType) childType).getElementType()); BMap annotationRecord = ValueCreator.createMapValue(Constants.JSON_MAP_TYPE); String keyName = entry.getKey().getValue(); - if (annotations.size() > 0) { + if (!annotations.isEmpty()) { keyName = getKeyNameFromAnnotation(annotations, keyName); processSubRecordAnnotation(annotations, annotationRecord); } BArray arrayValue = (BArray) entry.getValue(); - if (elementType.getTag() == TypeTags.RECORD_TYPE_TAG) { + if (elementType.getTag() == TypeTags.UNION_TAG) { + for (Type memberType: ((UnionType) elementType).getMemberTypes()) { + try { + processArray(memberType, annotations, record, entry); + return; + } catch (Exception ex) { + //ignore + } + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, elementType); + } + } else if (elementType.getTag() == TypeTags.RECORD_TYPE_TAG) { List> records = new ArrayList<>(); for (int i = 0; i < arrayValue.getLength(); i++) { BMap subRecord = addFields(((BMap) arrayValue.get(i)), @@ -923,12 +965,12 @@ public static boolean isSimpleType(Type type) { * @since 0.1.0 */ public static class XmlAnalyzerData { - public final Stack nodesStack = new Stack<>(); - public final Stack> fieldHierarchy = new Stack<>(); - public final Stack> visitedFieldHierarchy = new Stack<>(); - public final Stack> attributeHierarchy = new Stack<>(); - public final Stack restTypes = new Stack<>(); - public final Stack> arrayIndexes = new Stack<>(); + public Stack nodesStack = new Stack<>(); + public Stack> fieldHierarchy = new Stack<>(); + public Stack> visitedFieldHierarchy = new Stack<>(); + public Stack> attributeHierarchy = new Stack<>(); + public Stack restTypes = new Stack<>(); + public Stack> arrayIndexes = new Stack<>(); public RecordType rootRecord; public Field currentField; public QualifiedName rootElement; @@ -936,5 +978,41 @@ public static class XmlAnalyzerData { public String textFieldName; public boolean allowDataProjection; public boolean useSemanticEquality; + + @SuppressWarnings("unchecked") + public static XmlAnalyzerData copy(XmlAnalyzerData analyzerData) { + XmlAnalyzerData data = new XmlAnalyzerData(); + data.nodesStack = (Stack) analyzerData.nodesStack.clone(); + data.fieldHierarchy = (Stack>) analyzerData.fieldHierarchy.clone(); + data.visitedFieldHierarchy = (Stack>) analyzerData.visitedFieldHierarchy.clone(); + data.attributeHierarchy = (Stack>) analyzerData.attributeHierarchy.clone(); + data.restTypes = (Stack) analyzerData.restTypes.clone(); + data.arrayIndexes = (Stack>) analyzerData.arrayIndexes.clone(); + data.rootRecord = analyzerData.rootRecord; + data.currentField = analyzerData.currentField; + data.rootElement = analyzerData.rootElement; + data.attributePrefix = analyzerData.attributePrefix; + data.textFieldName = analyzerData.textFieldName; + data.allowDataProjection = analyzerData.allowDataProjection; + data.useSemanticEquality = analyzerData.useSemanticEquality; + + return data; + } + + public void resetFrom(XmlAnalyzerData analyzerData) { + this.nodesStack = analyzerData.nodesStack; + this.fieldHierarchy = analyzerData.fieldHierarchy; + this.visitedFieldHierarchy = analyzerData.visitedFieldHierarchy; + this.attributeHierarchy = analyzerData.attributeHierarchy; + this.restTypes = analyzerData.restTypes; + this.arrayIndexes = analyzerData.arrayIndexes; + this.rootRecord = analyzerData.rootRecord; + this.currentField = analyzerData.currentField; + this.rootElement = analyzerData.rootElement; + this.attributePrefix = analyzerData.attributePrefix; + this.textFieldName = analyzerData.textFieldName; + this.allowDataProjection = analyzerData.allowDataProjection; + this.useSemanticEquality = analyzerData.useSemanticEquality; + } } } diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java index ddbffcf..1226db7 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java @@ -816,7 +816,7 @@ private BString readElementRest(XMLStreamReader xmlStreamReader, XmlParserData x return currentFieldName; } - if (!DataUtils.isArrayValueAssignable(restType.getTag())) { + if (!DataUtils.isArrayValueAssignable(restType)) { throw DiagnosticLog.error( DiagnosticErrorCode.FOUND_ARRAY_FOR_NON_ARRAY_TYPE, restType, elemQName.getLocalPart()); } diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java index cda93cd..ed06087 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java @@ -99,11 +99,9 @@ public Object traverseXml(BXml xml, XmlAnalyzerData analyzerData, Type type) { return traverseXmlWithMapAsExpectedType(xml, referredType, analyzerData); } case TypeTags.UNION_TAG -> { - return traverseXmlToUnion(xml, analyzerData, type); - } - default -> { - throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, Constants.RECORD_OR_MAP, type); + return traverseXmlToUnion(xml, analyzerData, referredType); } + default -> throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, Constants.RECORD_OR_MAP, type); } } @@ -126,13 +124,17 @@ private Object traverseXmlWithMapAsExpectedType(BXml xml, Type referredType, Xml private Object traverseXmlToUnion(BXml xml, XmlAnalyzerData options, Type type) { UnionType unionType = (UnionType) type; + XmlAnalyzerData clonedAnalyzerData = XmlAnalyzerData.copy(options); for (Type memberType: unionType.getMemberTypes()) { + memberType = TypeUtils.getReferredType(memberType); try { if (memberType.getTag() == TypeTags.ERROR_TAG) { continue; } return traverseXml(xml, options, memberType); } catch (Exception ex) { + int a = 1; + options.resetFrom(clonedAnalyzerData); // ignore } } @@ -175,8 +177,31 @@ private void convertText(String text, XmlAnalyzerData analyzerData) { BString fieldName = StringUtils.fromString(currentField.getFieldName()); Type fieldType = TypeUtils.getReferredType(currentField.getFieldType()); - Object convertedValue = DataUtils.convertStringToExpType(StringUtils.fromString(text), fieldType); + Object convertedValue = null; Object value = mapValue.get(fieldName); + if (fieldType.getTag() == TypeTags.UNION_TAG) { + XmlAnalyzerData clonedAnalyzerData = XmlAnalyzerData.copy(analyzerData); + for (Type memberType: ((UnionType) fieldType).getMemberTypes()) { + try { + if (!(value instanceof BArray) && memberType.getTag() == TypeTags.ARRAY_TAG) { + continue; + } + convertedValue = DataUtils.convertStringToExpType(StringUtils.fromString(text), memberType); + fieldType = memberType; + break; + } catch (Exception ex) { + int a = 1; + analyzerData.resetFrom(clonedAnalyzerData); + // ignore + } + } + if (convertedValue == null) { + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldType); + } + } else { + convertedValue = DataUtils.convertStringToExpType(StringUtils.fromString(text), fieldType); + } + if (value instanceof BArray) { if (fieldName.getValue().equals(textFieldName)) { mapValue.put(fieldName, convertedValue); @@ -196,6 +221,9 @@ private void convertText(String text, XmlAnalyzerData analyzerData) { } ((BArray) value).add(currentIndex, convertedValue); } else { + if (fieldType.getTag() == TypeTags.ARRAY_TAG) { + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldType); + } mapValue.put(fieldName, convertedValue); } } @@ -208,7 +236,7 @@ private void convertElement(BXmlItem xmlItem, XmlAnalyzerData analyzerData) { if (analyzerData.visitedFieldHierarchy.peek().contains(elementQName)) { currentField = analyzerData.visitedFieldHierarchy.peek().get(elementQName); Type fieldType = TypeUtils.getReferredType(currentField.getFieldType()); - if (!DataUtils.isArrayValueAssignable(fieldType.getTag())) { + if (!DataUtils.isArrayValueAssignable(fieldType)) { throw DiagnosticLog.error(DiagnosticErrorCode.FOUND_ARRAY_FOR_NON_ARRAY_TYPE, fieldType, currentField.getFieldName()); } @@ -266,14 +294,31 @@ private void convertToFieldType(BXmlItem xmlItem, Field currentField, String fie case TypeTags.TYPE_REFERENCED_TYPE_TAG -> convertToFieldType(xmlItem, currentField, fieldName, TypeUtils.getReferredType(currentFieldType), mapValue, analyzerData); - case TypeTags.UNION_TAG -> traverseXml(xmlItem, analyzerData, currentFieldType); + case TypeTags.UNION_TAG -> convertFieldTypeToUnion(xmlItem, currentField, fieldName, + currentFieldType, mapValue, analyzerData); default -> traverseXml(xmlItem.getChildrenSeq(), currentFieldType, analyzerData); } } - private void convertFieldTypeToUnionType(BXmlItem xmlItem, Field currentField, String fieldName, - Type currentFieldType, BMap mapValue, XmlAnalyzerData analyzerData) { - + private void convertFieldTypeToUnion(BXmlItem xmlItem, Field currentField, String fieldName, + Type currentFieldType, BMap mapValue, XmlAnalyzerData analyzerData) { + XmlAnalyzerData clonedAnalyzerData = XmlAnalyzerData.copy(analyzerData); + for (Type memberType: ((UnionType) currentFieldType).getMemberTypes()) { + memberType = TypeUtils.getReferredType(memberType); + try { + if (memberType.getTag() == TypeTags.ERROR_TAG) { + continue; + } + convertToFieldType(xmlItem, currentField, fieldName, memberType, mapValue, analyzerData); + return; + } catch (Exception ex) { + analyzerData.resetFrom(clonedAnalyzerData); + mapValue.put(StringUtils.fromString(fieldName), null); + int a = 1; + // ignore + } + } + throw DiagnosticLog.error(DiagnosticErrorCode.UNSUPPORTED_TYPE); } private void convertToArrayType(BXmlItem xmlItem, Field field, BMap mapValue, @@ -321,7 +366,9 @@ private void convertToArrayMemberType(BXmlItem xmlItem, String fieldName, ArrayT private void convertToUnionMemberType(BXmlItem xmlItem, String fieldName, ArrayType fieldType, Type elementType, BMap mapValue, XmlAnalyzerData analyzerData) { + XmlAnalyzerData clonedAnalyzerData = XmlAnalyzerData.copy(analyzerData); for (Type memberType: ((UnionType) elementType).getMemberTypes()) { + memberType = TypeUtils.getReferredType(memberType); if (memberType.getTag() == TypeTags.ERROR_TAG) { continue; } @@ -329,6 +376,8 @@ private void convertToUnionMemberType(BXmlItem xmlItem, String fieldName, ArrayT convertToArrayMemberType(xmlItem, fieldName, fieldType, memberType, mapValue, analyzerData); return; } catch (Exception ex) { + analyzerData.resetFrom(clonedAnalyzerData); + int a = 1; // ignore } } @@ -400,11 +449,16 @@ private BMap updateNextMappingValue(Type type, String fieldName } Object temp = currentMapValue.get(StringUtils.fromString(fieldName)); - if (temp instanceof BArray) { + if (temp instanceof BArray tempArray) { ArrayType arrayType = (ArrayType) fieldType; - int currentIndex = analyzerData.arrayIndexes.peek().get(fieldName); + Integer peek = analyzerData.arrayIndexes.peek().get(fieldName); + int currentIndex = tempArray.size(); + if (peek != null) { + currentIndex = peek; + } + if (arrayType.getState() == ArrayType.ArrayState.OPEN || currentIndex < arrayType.getSize()) { - ((BArray) temp).add(currentIndex, nextValue); + tempArray.add(currentIndex, nextValue); } else { DataUtils.logArrayMismatchErrorIfProjectionNotAllowed(analyzerData.allowDataProjection); } @@ -441,7 +495,8 @@ private void checkRestTypeAndConvert(BXmlItem xmlItem, String elemName, Type res checkRestTypeAndConvert(xmlItem, elemName, restType, ((ArrayType) restType).getElementType(), mapValue, analyzerData); } - case TypeTags.UNION_TAG -> traverseXml(xmlItem, analyzerData, elementType); + case TypeTags.UNION_TAG -> checkRestTypeAndConvertForUnionTypes(xmlItem, elemName, restType, + elementType, mapValue, analyzerData); default -> { BString bElementName = StringUtils.fromString(elemName); if (mapValue.containsKey(bElementName) && mapValue.get(bElementName) != null) { @@ -463,6 +518,30 @@ private void checkRestTypeAndConvert(BXmlItem xmlItem, String elemName, Type res } } + private void checkRestTypeAndConvertForUnionTypes(BXmlItem xmlItem, String elemName, + Type restType, Type elementType, BMap mapValue, XmlAnalyzerData analyzerData) { + boolean isRestTypeUnion = restType.getTag() == TypeTags.UNION_TAG; + XmlAnalyzerData clonedAnalyzerData = XmlAnalyzerData.copy(analyzerData); + + for (Type memberType: ((UnionType) elementType).getMemberTypes()) { + memberType = TypeUtils.getReferredType(memberType); + if (memberType.getTag() == TypeTags.ERROR_TAG) { + continue; + } + try { + checkRestTypeAndConvert(xmlItem, elemName, isRestTypeUnion ? memberType : restType, + memberType, mapValue, analyzerData); + return; + } catch (Exception ex) { + analyzerData.resetFrom(clonedAnalyzerData); + mapValue.put(StringUtils.fromString(elemName), null); + int a = 1; + // ignore + } + } + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, elementType); + } + private void handleArrayValueForRestType(BXmlItem xmlItem, String elemName, Type restType, BMap mapValue, XmlAnalyzerData analyzerData) { BString bElementName = StringUtils.fromString(elemName); @@ -470,7 +549,7 @@ private void handleArrayValueForRestType(BXmlItem xmlItem, String elemName, Type boolean useSemanticEquality = analyzerData.useSemanticEquality; BArray arrayValue; if (!(currentElement instanceof BArray)) { - if (!DataUtils.isArrayValueAssignable(restType.getTag())) { + if (!DataUtils.isArrayValueAssignable(restType)) { throw DiagnosticLog.error(DiagnosticErrorCode.FOUND_ARRAY_FOR_NON_ARRAY_TYPE, restType, elemName); } diff --git a/native/src/main/resources/error.properties b/native/src/main/resources/error.properties index 1c4fe88..108ea74 100644 --- a/native/src/main/resources/error.properties +++ b/native/src/main/resources/error.properties @@ -74,5 +74,5 @@ error.undefined.field=\ error.cannot.convert.source.into.expected.type=\ source value cannot convert into ''{0}'' -field.cannot.convert.into.type=\ +error.field.cannot.convert.into.type=\ field ''{0}'' cannot convert into the type ''{1}'' From 8c627e05fa14620108b56d92cbdce474152235fe Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Sun, 25 Aug 2024 22:34:01 +0530 Subject: [PATCH 03/16] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 81e9251..7dd6cb5 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -55,26 +55,6 @@ modules = [ {org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"} ] -[[package]] -org = "ballerina" -name = "lang.__internal" -version = "0.0.0" -scope = "testOnly" -dependencies = [ - {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.object"} -] - -[[package]] -org = "ballerina" -name = "lang.array" -version = "0.0.0" -scope = "testOnly" -dependencies = [ - {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.__internal"} -] - [[package]] org = "ballerina" name = "lang.error" @@ -84,12 +64,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] -[[package]] -org = "ballerina" -name = "lang.object" -version = "0.0.0" -scope = "testOnly" - [[package]] org = "ballerina" name = "lang.value" @@ -106,7 +80,6 @@ version = "0.0.0" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.array"}, {org = "ballerina", name = "lang.error"} ] modules = [ From 44b3ed2c5a772bec176c884544f728b879666c50 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Sun, 25 Aug 2024 22:34:57 +0530 Subject: [PATCH 04/16] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 7dd6cb5..81e9251 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -55,6 +55,26 @@ modules = [ {org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"} ] +[[package]] +org = "ballerina" +name = "lang.__internal" +version = "0.0.0" +scope = "testOnly" +dependencies = [ + {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.object"} +] + +[[package]] +org = "ballerina" +name = "lang.array" +version = "0.0.0" +scope = "testOnly" +dependencies = [ + {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.__internal"} +] + [[package]] org = "ballerina" name = "lang.error" @@ -64,6 +84,12 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] +[[package]] +org = "ballerina" +name = "lang.object" +version = "0.0.0" +scope = "testOnly" + [[package]] org = "ballerina" name = "lang.value" @@ -80,6 +106,7 @@ version = "0.0.0" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.array"}, {org = "ballerina", name = "lang.error"} ] modules = [ From 1ca2d9cbb48382dc9c0231ea0b20adb7e4ba7b74 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Mon, 26 Aug 2024 21:57:21 +0530 Subject: [PATCH 05/16] Add initial implement for xml str union types --- ballerina/tests/union_type_test.bal | 946 ++++++++++-------- .../lib/data/xmldata/utils/DataUtils.java | 41 +- .../data/xmldata/xml/QualifiedNameMap.java | 9 + .../lib/data/xmldata/xml/XmlParser.java | 189 +++- .../lib/data/xmldata/xml/XmlTraversal.java | 16 +- 5 files changed, 749 insertions(+), 452 deletions(-) diff --git a/ballerina/tests/union_type_test.bal b/ballerina/tests/union_type_test.bal index d19d4ca..85029b1 100644 --- a/ballerina/tests/union_type_test.bal +++ b/ballerina/tests/union_type_test.bal @@ -1,466 +1,578 @@ -import ballerina/data.xmldata; -// import ballerina/io; -import ballerina/test; +// import ballerina/data.xmldata; +// // import ballerina/io; +// import ballerina/test; -xml x1 = xml `42`; +// xml x1 = xml `42`; -type A11 record { - int[]|string \#content; -}; +// type A11 record { +// int[]|string \#content; +// }; -type A12 record {int[] \#content;}|record {int \#content;}; +// type A12 record {int[] \#content;}|record {int \#content;}; -type A13 record {| - int[]|string...; -|}; +// type A13 record {| +// int[]|string...; +// |}; -type A14 record { - boolean|int \#content; -}; +// type A14 record { +// boolean|int \#content; +// }; -function testUnionTypes1() { - // // bug #3 - A11|error a11 = xmldata:parseAsType(x1); - test:assertEquals(a11, {"#content": "42"}); +// function testUnionTypes1() { +// // // bug #3 +// A11|error a11 = xmldata:parseAsType(x1); +// test:assertEquals(a11, {"#content": "42"}); - A12|error a12 = xmldata:parseAsType(x1); - test:assertEquals(a12, {"#content":42}); +// A12|error a12 = xmldata:parseAsType(x1); +// test:assertEquals(a12, {"#content":42}); - A13|error a13 = xmldata:parseAsType(x1); - test:assertEquals(a13, {"#content":"42"}); +// A13|error a13 = xmldata:parseAsType(x1); +// test:assertEquals(a13, {"#content":"42"}); - A14|error a14 = xmldata:parseAsType(x1); - test:assertEquals(a14, {"#content": 42}); -} +// A14|error a14 = xmldata:parseAsType(x1); +// test:assertEquals(a14, {"#content": 42}); +// } -xml x2 = xml `Sample Text`; +// xml x2 = xml `Sample Text`; -type A21 record { - int[]|string \#content; - int|boolean|string a1; -}; +// type A21 record { +// int[]|string \#content; +// int|boolean|string a1; +// }; -type A22 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {int \#content; int a1;}; +// type A22 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {int \#content; int a1;}; -type A23 record{int \#content;}|record {string \#content; int|decimal a1;}; +// type A23 record{int \#content;}|record {string \#content; int|decimal a1;}; -// type A24 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|float|string|int...;|}; +// // type A24 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|float|string|int...;|}; -type A25 record{int \#content;}|record {string \#content; int|decimal a1; int|decimal a2;}; +// type A25 record{int \#content;}|record {string \#content; int|decimal a1; int|decimal a2;}; -type A26 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|boolean?|string?...;|}; +// type A26 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|boolean?|string?...;|}; -function testUnionTypes2() { - A21|error a21 = xmldata:parseAsType(x2); - test:assertEquals(a21, {"#content":"Sample Text","a1":2024}); +// function testUnionTypes2() { +// A21|error a21 = xmldata:parseAsType(x2); +// test:assertEquals(a21, {"#content":"Sample Text","a1":2024}); - A22|error a22 = xmldata:parseAsType(x2); - test:assertTrue(a22 is xmldata:Error); - test:assertEquals(( a22).message(), "source value cannot convert into 'wso2/xml_data_dev:0:A22'"); +// A22|error a22 = xmldata:parseAsType(x2); +// test:assertTrue(a22 is xmldata:Error); +// test:assertEquals(( a22).message(), "source value cannot convert into 'wso2/xml_data_dev:0:A22'"); - // // bug #4 - // A23|error a23 = xmldata:parseAsType(x2); - // test:assertEquals(a23, {"#content":"Sample Text","a1":2024, "a2": 3.14}); +// // // bug #4 +// // A23|error a23 = xmldata:parseAsType(x2); +// // test:assertEquals(a23, {"#content":"Sample Text","a1":2024, "a2": 3.14}); - // // bug #5 - // A24|error a24 = xmldata:parseAsType(x2); - // test:assertEquals(a24, {"a1":2024, "a2": 3.14}); +// // // bug #5 +// // A24|error a24 = xmldata:parseAsType(x2); +// // test:assertEquals(a24, {"a1":2024, "a2": 3.14}); - A25|error a25 = xmldata:parseAsType(x2); - test:assertEquals(a25, {"#content":"Sample Text","a1":2024, "a2": 3.14}); +// A25|error a25 = xmldata:parseAsType(x2); +// test:assertEquals(a25, {"#content":"Sample Text","a1":2024, "a2": 3.14}); - A26|error a26 = xmldata:parseAsType(x2); - test:assertEquals(a26, {"#content":"Sample Text"}); -} +// A26|error a26 = xmldata:parseAsType(x2); +// test:assertEquals(a26, {"#content":"Sample Text"}); +// } -xml x3 = xml `100`; +// xml x3 = xml `100`; -type A31 record { - int[]|string B; -}; +// type A31 record { +// int[]|string B; +// }; -type A31P2 record { - @xmldata:Name { - value: "B" - } - string|int[] b; -}; +// type A31P2 record { +// @xmldata:Name { +// value: "B" +// } +// string|int[] b; +// }; -type A32 record { - @xmldata:Name { - value: "B" - } - boolean|record{int \#content;}|int[] b; -}; +// type A32 record { +// @xmldata:Name { +// value: "B" +// } +// boolean|record{int \#content;}|int[] b; +// }; -type A33 record{string|int[] b1;}|record {|int|string B;|}; +// type A33 record{string|int[] b1;}|record {|int|string B;|}; -type A34 record { - record{int \#content; int b1;}|record{int \#content;}[]|record{int \#content;} B; -}; +// type A34 record { +// record{int \#content; int b1;}|record{int \#content;}[]|record{int \#content;} B; +// }; -type A35 record {| - record{|boolean|string...;|}...; -|}; +// type A35 record {| +// record{|boolean|string...;|}...; +// |}; -function testUnionTypes3() { - A31|error a31 = xmldata:parseAsType(x3); - test:assertEquals(a31, {"B":[100]}); +// function testUnionTypes3() { +// A31|error a31 = xmldata:parseAsType(x3); +// test:assertEquals(a31, {"B":[100]}); - A31P2|error a31p2 = xmldata:parseAsType(x3); - test:assertEquals(a31p2, {"b":"100"}); +// A31P2|error a31p2 = xmldata:parseAsType(x3); +// test:assertEquals(a31p2, {"b":"100"}); - A32|error a32 = xmldata:parseAsType(x3); - test:assertEquals(a32, {"b":{"#content":100}}); +// A32|error a32 = xmldata:parseAsType(x3); +// test:assertEquals(a32, {"b":{"#content":100}}); - A33|error a33 = xmldata:parseAsType(x3); - test:assertEquals(a33, {"B":100}); +// A33|error a33 = xmldata:parseAsType(x3); +// test:assertEquals(a33, {"B":100}); - A34|error a34 = xmldata:parseAsType(x3); - test:assertEquals(a34, {"B":[{"#content":100}]}); +// A34|error a34 = xmldata:parseAsType(x3); +// test:assertEquals(a34, {"B":[{"#content":100}]}); - A35|error a35 = xmldata:parseAsType(x3); - test:assertEquals(a35, {"B":{"#content":"100"}}); -} +// A35|error a35 = xmldata:parseAsType(x3); +// test:assertEquals(a35, {"B":{"#content":"100"}}); +// } -xml x4 = xml `Nested Content`; +// xml x4 = xml `Nested Content`; -type A41 record {| - int|record{|string \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; -|}; +// type A41 record {| +// int|record{|string \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; +// |}; -type A41P2 record {| - int|record{|boolean \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; -|}; +// type A41P2 record {| +// int|record{|boolean \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; +// |}; -type A42 record {| - int|record{|int...;|}|record{string \#content; int[]|int b1;}|record{} B; -|}; +// type A42 record {| +// int|record{|int...;|}|record{string \#content; int[]|int b1;}|record{} B; +// |}; -type A43P2 record {|int[]|record{|string \#content;|} B;|}; -type A43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|A43P2; +// type A43P2 record {|int[]|record{|string \#content;|} B;|}; +// type A43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|A43P2; -function testUnionTypes4() { - // // bug #2 - // A41|error a41 = xmldata:parseAsType(x4); - // test:assertEquals(a41, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); +// function testUnionTypes4() { +// // // bug #2 +// // A41|error a41 = xmldata:parseAsType(x4); +// // test:assertEquals(a41, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); - A41P2|error a41p2 = xmldata:parseAsType(x4); - test:assertEquals(a41p2, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); +// A41P2|error a41p2 = xmldata:parseAsType(x4); +// test:assertEquals(a41p2, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); - A42|error a42 = xmldata:parseAsType(x4); - test:assertEquals(a42, {"B":{"#content":"Nested Content","b1":99}}); +// A42|error a42 = xmldata:parseAsType(x4); +// test:assertEquals(a42, {"B":{"#content":"Nested Content","b1":99}}); - A43|error a43 = xmldata:parseAsType(x4); - test:assertEquals(a43, {"B":{"#content":"Nested Content"}}); -} +// A43|error a43 = xmldata:parseAsType(x4); +// test:assertEquals(a43, {"B":{"#content":"Nested Content"}}); +// } -xml x5 = xml `123456`; +// xml x5 = xml `123456`; -type Ref record {|int...;|}; -type RefArr Ref[]; +// type Ref record {|int...;|}; +// type RefArr Ref[]; -type A51 record {RefArr|int[] B;}; -type A52 record {int[]|RefArr B;}; -type A53 record {Ref|int[] B;}; -type A54 record {|Ref|int[]...;|}; -type A55 record {|Ref[]|int[]...;|}; -type A56 record {|(Ref|int)[]...;|}; -type A57 record {|(Ref|int)[] B;|}; -type A58 record {|(int|Ref)[]...;|}; +// type A51 record {RefArr|int[] B;}; +// type A52 record {int[]|RefArr B;}; +// type A53 record {Ref|int[] B;}; +// type A54 record {|Ref|int[]...;|}; +// type A55 record {|Ref[]|int[]...;|}; +// type A56 record {|(Ref|int)[]...;|}; +// type A57 record {|(Ref|int)[] B;|}; +// type A58 record {|(int|Ref)[]...;|}; -function testUnionTypes5() { - // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A51|error a51 = xmldata:parseAsType(x5); - // test:assertEquals(a51, {"B":[{"#content":123},{"#content":456}]}); - - A52|error a52 = xmldata:parseAsType(x5); - test:assertEquals(a52, {"B":[123,456]}); - - // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A53|error a53 = xmldata:parseAsType(x5); - // test:assertEquals(a53, {); - - // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A54|error a54 = xmldata:parseAsType(x5); - // test:assertEquals(a54, {}); - - // // bug #6 - // A55|error a55 = xmldata:parseAsType(x5); - // test:assertEquals(a55, {"B":[123,456]}); - - A56|error a56 = xmldata:parseAsType(x5); - test:assertEquals(a56, {"B":[{"#content":123},{"#content":456}]}); - - A57|error a57 = xmldata:parseAsType(x5); - test:assertEquals(a57, {"B":[{"#content":123},{"#content":456}]}); - - // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A58|error a58 = xmldata:parseAsType(x5); - // test:assertEquals(a58, {"B":[{"#content":123},{"#content":456}]}); -} - -xml x6 = xml `ToyotaYamaha`; - -type A61 record {string C; record {|string \#content;|}[]|string B;}; -type A62 record {record {|boolean|record{(record{}|int[])[]|string \#content;}|string \#content;|}|string B; string C;}; -type A63 record {|record {|string \#content;|}[]|record {|string \#content;|}...;|}; -type A64 record {|record {|boolean|record{}|record{}[]|string \#content;|}[]|string B;|}; - -function testUnionTypes6() { - A61|error a61 = xmldata:parseAsType(x6); - test:assertEquals(a61, {"C":"Yamaha","B":[{"#content":"Toyota"}]}); - - A62|error a62 = xmldata:parseAsType(x6); - test:assertEquals(a62, {"B":"Toyota","C":"Yamaha"}); - - A63|error a63 = xmldata:parseAsType(x6); - test:assertEquals(a63, {"B":[{"#content":"Toyota"}],"C":[{"#content":"Yamaha"}]}); - - A64|error a64 = xmldata:parseAsType(x6); - test:assertEquals(a64, {"B":[{"#content":"Toyota"}]}); -} - -xml x7 = xml `BrickWaterAir`; - -type A71 record {record {|string...;|}[]|string[] B;}; -type A72 record {string[]|record {|string...;|}[] B;}; -type A73 record {record {|string \@content;|}|string[] B;}; -type A74 record {|record {|string...;|}|string[]...;|}; -type A75 record {|record {|string...;|}[]|string[]...;|}; -type A76 record {|(record {|string...;|}|string)[]...;|}; -type A77 record {|(record {|string...;|}|string)[] B;|}; -type A78 record {|(string|record {|string...;|})[]...;|}; - -function testUnionTypes7() { - // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A71|error a71 = xmldata:parseAsType(x7); - // test:assertEquals(a71, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); - - A72|error a72 = xmldata:parseAsType(x7); - test:assertEquals(a72, {"B":["Brick","Water"],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); - - A73|error a73 = xmldata:parseAsType(x7); - test:assertTrue(a73 is xmldata:Error); - test:assertEquals((a73).message(), "unsupported input type"); - - // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A74|error a74 = xmldata:parseAsType(x7); - // test:assertEquals(a74, {"B":{"#content":"Water"},"C":{"#content":"Air"}); - - // // bug #6 - // A75|error a75 = xmldata:parseAsType(x7); - // test:assertEquals(a75, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); - - // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A76|error a76 = xmldata:parseAsType(x7); - // test:assertEquals(a76, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); - - // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A77|error a77 = xmldata:parseAsType(x7); - // test:assertEquals(a77, {"B":[{"#content":"Brick"},{"#content":"Water"}]}); - - // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A78|error a78 = xmldata:parseAsType(x7); - // test:assertEquals(a78, {"B":{"#content":"Water"},"C":{"#content":"Air"}}); -} - -xml x8 = xml ` - - First - - - Second - Third - - - Fourth - Fifth - - `; - -type A81P2 record{string \#content;}[]; -type A81P1 record{string \#content;}; -type A81 record {record{|(A81P1|A81P2)[] C?;|}[] B;}; -type A81Part2 record {record{(A81P1|A81P2)[] C?;}[] B;}; -type A82P2 record{string \#content;}[][]; -type A82P1 record{string \#content;}[]; -type A82 record {record{|A82P1|A82P2 C?;|}[] B;}; -type A82Part2 record {record{A82P1|A82P2 C?;}[] B;}; -type A83P2 record{string \#content;}[]; -type A83P1 record{string \#content;}; -type A83 record {|record{|(A83P1|A83P2)[] C?;|}...;|}; -type A84P2 record{string \#content;}[]; -type A84P1 record{string \#content;}; -type A84 record {|record{|(A84P1|A84P2)[] C?;|}[]...;|}; -type A85 record{|record{}...;|}|record{|record{}[]...;|}; -type A86 record{|record{}[]...;|}|record{|record{}...;|}; - -function testUnionTypes8() { - A81|error a81 = xmldata:parseAsType(x8); - test:assertEquals(a81, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - - A81Part2|error a81p2 = xmldata:parseAsType(x8); - test:assertEquals(a81p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, - {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); - - A82|error a82 = xmldata:parseAsType(x8); - test:assertEquals(a82, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - - A82Part2|error a82p2 = xmldata:parseAsType(x8); - test:assertEquals(a82p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, - {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); - - A83|error a83 = xmldata:parseAsType(x8); - test:assertEquals(a83, {B: {}}); - - A84|error a84 = xmldata:parseAsType(x8); - test:assertEquals(a84, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - - A85|error a85 = xmldata:parseAsType(x8); - test:assertEquals(a85, {"B":{"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}}); - - A86|error a86 = xmldata:parseAsType(x8); - test:assertEquals(a86, {"B":[{"C":{"c1":"inner1","c2":"value","#content":"First"}},{"C":[{"c1":"inner2","c2":"value","#content":"Second"}, - {"c1":"inner3","c2":"value","#content":"Third"}]},{"D":{"d1":"inner4","d2":"value","#content":"Fourth"}, - "E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); -} +// function testUnionTypes5() { +// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 +// // A51|error a51 = xmldata:parseAsType(x5); +// // test:assertEquals(a51, {"B":[{"#content":123},{"#content":456}]}); + +// A52|error a52 = xmldata:parseAsType(x5); +// test:assertEquals(a52, {"B":[123,456]}); + +// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 +// // A53|error a53 = xmldata:parseAsType(x5); +// // test:assertEquals(a53, {); + +// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 +// // A54|error a54 = xmldata:parseAsType(x5); +// // test:assertEquals(a54, {}); + +// // // bug #6 +// // A55|error a55 = xmldata:parseAsType(x5); +// // test:assertEquals(a55, {"B":[123,456]}); + +// A56|error a56 = xmldata:parseAsType(x5); +// test:assertEquals(a56, {"B":[{"#content":123},{"#content":456}]}); + +// A57|error a57 = xmldata:parseAsType(x5); +// test:assertEquals(a57, {"B":[{"#content":123},{"#content":456}]}); + +// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 +// // A58|error a58 = xmldata:parseAsType(x5); +// // test:assertEquals(a58, {"B":[{"#content":123},{"#content":456}]}); +// } + +// xml x6 = xml `ToyotaYamaha`; + +// type A61 record {string C; record {|string \#content;|}[]|string B;}; +// type A62 record {record {|boolean|record{(record{}|int[])[]|string \#content;}|string \#content;|}|string B; string C;}; +// type A63 record {|record {|string \#content;|}[]|record {|string \#content;|}...;|}; +// type A64 record {|record {|boolean|record{}|record{}[]|string \#content;|}[]|string B;|}; + +// function testUnionTypes6() { +// A61|error a61 = xmldata:parseAsType(x6); +// test:assertEquals(a61, {"C":"Yamaha","B":[{"#content":"Toyota"}]}); + +// A62|error a62 = xmldata:parseAsType(x6); +// test:assertEquals(a62, {"B":"Toyota","C":"Yamaha"}); + +// A63|error a63 = xmldata:parseAsType(x6); +// test:assertEquals(a63, {"B":[{"#content":"Toyota"}],"C":[{"#content":"Yamaha"}]}); + +// A64|error a64 = xmldata:parseAsType(x6); +// test:assertEquals(a64, {"B":[{"#content":"Toyota"}]}); +// } + +// xml x7 = xml `BrickWaterAir`; + +// type A71 record {record {|string...;|}[]|string[] B;}; +// type A72 record {string[]|record {|string...;|}[] B;}; +// type A73 record {record {|string \@content;|}|string[] B;}; +// type A74 record {|record {|string...;|}|string[]...;|}; +// type A75 record {|record {|string...;|}[]|string[]...;|}; +// type A76 record {|(record {|string...;|}|string)[]...;|}; +// type A77 record {|(record {|string...;|}|string)[] B;|}; +// type A78 record {|(string|record {|string...;|})[]...;|}; + +// function testUnionTypes7() { +// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 +// // A71|error a71 = xmldata:parseAsType(x7); +// // test:assertEquals(a71, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); + +// A72|error a72 = xmldata:parseAsType(x7); +// test:assertEquals(a72, {"B":["Brick","Water"],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); + +// A73|error a73 = xmldata:parseAsType(x7); +// test:assertTrue(a73 is xmldata:Error); +// test:assertEquals((a73).message(), "unsupported input type"); + +// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 +// // A74|error a74 = xmldata:parseAsType(x7); +// // test:assertEquals(a74, {"B":{"#content":"Water"},"C":{"#content":"Air"}); + +// // // bug #6 +// // A75|error a75 = xmldata:parseAsType(x7); +// // test:assertEquals(a75, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); + +// // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 +// // A76|error a76 = xmldata:parseAsType(x7); +// // test:assertEquals(a76, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); + +// // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 +// // A77|error a77 = xmldata:parseAsType(x7); +// // test:assertEquals(a77, {"B":[{"#content":"Brick"},{"#content":"Water"}]}); + +// // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 +// // A78|error a78 = xmldata:parseAsType(x7); +// // test:assertEquals(a78, {"B":{"#content":"Water"},"C":{"#content":"Air"}}); +// } + +// xml x8 = xml ` +// +// First +// +// +// Second +// Third +// +// +// Fourth +// Fifth +// +// `; + +// type A81P2 record{string \#content;}[]; +// type A81P1 record{string \#content;}; +// type A81 record {record{|(A81P1|A81P2)[] C?;|}[] B;}; +// type A81Part2 record {record{(A81P1|A81P2)[] C?;}[] B;}; +// type A82P2 record{string \#content;}[][]; +// type A82P1 record{string \#content;}[]; +// type A82 record {record{|A82P1|A82P2 C?;|}[] B;}; +// type A82Part2 record {record{A82P1|A82P2 C?;}[] B;}; +// type A83P2 record{string \#content;}[]; +// type A83P1 record{string \#content;}; +// type A83 record {|record{|(A83P1|A83P2)[] C?;|}...;|}; +// type A84P2 record{string \#content;}[]; +// type A84P1 record{string \#content;}; +// type A84 record {|record{|(A84P1|A84P2)[] C?;|}[]...;|}; +// type A85 record{|record{}...;|}|record{|record{}[]...;|}; +// type A86 record{|record{}[]...;|}|record{|record{}...;|}; + +// function testUnionTypes8() { +// A81|error a81 = xmldata:parseAsType(x8); +// test:assertEquals(a81, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + +// A81Part2|error a81p2 = xmldata:parseAsType(x8); +// test:assertEquals(a81p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, +// {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); + +// A82|error a82 = xmldata:parseAsType(x8); +// test:assertEquals(a82, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + +// A82Part2|error a82p2 = xmldata:parseAsType(x8); +// test:assertEquals(a82p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, +// {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); + +// A83|error a83 = xmldata:parseAsType(x8); +// test:assertEquals(a83, {B: {}}); + +// A84|error a84 = xmldata:parseAsType(x8); +// test:assertEquals(a84, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + +// A85|error a85 = xmldata:parseAsType(x8); +// test:assertEquals(a85, {"B":{"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}}); + +// A86|error a86 = xmldata:parseAsType(x8); +// test:assertEquals(a86, {"B":[{"C":{"c1":"inner1","c2":"value","#content":"First"}},{"C":[{"c1":"inner2","c2":"value","#content":"Second"}, +// {"c1":"inner3","c2":"value","#content":"Third"}]},{"D":{"d1":"inner4","d2":"value","#content":"Fourth"}, +// "E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); +// } -xml x9 = xml ` - - 100 - 200 - 300 - - - 400 - 500 - 600 - - `; - -type A91P1 record{string[]|record{string \#content;}[] C;}; -type A91 record {A91P1[] B;}; -type A92P1 record{(string|record{string \#content;})[] C;}; -type A92 record {A92P1[] B;}; -type A93P1 record{record{string \#content;}[]|string[] C;}; -type A93 record {A93P1[] B;}; -type A94P1 record{|(record{string \#content;}|string)[]...;|}; -type A94 record {A94P1[] B;}; - -function testUnionTypes9() { - A91|error a91 = xmldata:parseAsType(x9); - test:assertEquals(a91, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); - - A92|error a92 = xmldata:parseAsType(x9); - test:assertEquals(a92, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); - - A93|error a93 = xmldata:parseAsType(x9); - test:assertEquals(a93, {"B":[{"C":[{"#content":"100"}, - {"#content":"200"},{"#content":"300"}]}, - {"C":[{"#content":"400"},{"#content":"500"}, - {"#content":"600"}]}]}); - - A94|error a94 = xmldata:parseAsType(x9); - test:assertEquals(a94, {"B":[{"C":[{"#content":"100"}, - {"#content":"200"},{"#content":"300"}]}, - {"C":[{"#content":"400"},{"#content":"500"}, - {"#content":"600"}]}]}); -} - -xml x10 = xml ` - - Deep Value1 - Deep Value2 - - - Deep Value3 - Deep Value4 - - `; - -type A101P1 record{string[]|record{string \#content;}[] C;}; -type A101 record {A101P1[] B;}; -type A102P1 record{(string|record{string \#content;})[] C;}; -type A102 record {A102P1[] B;}; -type A103P1 record{record{string \#content;}[]|string[] C;}; -type A103 record {A103P1[] B;}; -type A104P1 record{(record{string \#content;}|string)[] C;}; -type A104 record {A104P1[] B;}; - -function testUnionTypes10() { - A101|error a101 = xmldata:parseAsType(x10); - test:assertEquals(a101, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); - - A102|error a102 = xmldata:parseAsType(x10); - test:assertEquals(a102, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); - - A103|error a103 = xmldata:parseAsType(x10); - test:assertEquals(a103, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, - {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); - - A104|error a104 = xmldata:parseAsType(x10); - test:assertEquals(a104, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, - {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); -} - -public function main() { - testUnionTypes1(); - testUnionTypes2(); - testUnionTypes3(); - testUnionTypes4(); - testUnionTypes5(); - testUnionTypes6(); - testUnionTypes7(); - testUnionTypes8(); - testUnionTypes9(); - testUnionTypes10(); -} - -xml x11 = xml ` - - Deep Value1 - Deep Value2 - - - Deep Value1 - Deep Value2 - - `; - -xml x12 = xml ` - - Deep Value1 - Deep Value2 - - - Deep Value3 - Deep Value4 - - `; - -xml x13 = xml ` - - Deep Value1 - Deep Value2 - - - Deep Value1 - Deep Value2 - - - Deep Value1 - Deep Value2 - - `; - -xml x14 = xml ` - - Deep Value1 - Deep Value2 - - - Deep Value1 - Deep Value2 - - `; +// xml x9 = xml ` +// +// 100 +// 200 +// 300 +// +// +// 400 +// 500 +// 600 +// +// `; + +// type A91P1 record{string[]|record{string \#content;}[] C;}; +// type A91 record {A91P1[] B;}; +// type A92P1 record{(string|record{string \#content;})[] C;}; +// type A92 record {A92P1[] B;}; +// type A93P1 record{record{string \#content;}[]|string[] C;}; +// type A93 record {A93P1[] B;}; +// type A94P1 record{|(record{string \#content;}|string)[]...;|}; +// type A94 record {A94P1[] B;}; + +// function testUnionTypes9() { +// A91|error a91 = xmldata:parseAsType(x9); +// test:assertEquals(a91, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); + +// A92|error a92 = xmldata:parseAsType(x9); +// test:assertEquals(a92, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); + +// A93|error a93 = xmldata:parseAsType(x9); +// test:assertEquals(a93, {"B":[{"C":[{"#content":"100"}, +// {"#content":"200"},{"#content":"300"}]}, +// {"C":[{"#content":"400"},{"#content":"500"}, +// {"#content":"600"}]}]}); + +// A94|error a94 = xmldata:parseAsType(x9); +// test:assertEquals(a94, {"B":[{"C":[{"#content":"100"}, +// {"#content":"200"},{"#content":"300"}]}, +// {"C":[{"#content":"400"},{"#content":"500"}, +// {"#content":"600"}]}]}); +// } + +// xml x10 = xml ` +// +// Deep Value1 +// Deep Value2 +// +// +// Deep Value3 +// Deep Value4 +// +// `; + +// type A101P1 record{string[]|record{string \#content;}[] C;}; +// type A101 record {A101P1[] B;}; +// type A102P1 record{(string|record{string \#content;})[] C;}; +// type A102 record {A102P1[] B;}; +// type A103P1 record{record{string \#content;}[]|string[] C;}; +// type A103 record {A103P1[] B;}; +// type A104P1 record{(record{string \#content;}|string)[] C;}; +// type A104 record {A104P1[] B;}; + +// function testUnionTypes10() { +// A101|error a101 = xmldata:parseAsType(x10); +// test:assertEquals(a101, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); + +// A102|error a102 = xmldata:parseAsType(x10); +// test:assertEquals(a102, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); + +// A103|error a103 = xmldata:parseAsType(x10); +// test:assertEquals(a103, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, +// {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); + +// A104|error a104 = xmldata:parseAsType(x10); +// test:assertEquals(a104, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, +// {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); +// } + +// xml x11 = xml ` +// +// Deep Value1 +// Deep Value2 +// +// +// Deep Value3 +// Deep Value2 +// +// `; + +// @xmldata:Namespace { +// prefix: "ns1", +// uri: "http://example.com/ns1" +// } +// type A111 record { +// string a1; +// (B111|B112)[] B; +// }; + +// @xmldata:Namespace { +// prefix: "ns1", +// uri: "http://example.com/ns1" +// } +// type A112 record {| +// string a1; +// (B111|B112)[]...; +// |}; + +// @xmldata:Namespace { +// prefix: "ns1", +// uri: "http://example.com/ns1" +// } +// type B111 record { +// @xmldata:Namespace { +// prefix: "ns1", +// uri: "http://example.com/ns1" +// } +// string b1; +// (C111|C112)[] C; +// }; + +// @xmldata:Namespace { +// prefix: "ns2", +// uri: "http://example.com/ns2" +// } +// type B112 record { +// @xmldata:Namespace { +// prefix: "ns1", +// uri: "http://example.com/ns1" +// } +// string b1; +// (C111|C112)[] C; +// }; + +// @xmldata:Namespace { +// prefix: "ns1", +// uri: "http://example.com/ns1" +// } +// type C111 record { +// @xmldata:Namespace { +// prefix: "ns1", +// uri: "http://example.com/ns1" +// } +// string c1; +// string \#content; +// }; + +// @xmldata:Namespace { +// prefix: "ns1", +// uri: "http://example.com/ns1" +// } +// type C112 record { +// @xmldata:Namespace { +// prefix: "ns1", +// uri: "http://example.com/ns1" +// } +// string c1; +// string \#content; +// }; + +// function testUnionTypes11() { +// A111|error a111 = xmldata:parseAsType(x11); +// test:assertEquals(a111, {"a1":"outer","B":[{"b1":"middle","C":[{"c1":"inner","#content":"Deep Value1"}, +// {"c1":"inner","#content":"Deep Value2"}]}, +// {"b1":"middle","C":[{"c1":"inner","#content":"Deep Value3"}, +// {"c1":"inner","#content":"Deep Value2"}]}]}); + +// A112|error a112 = xmldata:parseAsType(x11); +// test:assertEquals(a112, {"a1":"outer","B":[{"b1":"middle","C":[{"c1":"inner","#content":"Deep Value1"}, +// {"c1":"inner","#content":"Deep Value2"}]}, +// {"b1":"middle","C":[{"c1":"inner","#content":"Deep Value3"}, +// {"c1":"inner","#content":"Deep Value2"}]}]}); +// } + +// xml x12 = xml ` +// +// Deep Value1 +// Deep Value2 +// +// +// Deep Value3 +// Deep Value4 +// +// `; + +// @xmldata:Namespace { +// prefix: "ns1", +// uri: "http://example.com/ns1" +// } +// type A121 record { +// string a1; +// (B121|B122)[] B; +// }; + +// type A122 record {| +// string a1; +// (B121|B122)[]...; +// |}; + +// @xmldata:Namespace { +// prefix: "ns2", +// uri: "http://example.com/ns2" +// } +// type B121 record { +// string b1; +// C121[] C; +// }; + +// @xmldata:Namespace { +// prefix: "ns2", +// uri: "http://example.com/ns2" +// } +// type B122 record { +// string b1; +// C121[] C; +// }; + +// @xmldata:Namespace { +// prefix: "ns3", +// uri: "http://example.com/ns3" +// } +// type C121 record { +// string c1; +// string \#content; +// }; + +// function testUnionTypes12() { +// A121|error a121 = xmldata:parseAsType(x12); +// test:assertEquals(a121, {"a1":"outer","B":[{"b1":"middle", "C":[{"c1":"inner","#content":"Deep Value1"}, +// {"c1":"inner","#content":"Deep Value2"}]},{"b1":"middle", +// "C":[{"c1":"inner","#content":"Deep Value3"},{"c1":"inner","#content":"Deep Value4"}]}]}); +// A122|error a122 = xmldata:parseAsType(x12); +// test:assertEquals(a122, {"a1":"outer","B":[{"b1":"middle", "C":[{"c1":"inner","#content":"Deep Value1"}, +// {"c1":"inner","#content":"Deep Value2"}]},{"b1":"middle", +// "C":[{"c1":"inner","#content":"Deep Value3"},{"c1":"inner","#content":"Deep Value4"}]}]}); +// } + +// public function main() { +// testUnionTypes1(); +// testUnionTypes2(); +// testUnionTypes3(); +// testUnionTypes4(); +// testUnionTypes5(); +// testUnionTypes6(); +// testUnionTypes7(); +// testUnionTypes8(); +// testUnionTypes9(); +// testUnionTypes10(); +// testUnionTypes11(); +// testUnionTypes12(); +// } diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java index 3940150..d3f4f7d 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java @@ -45,6 +45,8 @@ import io.ballerina.runtime.api.values.BTypedesc; import io.ballerina.stdlib.constraint.Constraints; +import java.io.IOException; +import java.io.Reader; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; @@ -262,16 +264,33 @@ private static Object convertStringToUnionExpType(BString value, Type expType) { throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, expType); } - public static void validateRequiredFields(XmlAnalyzerData analyzerData) { - for (Field field : analyzerData.fieldHierarchy.peek().getMembers().values()) { + public static void validateRequiredFields(XmlAnalyzerData analyzerData, BMap currentMapValue) { + Map fields = analyzerData.fieldHierarchy.peek().getMembers(); + for (QualifiedName key : fields.keySet()) { + // Validate required array size + Field field = fields.get(key); + String fieldName = field.getFieldName(); + Type fieldType = TypeUtils.getReferredType(field.getFieldType()); + if (fieldType.getTag() == TypeTags.ARRAY_TAG) { + ArrayType arrayType = (ArrayType) fieldType; + if (arrayType.getSize() != -1 + && arrayType.getSize() != ((BArray) currentMapValue.get( + StringUtils.fromString(fieldName))).getLength()) { + throw DiagnosticLog.error(DiagnosticErrorCode.ARRAY_SIZE_MISMATCH); + } + continue; + } + if (SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.REQUIRED)) { - throw DiagnosticLog.error(DiagnosticErrorCode.REQUIRED_FIELD_NOT_PRESENT, field.getFieldName()); + throw DiagnosticLog.error(DiagnosticErrorCode.REQUIRED_FIELD_NOT_PRESENT, fieldName); } } - for (Field attribute : analyzerData.attributeHierarchy.peek().getMembers().values()) { - if (!SymbolFlags.isFlagOn(attribute.getFlags(), SymbolFlags.OPTIONAL)) { - throw DiagnosticLog.error(DiagnosticErrorCode.REQUIRED_ATTRIBUTE_NOT_PRESENT, attribute.getFieldName()); + Map attributes = analyzerData.attributeHierarchy.peek().getMembers(); + for (QualifiedName key : attributes.keySet()) { + Field field = attributes.get(key); + if (!SymbolFlags.isFlagOn(field.getFlags(), SymbolFlags.OPTIONAL)) { + throw DiagnosticLog.error(DiagnosticErrorCode.REQUIRED_ATTRIBUTE_NOT_PRESENT, field.getFieldName()); } } } @@ -959,6 +978,16 @@ public static boolean isSimpleType(Type type) { }; } + public static String generateStringFromXmlReader(Reader reader) throws IOException { + StringBuilder builder = new StringBuilder(); + char[] buffer = new char[1024]; + int numCharsRead; + while ((numCharsRead = reader.read(buffer)) != -1) { + builder.append(buffer, 0, numCharsRead); + } + return builder.toString(); + } + /** * Holds data required for the traversing. * diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/QualifiedNameMap.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/QualifiedNameMap.java index f32cc75..8aa0f64 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/QualifiedNameMap.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/QualifiedNameMap.java @@ -17,10 +17,19 @@ public QualifiedNameMap(Map fields) { this.stringToQNameMap = getStringToQNamesMap(fields.keySet()); } + public QualifiedNameMap(Map fields, Map> stringToQNameMap) { + this.members = fields; + this.stringToQNameMap = stringToQNameMap; + } + public Map getMembers() { return members; } + public Map> getStringToQnamesMap() { + return stringToQNameMap; + } + public V remove(QualifiedName qName) { V field = members.remove(qName); if (field == null) { diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java index 1226db7..a09b9cb 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java @@ -33,14 +33,18 @@ import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.RecordType; import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.UnionType; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; +import io.ballerina.runtime.api.utils.XmlUtils; import io.ballerina.runtime.api.values.BArray; import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.api.values.BTypedesc; +import io.ballerina.runtime.api.values.BXml; +import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.HashMap; @@ -87,9 +91,10 @@ public class XmlParser { public static final String PARSE_ERROR = "failed to parse xml"; public static final String PARSE_ERROR_PREFIX = PARSE_ERROR + ": "; - public XmlParser(Reader stringReader) { + public XmlParser(Reader stringReader, Type type) { try { - xmlStreamReader = xmlInputFactory.createXMLStreamReader(stringReader); + xmlStreamReader = type.getTag() != TypeTags.UNION_TAG ? + xmlInputFactory.createXMLStreamReader(stringReader) : null; } catch (XMLStreamException e) { handleXMLStreamException(e); } @@ -106,10 +111,11 @@ public static Object parse(Reader reader, BMap options, BTypede public static Object parse(Reader reader, BMap options, Type type) { try { + type = TypeUtils.getReferredType(type); XmlParserData xmlParserData = new XmlParserData(); updateOptions(options, xmlParserData); - XmlParser xmlParser = new XmlParser(reader); - return xmlParser.parse(type, xmlParserData); + XmlParser xmlParser = new XmlParser(reader, type); + return xmlParser.parse(reader, type, xmlParserData, options); } catch (BError e) { return e; } catch (Throwable e) { @@ -132,7 +138,28 @@ private void handleXMLStreamException(Exception e) { throw DiagnosticLog.createXmlError(PARSE_ERROR_PREFIX + reason); } - public Object parse(Type type, XmlParserData xmlParserData) { + public Object parse(Reader reader, Type type, XmlParserData xmlParserData, BMap options) + throws IOException { + Type referredType = TypeUtils.getReferredType(type); + if (referredType.getTag() == TypeTags.UNION_TAG) { + String xmlStr = DataUtils.generateStringFromXmlReader(reader); + BXml xmlValue = XmlUtils.parse(xmlStr); + XmlParserData clonedAnalyzerData = XmlParserData.copy(xmlParserData); + for (Type memberType: ((UnionType) referredType).getMemberTypes()) { + memberType = TypeUtils.getReferredType(memberType); + if (memberType.getTag() == TypeTags.ERROR_TAG) { + continue; + } + try { + return XmlTraversal.traverse(xmlValue, options, referredType); + } catch (Exception ex) { + xmlParserData.resetFrom(clonedAnalyzerData); + int a = 1; + // ignore + } + throw DiagnosticLog.error(DiagnosticErrorCode.CANNOT_CONVERT_SOURCE_INTO_EXP_TYPE, type); + } + } if (type.getTag() != TypeTags.RECORD_TYPE_TAG) { throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, Constants.RECORD, type.getName()); } @@ -300,7 +327,31 @@ private void readText(XMLStreamReader xmlStreamReader, throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, fieldType, PredefinedTypes.TYPE_STRING); } + Object value = xmlParserData.currentNode.get(bFieldName); Object temp = xmlParserData.currentNode.get(bFieldName); + if (fieldType.getTag() == TypeTags.UNION_TAG) { + XmlParserData clonedAnalyzerData = XmlParserData.copy(xmlParserData); + for (Type memberType: ((UnionType) fieldType).getMemberTypes()) { + try { + if (!(value instanceof BArray) && memberType.getTag() == TypeTags.ARRAY_TAG) { + continue; + } + convertTextToExpType(memberType, textFieldName, fieldName, bText, xmlParserData, bFieldName, temp); + return; + } catch (Exception ex) { + int a = 1; + xmlParserData.resetFrom(clonedAnalyzerData); + // ignore + } + } + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldType); + } else { + convertTextToExpType(fieldType, textFieldName, fieldName, bText, xmlParserData, bFieldName, temp); + } + } + + private void convertTextToExpType(Type fieldType, String textFieldName, String fieldName, + BString bText, XmlParserData xmlParserData, BString bFieldName, Object temp) { if (temp instanceof BArray && !DataUtils.isAnydataOrJson(fieldType.getTag())) { if (fieldName.equals(textFieldName)) { xmlParserData.currentNode.put(bFieldName, convertStringToRestExpType(bText, fieldType)); @@ -315,20 +366,24 @@ private void readText(XMLStreamReader xmlStreamReader, return; } - ((BArray) xmlParserData.currentNode.get(bFieldName)).add(currentIndex, - convertStringToRestExpType(bText, fieldType)); + ((BArray) xmlParserData.currentNode.get(bFieldName)) + .add(currentIndex, convertStringToRestExpType(bText, fieldType)); return; } switch (fieldType.getTag()) { case TypeTags.RECORD_TYPE_TAG -> handleContentFieldInRecordType((RecordType) fieldType, bText, xmlParserData); - case TypeTags.ARRAY_TAG -> - addTextToCurrentNodeIfExpTypeIsArray((ArrayType) fieldType, bFieldName, bText, xmlParserData); + case TypeTags.ARRAY_TAG -> { + ArrayType arrayType = (ArrayType) fieldType; + addTextToCurrentNodeIfExpTypeIsArray( + TypeUtils.getReferredType((arrayType.getElementType())), + arrayType, bFieldName, bText, xmlParserData); + } case TypeTags.ANYDATA_TAG, TypeTags.JSON_TAG -> - convertTextAndUpdateCurrentNode(xmlParserData.currentNode, - (BMap) xmlParserData.nodesStack.pop(), - bFieldName, bText, fieldType, xmlParserData); + convertTextAndUpdateCurrentNode(xmlParserData.currentNode, + (BMap) xmlParserData.nodesStack.pop(), + bFieldName, bText, fieldType, xmlParserData); default -> xmlParserData.currentNode.put(bFieldName, convertStringToRestExpType(bText, fieldType)); } } @@ -355,9 +410,8 @@ private void convertTextAndUpdateCurrentNode(BMap currentNode, } @SuppressWarnings("unchecked") - private void addTextToCurrentNodeIfExpTypeIsArray(ArrayType fieldType, BString bFieldName, BString bText, - XmlParserData xmlParserData) { - Type referredType = TypeUtils.getReferredType(fieldType.getElementType()); + private void addTextToCurrentNodeIfExpTypeIsArray(Type referredType, ArrayType arrayType, BString bFieldName, + BString bText, XmlParserData xmlParserData) { int elementTypeTag = referredType.getTag(); switch (elementTypeTag) { case TypeTags.RECORD_TYPE_TAG -> handleContentFieldInRecordType((RecordType) referredType, @@ -367,11 +421,25 @@ private void addTextToCurrentNodeIfExpTypeIsArray(ArrayType fieldType, BString b HashMap indexes = xmlParserData.arrayIndexes.get(xmlParserData.arrayIndexes.size() - 2); int currentIndex = indexes.get(bFieldName.getValue()); - if (fieldType.getState() == ArrayType.ArrayState.CLOSED && currentIndex >= fieldType.getSize()) { + if (arrayType.getState() == ArrayType.ArrayState.CLOSED && currentIndex >= arrayType.getSize()) { DataUtils.logArrayMismatchErrorIfProjectionNotAllowed(xmlParserData.allowDataProjection); return; } - tempArr.add(currentIndex, convertStringToRestExpType(bText, fieldType)); + tempArr.add(currentIndex, convertStringToRestExpType(bText, referredType)); + } + case TypeTags.UNION_TAG -> { + XmlParserData clonedAnalyzerData = XmlParserData.copy(xmlParserData); + for (Type memberType: ((UnionType) referredType).getMemberTypes()) { + try { + memberType = TypeUtils.getReferredType(memberType); + addTextToCurrentNodeIfExpTypeIsArray(memberType, arrayType, bFieldName, bText, xmlParserData); + return; + } catch (Exception ex) { + xmlParserData.resetFrom(clonedAnalyzerData); + int a = 1; + // ignore + } + } } } } @@ -416,6 +484,17 @@ private Object convertStringToExpType(BString value, Type expType) { if (expType.getTag() == TypeTags.ARRAY_TAG) { expType = ((ArrayType) expType).getElementType(); } + if (expType.getTag() == TypeTags.UNION_TAG) { + for (Type memberType: ((UnionType) expType).getMemberTypes()) { + memberType = TypeUtils.getReferredType(memberType); + try { + return convertStringToExpType(value, memberType); + } catch (Exception ex) { + int a = 1; + // ignore + } + } + } Object result = FromString.fromStringWithType(value, expType); if (result instanceof BError) { throw (BError) result; @@ -559,6 +638,21 @@ private void initializeNextValueBasedOnExpectedType(String fieldName, Type field case TypeTags.TYPE_REFERENCED_TYPE_TAG -> initializeNextValueBasedOnExpectedType(fieldName, TypeUtils.getReferredType(fieldType), temp, currentNode, xmlParserData); + case TypeTags.UNION_TAG -> { + XmlParserData clonedAnalyzerData = XmlParserData.copy(xmlParserData); + for (Type memberType: ((UnionType) fieldType).getMemberTypes()) { + memberType = TypeUtils.getReferredType(memberType); + try { + initializeNextValueBasedOnExpectedType(fieldName, memberType, temp, currentNode, xmlParserData); + return; + } catch (Exception ex) { + xmlParserData.resetFrom(clonedAnalyzerData); + currentNode.put(StringUtils.fromString(fieldName), null); + int a = 1; + // ignore + } + } + } } } @@ -1143,23 +1237,70 @@ static class TextValue { * @since 0.1.0 */ public static class XmlParserData { - private final Stack nodesStack = new Stack<>(); - private final Stack> fieldHierarchy = new Stack<>(); + private Stack nodesStack = new Stack<>(); + private Stack> fieldHierarchy = new Stack<>(); Stack> visitedFieldHierarchy = new Stack<>(); - private final Stack> attributeHierarchy = new Stack<>(); - private final Stack restTypes = new Stack<>(); - private final Stack restFieldsPoints = new Stack<>(); - private final Stack recordTypeStack = new Stack<>(); + private Stack> attributeHierarchy = new Stack<>(); + private Stack restTypes = new Stack<>(); + private Stack restFieldsPoints = new Stack<>(); + private Stack recordTypeStack = new Stack<>(); Stack> arrayIndexes = new Stack<>(); private RecordType rootRecord; private Field currentField; private QualifiedName rootElement; - private final Stack> parents = new Stack<>(); + private Stack> parents = new Stack<>(); private QualifiedNameMap siblings = new QualifiedNameMap<>(new LinkedHashMap<>()); private BMap currentNode; private String attributePrefix; private String textFieldName; private boolean allowDataProjection; private boolean useSemanticEquality; + + @SuppressWarnings("unchecked") + public static XmlParserData copy(XmlParserData analyzerData) { + XmlParserData data = new XmlParserData(); + data.nodesStack = (Stack) analyzerData.nodesStack.clone(); + data.fieldHierarchy = (Stack>) analyzerData.fieldHierarchy.clone(); + data.visitedFieldHierarchy = (Stack>) analyzerData.visitedFieldHierarchy.clone(); + data.attributeHierarchy = (Stack>) analyzerData.attributeHierarchy.clone(); + data.restTypes = (Stack) analyzerData.restTypes.clone(); + data.restFieldsPoints = (Stack) analyzerData.restFieldsPoints.clone(); + data.recordTypeStack = (Stack) analyzerData.recordTypeStack.clone(); + data.arrayIndexes = (Stack>) analyzerData.arrayIndexes.clone(); + data.rootRecord = analyzerData.rootRecord; + data.currentField = analyzerData.currentField; + data.rootElement = analyzerData.rootElement; + data.parents = (Stack>) analyzerData.parents.clone(); + data.siblings = new QualifiedNameMap<>(Map.copyOf(analyzerData.siblings.getMembers()), + Map.copyOf(analyzerData.siblings.getStringToQnamesMap())); + data.currentNode = analyzerData.currentNode; + data.attributePrefix = analyzerData.attributePrefix; + data.textFieldName = analyzerData.textFieldName; + data.allowDataProjection = analyzerData.allowDataProjection; + data.useSemanticEquality = analyzerData.useSemanticEquality; + + return data; + } + + public void resetFrom(XmlParserData analyzerData) { + this.nodesStack = analyzerData.nodesStack; + this.fieldHierarchy = analyzerData.fieldHierarchy; + this.visitedFieldHierarchy = analyzerData.visitedFieldHierarchy; + this.attributeHierarchy = analyzerData.attributeHierarchy; + this.restTypes = analyzerData.restTypes; + this.restFieldsPoints = analyzerData.restFieldsPoints; + this.recordTypeStack = analyzerData.recordTypeStack; + this.arrayIndexes = analyzerData.arrayIndexes; + this.rootRecord = analyzerData.rootRecord; + this.currentField = analyzerData.currentField; + this.rootElement = analyzerData.rootElement; + this.parents = analyzerData.parents; + this.siblings = analyzerData.siblings; + this.currentNode = analyzerData.currentNode; + this.attributePrefix = analyzerData.attributePrefix; + this.textFieldName = analyzerData.textFieldName; + this.allowDataProjection = analyzerData.allowDataProjection; + this.useSemanticEquality = analyzerData.useSemanticEquality; + } } } diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java index ed06087..30b7b88 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java @@ -111,7 +111,7 @@ private Object traverseXmlWithRecordAsExpectedType(BXml xml, currentNode = ValueCreator.createRecordValue(recordType.getPackage(), recordType.getName()); BXml nextXml = validateRootElement(xml, recordType, analyzerData); Object resultRecordValue = traverseXml(nextXml, recordType, analyzerData); - DataUtils.validateRequiredFields(analyzerData); + DataUtils.validateRequiredFields(analyzerData, (BMap) currentNode); return resultRecordValue; } @@ -241,7 +241,11 @@ private void convertElement(BXmlItem xmlItem, XmlAnalyzerData analyzerData) { currentField.getFieldName()); } } else { - currentField = fieldsMap.remove(elementQName); + currentField = fieldsMap.get(elementQName); + if (currentField != null + && TypeUtils.getReferredType(currentField.getFieldType()).getTag() != TypeTags.ARRAY_TAG) { + fieldsMap.remove(elementQName); + } } analyzerData.currentField = currentField; @@ -392,7 +396,7 @@ private void convertToRecordType(BXmlItem xmlItem, Type currentFieldType, String RecordType prevRecord = analyzerData.rootRecord; analyzerData.rootRecord = elementType; traverseXml(xmlItem.getChildrenSeq(), currentFieldType, analyzerData); - DataUtils.validateRequiredFields(analyzerData); + DataUtils.validateRequiredFields(analyzerData, (BMap) currentNode); DataUtils.popExpectedTypeStacks(analyzerData); analyzerData.rootRecord = prevRecord; currentNode = analyzerData.nodesStack.pop(); @@ -403,7 +407,7 @@ private void convertToMapType(BXmlItem xmlItem, Type fieldType, Type elementType updateNextMap(elementType, analyzerData); currentNode = updateNextMappingValue(elementType, fieldName, fieldType, mapValue, analyzerData); traverseXml(xmlItem.getChildrenSeq(), fieldType, analyzerData); - DataUtils.validateRequiredFields(analyzerData); + DataUtils.validateRequiredFields(analyzerData, (BMap) currentNode); DataUtils.popExpectedTypeStacks(analyzerData); currentNode = analyzerData.nodesStack.pop(); } @@ -534,7 +538,9 @@ private void checkRestTypeAndConvertForUnionTypes(BXmlItem xmlItem, String elemN return; } catch (Exception ex) { analyzerData.resetFrom(clonedAnalyzerData); - mapValue.put(StringUtils.fromString(elemName), null); + if (restType.getTag() != TypeTags.ARRAY_TAG) { + mapValue.put(StringUtils.fromString(elemName), null); + } int a = 1; // ignore } From 1fed63637ff91e0e221db61f704de1af7854a473 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Tue, 27 Aug 2024 13:37:11 +0530 Subject: [PATCH 06/16] Add union implementation for parseString API --- .../lib/data/xmldata/utils/DataUtils.java | 89 +++++-- .../lib/data/xmldata/xml/XmlParser.java | 226 ++++-------------- 2 files changed, 114 insertions(+), 201 deletions(-) diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java index d3f4f7d..d8af0f3 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java @@ -34,6 +34,7 @@ import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.RecordType; import io.ballerina.runtime.api.types.ReferenceType; +import io.ballerina.runtime.api.types.TupleType; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.UnionType; import io.ballerina.runtime.api.utils.StringUtils; @@ -252,7 +253,7 @@ public static Object convertStringToExpType(BString value, Type expType) { } private static Object convertStringToUnionExpType(BString value, Type expType) { - for (Type memberType: ((UnionType) expType).getMemberTypes()) { + for (Type memberType : ((UnionType) expType).getMemberTypes()) { memberType = TypeUtils.getReferredType(memberType); try { return convertStringToExpType(value, memberType); @@ -298,7 +299,7 @@ public static void validateRequiredFields(XmlAnalyzerData analyzerData, BMap throw new IllegalStateException("Unexpected value: " + type.getTag()); }; } + public static MapType getMapTypeFromConstraintType(Type constraintType) { return switch (constraintType.getTag()) { case TypeTags.MAP_TAG -> (MapType) constraintType; case TypeTags.INT_TAG, TypeTags.FLOAT_TAG, TypeTags.STRING_TAG, TypeTags.BOOLEAN_TAG, TypeTags.BYTE_TAG, - TypeTags.DECIMAL_TAG, TypeTags.JSON_TAG, TypeTags.RECORD_TYPE_TAG, TypeTags.OBJECT_TYPE_TAG, - TypeTags.XML_TAG, TypeTags.NULL_TAG -> TypeCreator.createMapType(constraintType); + TypeTags.DECIMAL_TAG, TypeTags.JSON_TAG, TypeTags.RECORD_TYPE_TAG, TypeTags.OBJECT_TYPE_TAG, + TypeTags.XML_TAG, TypeTags.NULL_TAG -> TypeCreator.createMapType(constraintType); case TypeTags.ARRAY_TAG -> TypeCreator.createMapType(((ArrayType) constraintType).getElementType()); case TypeTags.TYPE_REFERENCED_TYPE_TAG -> getMapTypeFromConstraintType(TypeUtils.getReferredType(constraintType)); @@ -361,8 +363,8 @@ public static boolean isAnydataOrJson(int typeTag) { public static boolean isSupportedType(Type type) { switch (type.getTag()) { case TypeTags.NULL_TAG, TypeTags.INT_TAG, TypeTags.BYTE_TAG, TypeTags.FLOAT_TAG, TypeTags.DECIMAL_TAG, - TypeTags.BOOLEAN_TAG, TypeTags.STRING_TAG, TypeTags.RECORD_TYPE_TAG, TypeTags.MAP_TAG, - TypeTags.JSON_TAG, TypeTags.ANYDATA_TAG -> { + TypeTags.BOOLEAN_TAG, TypeTags.STRING_TAG, TypeTags.RECORD_TYPE_TAG, TypeTags.MAP_TAG, + TypeTags.JSON_TAG, TypeTags.ANYDATA_TAG -> { return true; } case TypeTags.ARRAY_TAG -> { @@ -442,7 +444,7 @@ public static Object getModifiedRecord(BMap input, BString text if (describingType.getTag() == TypeTags.RECORD_TYPE_TAG && describingType.getFlags() != Constants.DEFAULT_TYPE_FLAG) { BArray jsonArray = ValueCreator.createArrayValue(PredefinedTypes.TYPE_JSON_ARRAY); - BMap recordField = addFields(input, type.getDescribingType()); + BMap recordField = addFields(input, type.getDescribingType()); BMap processedRecord = processParentAnnotation(type.getDescribingType(), recordField); BString rootTagName = processedRecord.getKeys()[0]; jsonArray.append(processedRecord.get(rootTagName)); @@ -497,7 +499,7 @@ private static BMap addFields(BMap input, Type BMap recordValue = ValueCreator.createMapValue(Constants.JSON_MAP_TYPE); Map fields = ((RecordType) type).getFields(); BMap annotations = ((RecordType) type).getAnnotations(); - for (Map.Entry entry: input.entrySet()) { + for (Map.Entry entry : input.entrySet()) { String key = entry.getKey().getValue(); Object value = entry.getValue(); if (fields.containsKey(key)) { @@ -527,7 +529,7 @@ private static void processRecordField(Type fieldType, BMap ann processTypeReferenceType(fieldType, annotations, recordValue, key, value); } case TypeTags.UNION_TAG -> { - for (Type memberType: ((UnionType) fieldType).getMemberTypes()) { + for (Type memberType : ((UnionType) fieldType).getMemberTypes()) { try { processRecordField(memberType, annotations, recordValue, entry, key, value); return; @@ -558,7 +560,7 @@ private static void processTypeReferenceType(Type fieldType, BMap annotationRecord = ValueCreator.createMapValue(Constants.JSON_MAP_TYPE); + BMap annotationRecord = ValueCreator.createMapValue(Constants.JSON_MAP_TYPE); Type referredType = TypeUtils.getReferredType(fieldType); if (!doesNamespaceDefinedInField) { BMap subRecordAnnotations = ((RecordType) referredType).getAnnotations(); @@ -586,7 +588,7 @@ private static void addNamespaceToSubRecord(String key, BMap na return; } - for (Map.Entry nsAnnotEntry: ((BMap) value).entrySet()) { + for (Map.Entry nsAnnotEntry : ((BMap) value).entrySet()) { subRecord.put(nsAnnotEntry.getKey(), nsAnnotEntry.getValue()); } } @@ -649,7 +651,7 @@ private static BMap getFieldNamespaceAndNameAnnotations(String @SuppressWarnings("unchecked") private static void processRecord(String key, BMap parentAnnotations, BMap record, Object value, RecordType childType) { - BMap parentRecordAnnotations = ValueCreator.createMapValue(Constants.JSON_MAP_TYPE); + BMap parentRecordAnnotations = ValueCreator.createMapValue(Constants.JSON_MAP_TYPE); BMap annotation = childType.getAnnotations(); if (parentAnnotations.size() > 0) { annotation.merge(getFieldNamespaceAndNameAnnotations(key, parentAnnotations), true); @@ -674,7 +676,7 @@ private static void addPrimitiveValue(QName qName, BMap annotat BString key = qName.getPrefix().isBlank() ? localPart : StringUtils.fromString(qName.getPrefix() + ":" + localPart); BString annotationKey = StringUtils.fromString(Constants.FIELD - + (localPart.getValue().replaceAll(Constants.RECORD_FIELD_NAME_ESCAPE_CHAR_REGEX, "\\\\$0"))); + + (localPart.getValue().replaceAll(Constants.RECORD_FIELD_NAME_ESCAPE_CHAR_REGEX, "\\\\$0"))); BMap currentValue; if (record.containsKey(key)) { currentValue = (BMap) record.get(key); @@ -694,7 +696,7 @@ private static void addPrimitiveValue(QName qName, BMap annotat @SuppressWarnings("unchecked") private static void processArray(Type elementType, BMap annotations, BMap record, Map.Entry entry) { - BMap annotationRecord = ValueCreator.createMapValue(Constants.JSON_MAP_TYPE); + BMap annotationRecord = ValueCreator.createMapValue(Constants.JSON_MAP_TYPE); String keyName = entry.getKey().getValue(); if (!annotations.isEmpty()) { keyName = getKeyNameFromAnnotation(annotations, keyName); @@ -702,7 +704,7 @@ private static void processArray(Type elementType, BMap annotat } BArray arrayValue = (BArray) entry.getValue(); if (elementType.getTag() == TypeTags.UNION_TAG) { - for (Type memberType: ((UnionType) elementType).getMemberTypes()) { + for (Type memberType : ((UnionType) elementType).getMemberTypes()) { try { processArray(memberType, annotations, record, entry); return; @@ -814,7 +816,7 @@ private static BString processAnnotation(BMap annotation, Strin return StringUtils.fromString(key); } - private static void processSubRecordAnnotation(BMap annotation, BMap subRecord) { + private static void processSubRecordAnnotation(BMap annotation, BMap subRecord) { BString[] keys = annotation.getKeys(); for (BString value : keys) { if (isNamespaceAnnotationKey(value.getValue())) { @@ -860,11 +862,11 @@ private static String processNameAnnotation(BMap annotation, St @SuppressWarnings("unchecked") private static String processNamespaceAnnotation(BMap annotation, String key, BString value, - BMap subRecord) { + BMap subRecord) { BMap namespaceAnnotation = (BMap) annotation.get(value); BString uri = (BString) namespaceAnnotation.get(Constants.URI); BString prefix = (BString) namespaceAnnotation.get(Constants.PREFIX); - if (prefix == null) { + if (prefix == null) { subRecord.put(StringUtils.fromString(ATTRIBUTE_PREFIX + "xmlns"), uri); } else { subRecord.put(StringUtils.fromString(ATTRIBUTE_PREFIX + "xmlns:" + prefix), uri); @@ -875,7 +877,7 @@ private static String processNamespaceAnnotation(BMap annotatio @SuppressWarnings("unchecked") private static QName processFieldNamespaceAnnotation(BMap annotation, String key, BString value, - BMap subRecord, boolean isAttributeField) { + BMap subRecord, boolean isAttributeField) { BMap namespaceAnnotation = (BMap) annotation.get(value); BString uri = (BString) namespaceAnnotation.get(Constants.URI); BString prefix = (BString) namespaceAnnotation.get(Constants.PREFIX); @@ -892,7 +894,7 @@ private static QName processFieldNamespaceAnnotation(BMap annot private static String addAttributeToRecord(BString prefix, BString uri, String key, BMap subRecord) { - if (prefix == null) { + if (prefix == null) { subRecord.put(StringUtils.fromString(ATTRIBUTE_PREFIX + "xmlns"), uri); return key; } @@ -971,7 +973,7 @@ public static boolean isEqualQualifiedName(QualifiedName firstQName, QualifiedNa public static boolean isSimpleType(Type type) { return switch (type.getTag()) { case TypeTags.JSON_TAG, TypeTags.ANYDATA_TAG, TypeTags.MAP_TAG, TypeTags.OBJECT_TYPE_TAG, - TypeTags.RECORD_TYPE_TAG, TypeTags.XML_TAG -> false; + TypeTags.RECORD_TYPE_TAG, TypeTags.XML_TAG -> false; case TypeTags.ARRAY_TAG -> isSimpleType(((ArrayType) type).getElementType()); case TypeTags.TYPE_REFERENCED_TYPE_TAG -> isSimpleType(((ReferenceType) type).getReferredType()); default -> true; @@ -988,6 +990,51 @@ public static String generateStringFromXmlReader(Reader reader) throws IOExcepti return builder.toString(); } + public static boolean isContainsUnionType(Type expType) { + if (expType == null) { + return false; + } + expType = TypeUtils.getReferredType(expType); + if (expType.getTag() == TypeTags.UNION_TAG) { + for (Type memberType : ((UnionType) expType).getMemberTypes()) { + if (!isSimpleType(memberType)) { + return true; + } + } + } + + if (expType.getTag() == TypeTags.ARRAY_TAG) { + Type memberType = TypeUtils.getReferredType(((ArrayType) expType).getElementType()); + return isContainsUnionType(memberType); + } + + if (expType.getTag() == TypeTags.MAP_TAG) { + Type memberType = TypeUtils.getReferredType(((MapType) expType).getConstrainedType()); + return isContainsUnionType(memberType); + } + + if (expType.getTag() == TypeTags.TUPLE_TAG) { + TupleType tupleType = (TupleType) expType; + for (Type type : tupleType.getTupleTypes()) { + if (isContainsUnionType(type)) { + return true; + } + } + return isContainsUnionType(tupleType.getRestType()); + } + + if (expType.getTag() == TypeTags.RECORD_TYPE_TAG) { + RecordType recordType = (RecordType) expType; + for (Field field : recordType.getFields().values()) { + if (isContainsUnionType(field.getFieldType())) { + return true; + } + } + return isContainsUnionType(recordType.getRestFieldType()); + } + return false; + } + /** * Holds data required for the traversing. * diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java index a09b9cb..388970e 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java @@ -33,7 +33,6 @@ import io.ballerina.runtime.api.types.MapType; import io.ballerina.runtime.api.types.RecordType; import io.ballerina.runtime.api.types.Type; -import io.ballerina.runtime.api.types.UnionType; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.utils.XmlUtils; @@ -44,7 +43,6 @@ import io.ballerina.runtime.api.values.BTypedesc; import io.ballerina.runtime.api.values.BXml; -import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.HashMap; @@ -91,10 +89,9 @@ public class XmlParser { public static final String PARSE_ERROR = "failed to parse xml"; public static final String PARSE_ERROR_PREFIX = PARSE_ERROR + ": "; - public XmlParser(Reader stringReader, Type type) { + public XmlParser(Reader stringReader) { try { - xmlStreamReader = type.getTag() != TypeTags.UNION_TAG ? - xmlInputFactory.createXMLStreamReader(stringReader) : null; + xmlStreamReader = xmlInputFactory.createXMLStreamReader(stringReader); } catch (XMLStreamException e) { handleXMLStreamException(e); } @@ -111,15 +108,20 @@ public static Object parse(Reader reader, BMap options, BTypede public static Object parse(Reader reader, BMap options, Type type) { try { - type = TypeUtils.getReferredType(type); XmlParserData xmlParserData = new XmlParserData(); + if (DataUtils.isContainsUnionType(type)) { + String xmlStr = DataUtils.generateStringFromXmlReader(reader); + BXml xmlValue = XmlUtils.parse(xmlStr); + return XmlTraversal.traverse(xmlValue, options, type); + } + updateOptions(options, xmlParserData); - XmlParser xmlParser = new XmlParser(reader, type); - return xmlParser.parse(reader, type, xmlParserData, options); + XmlParser xmlParser = new XmlParser(reader); + return xmlParser.parse(type, xmlParserData); } catch (BError e) { return e; } catch (Throwable e) { - throw DiagnosticLog.error(DiagnosticErrorCode.XML_PARSE_ERROR, e.getMessage()); + return DiagnosticLog.error(DiagnosticErrorCode.XML_PARSE_ERROR, e.getMessage()); } } @@ -138,28 +140,7 @@ private void handleXMLStreamException(Exception e) { throw DiagnosticLog.createXmlError(PARSE_ERROR_PREFIX + reason); } - public Object parse(Reader reader, Type type, XmlParserData xmlParserData, BMap options) - throws IOException { - Type referredType = TypeUtils.getReferredType(type); - if (referredType.getTag() == TypeTags.UNION_TAG) { - String xmlStr = DataUtils.generateStringFromXmlReader(reader); - BXml xmlValue = XmlUtils.parse(xmlStr); - XmlParserData clonedAnalyzerData = XmlParserData.copy(xmlParserData); - for (Type memberType: ((UnionType) referredType).getMemberTypes()) { - memberType = TypeUtils.getReferredType(memberType); - if (memberType.getTag() == TypeTags.ERROR_TAG) { - continue; - } - try { - return XmlTraversal.traverse(xmlValue, options, referredType); - } catch (Exception ex) { - xmlParserData.resetFrom(clonedAnalyzerData); - int a = 1; - // ignore - } - throw DiagnosticLog.error(DiagnosticErrorCode.CANNOT_CONVERT_SOURCE_INTO_EXP_TYPE, type); - } - } + public Object parse(Type type, XmlParserData xmlParserData) { if (type.getTag() != TypeTags.RECORD_TYPE_TAG) { throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, Constants.RECORD, type.getName()); } @@ -217,7 +198,8 @@ private boolean parseXmlElements(int next, XmlParserData xmlParserData) throws X return true; } case END_DOCUMENT -> buildDocument(xmlParserData); - case PROCESSING_INSTRUCTION, COMMENT, DTD -> { } // Ignore + case PROCESSING_INSTRUCTION, COMMENT, DTD -> { + } // Ignore default -> { assert false; } @@ -327,31 +309,7 @@ private void readText(XMLStreamReader xmlStreamReader, throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, fieldType, PredefinedTypes.TYPE_STRING); } - Object value = xmlParserData.currentNode.get(bFieldName); Object temp = xmlParserData.currentNode.get(bFieldName); - if (fieldType.getTag() == TypeTags.UNION_TAG) { - XmlParserData clonedAnalyzerData = XmlParserData.copy(xmlParserData); - for (Type memberType: ((UnionType) fieldType).getMemberTypes()) { - try { - if (!(value instanceof BArray) && memberType.getTag() == TypeTags.ARRAY_TAG) { - continue; - } - convertTextToExpType(memberType, textFieldName, fieldName, bText, xmlParserData, bFieldName, temp); - return; - } catch (Exception ex) { - int a = 1; - xmlParserData.resetFrom(clonedAnalyzerData); - // ignore - } - } - throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldType); - } else { - convertTextToExpType(fieldType, textFieldName, fieldName, bText, xmlParserData, bFieldName, temp); - } - } - - private void convertTextToExpType(Type fieldType, String textFieldName, String fieldName, - BString bText, XmlParserData xmlParserData, BString bFieldName, Object temp) { if (temp instanceof BArray && !DataUtils.isAnydataOrJson(fieldType.getTag())) { if (fieldName.equals(textFieldName)) { xmlParserData.currentNode.put(bFieldName, convertStringToRestExpType(bText, fieldType)); @@ -366,24 +324,19 @@ private void convertTextToExpType(Type fieldType, String textFieldName, String f return; } - ((BArray) xmlParserData.currentNode.get(bFieldName)) - .add(currentIndex, convertStringToRestExpType(bText, fieldType)); + ((BArray) xmlParserData.currentNode.get(bFieldName)).add(currentIndex, + convertStringToRestExpType(bText, fieldType)); return; } switch (fieldType.getTag()) { case TypeTags.RECORD_TYPE_TAG -> handleContentFieldInRecordType((RecordType) fieldType, bText, xmlParserData); - case TypeTags.ARRAY_TAG -> { - ArrayType arrayType = (ArrayType) fieldType; - addTextToCurrentNodeIfExpTypeIsArray( - TypeUtils.getReferredType((arrayType.getElementType())), - arrayType, bFieldName, bText, xmlParserData); - } - case TypeTags.ANYDATA_TAG, TypeTags.JSON_TAG -> - convertTextAndUpdateCurrentNode(xmlParserData.currentNode, - (BMap) xmlParserData.nodesStack.pop(), - bFieldName, bText, fieldType, xmlParserData); + case TypeTags.ARRAY_TAG -> + addTextToCurrentNodeIfExpTypeIsArray((ArrayType) fieldType, bFieldName, bText, xmlParserData); + case TypeTags.ANYDATA_TAG, TypeTags.JSON_TAG -> convertTextAndUpdateCurrentNode(xmlParserData.currentNode, + (BMap) xmlParserData.nodesStack.pop(), + bFieldName, bText, fieldType, xmlParserData); default -> xmlParserData.currentNode.put(bFieldName, convertStringToRestExpType(bText, fieldType)); } } @@ -399,7 +352,7 @@ private void convertTextAndUpdateCurrentNode(BMap currentNode, if (currentElement == null && !currentNode.isEmpty()) { // Add text to the #content field currentNode.put(StringUtils.fromString(Constants.CONTENT), result); } else if (parent.get(currentFieldName) instanceof BArray bArray) { - bArray.add(bArray.getLength() - 1, result); + bArray.add(bArray.getLength() - 1, result); } else { parent.put(currentFieldName, result); } @@ -410,36 +363,22 @@ private void convertTextAndUpdateCurrentNode(BMap currentNode, } @SuppressWarnings("unchecked") - private void addTextToCurrentNodeIfExpTypeIsArray(Type referredType, ArrayType arrayType, BString bFieldName, - BString bText, XmlParserData xmlParserData) { - int elementTypeTag = referredType.getTag(); - switch (elementTypeTag) { - case TypeTags.RECORD_TYPE_TAG -> handleContentFieldInRecordType((RecordType) referredType, + private void addTextToCurrentNodeIfExpTypeIsArray(ArrayType fieldType, BString bFieldName, BString bText, + XmlParserData xmlParserData) { + Type elementType = TypeUtils.getReferredType(fieldType.getElementType()); + switch (elementType.getTag()) { + case TypeTags.RECORD_TYPE_TAG -> handleContentFieldInRecordType((RecordType) elementType, bText, xmlParserData); case TypeTags.ANYDATA_TAG, TypeTags.JSON_TAG -> { BArray tempArr = (BArray) ((BMap) xmlParserData.nodesStack.peek()).get(bFieldName); HashMap indexes = xmlParserData.arrayIndexes.get(xmlParserData.arrayIndexes.size() - 2); int currentIndex = indexes.get(bFieldName.getValue()); - if (arrayType.getState() == ArrayType.ArrayState.CLOSED && currentIndex >= arrayType.getSize()) { + if (fieldType.getState() == ArrayType.ArrayState.CLOSED && currentIndex >= fieldType.getSize()) { DataUtils.logArrayMismatchErrorIfProjectionNotAllowed(xmlParserData.allowDataProjection); return; } - tempArr.add(currentIndex, convertStringToRestExpType(bText, referredType)); - } - case TypeTags.UNION_TAG -> { - XmlParserData clonedAnalyzerData = XmlParserData.copy(xmlParserData); - for (Type memberType: ((UnionType) referredType).getMemberTypes()) { - try { - memberType = TypeUtils.getReferredType(memberType); - addTextToCurrentNodeIfExpTypeIsArray(memberType, arrayType, bFieldName, bText, xmlParserData); - return; - } catch (Exception ex) { - xmlParserData.resetFrom(clonedAnalyzerData); - int a = 1; - // ignore - } - } + tempArr.add(currentIndex, convertStringToRestExpType(bText, fieldType)); } } } @@ -484,17 +423,6 @@ private Object convertStringToExpType(BString value, Type expType) { if (expType.getTag() == TypeTags.ARRAY_TAG) { expType = ((ArrayType) expType).getElementType(); } - if (expType.getTag() == TypeTags.UNION_TAG) { - for (Type memberType: ((UnionType) expType).getMemberTypes()) { - memberType = TypeUtils.getReferredType(memberType); - try { - return convertStringToExpType(value, memberType); - } catch (Exception ex) { - int a = 1; - // ignore - } - } - } Object result = FromString.fromStringWithType(value, expType); if (result instanceof BError) { throw (BError) result; @@ -508,7 +436,7 @@ private Object convertStringToRestExpType(BString value, Type expType) { return convertStringToRestExpType(value, ((ArrayType) expType).getElementType()); } case TypeTags.INT_TAG, TypeTags.FLOAT_TAG, TypeTags.DECIMAL_TAG, TypeTags.STRING_TAG, - TypeTags.BOOLEAN_TAG, TypeTags.UNION_TAG -> { + TypeTags.BOOLEAN_TAG, TypeTags.UNION_TAG -> { return convertStringToExpType(value, expType); } case TypeTags.ANYDATA_TAG, TypeTags.JSON_TAG -> { @@ -636,23 +564,8 @@ private void initializeNextValueBasedOnExpectedType(String fieldName, Type field case TypeTags.MAP_TAG, TypeTags.ANYDATA_TAG, TypeTags.JSON_TAG -> initializeAttributesForNextMappingValue(xmlParserData, fieldName, fieldType); case TypeTags.TYPE_REFERENCED_TYPE_TAG -> - initializeNextValueBasedOnExpectedType(fieldName, TypeUtils.getReferredType(fieldType), temp, - currentNode, xmlParserData); - case TypeTags.UNION_TAG -> { - XmlParserData clonedAnalyzerData = XmlParserData.copy(xmlParserData); - for (Type memberType: ((UnionType) fieldType).getMemberTypes()) { - memberType = TypeUtils.getReferredType(memberType); - try { - initializeNextValueBasedOnExpectedType(fieldName, memberType, temp, currentNode, xmlParserData); - return; - } catch (Exception ex) { - xmlParserData.resetFrom(clonedAnalyzerData); - currentNode.put(StringUtils.fromString(fieldName), null); - int a = 1; - // ignore - } - } - } + initializeNextValueBasedOnExpectedType(fieldName, TypeUtils.getReferredType(fieldType), temp, + currentNode, xmlParserData); } } @@ -668,8 +581,8 @@ private void updateNextArrayMember(XMLStreamReader xmlStreamReader, XmlParserDat case TypeTags.MAP_TAG, TypeTags.ANYDATA_TAG, TypeTags.JSON_TAG -> initializeAttributesForNextMappingValue(xmlParserData, fieldName, fieldType); case TypeTags.TYPE_REFERENCED_TYPE_TAG -> - updateNextArrayMember(xmlStreamReader, xmlParserData, fieldName, fieldType, - TypeUtils.getReferredType(type)); + updateNextArrayMember(xmlStreamReader, xmlParserData, fieldName, fieldType, + TypeUtils.getReferredType(type)); } } @@ -871,7 +784,7 @@ private BString readElementRest(XMLStreamReader xmlStreamReader, XmlParserData x handleAttributesRest(xmlStreamReader, restType, next, useSemanticEquality); Object temp = xmlParserData.currentNode.get( - StringUtils.fromString(lastElement.getLocalPart())); + StringUtils.fromString(lastElement.getLocalPart())); BMap mapValue = xmlParserData.currentNode; if (temp == null) { xmlParserData.currentNode.put(currentFieldName, next); @@ -910,7 +823,7 @@ private BString readElementRest(XMLStreamReader xmlStreamReader, XmlParserData x return currentFieldName; } - if (!DataUtils.isArrayValueAssignable(restType)) { + if (!DataUtils.isArrayValueAssignable(restType.getTag())) { throw DiagnosticLog.error( DiagnosticErrorCode.FOUND_ARRAY_FOR_NON_ARRAY_TYPE, restType, elemQName.getLocalPart()); } @@ -955,7 +868,7 @@ private boolean endElementRest(XMLStreamReader xmlStreamReader, XmlParserData xm if (xmlParserData.siblings.contains(elemQName)) { // TODO: This place behaviour is strange need to check and fix it, Properly. popMappingTypeStacks(xmlParserData); -// xmlParserData.attributeHierarchy.pop(); + // xmlParserData.attributeHierarchy.pop(); xmlParserData.arrayIndexes.pop(); } xmlParserData.restFieldsPoints.pop(); @@ -993,8 +906,8 @@ private void readTextRest(XMLStreamReader xmlStreamReader, @SuppressWarnings("unchecked") private void convertTextRestAndUpdateCurrentNodeForRestType(BMap currentNode, - BString currentFieldName, - BString bText, Type restType, BString textFieldName) { + BString currentFieldName, + BString bText, Type restType, BString textFieldName) { Object currentElement = currentNode.get(currentFieldName); Object result = convertStringToRestExpType(bText, restType); @@ -1237,70 +1150,23 @@ static class TextValue { * @since 0.1.0 */ public static class XmlParserData { - private Stack nodesStack = new Stack<>(); - private Stack> fieldHierarchy = new Stack<>(); + private final Stack nodesStack = new Stack<>(); + private final Stack> fieldHierarchy = new Stack<>(); Stack> visitedFieldHierarchy = new Stack<>(); - private Stack> attributeHierarchy = new Stack<>(); - private Stack restTypes = new Stack<>(); - private Stack restFieldsPoints = new Stack<>(); - private Stack recordTypeStack = new Stack<>(); + private final Stack> attributeHierarchy = new Stack<>(); + private final Stack restTypes = new Stack<>(); + private final Stack restFieldsPoints = new Stack<>(); + private final Stack recordTypeStack = new Stack<>(); Stack> arrayIndexes = new Stack<>(); private RecordType rootRecord; private Field currentField; private QualifiedName rootElement; - private Stack> parents = new Stack<>(); + private final Stack> parents = new Stack<>(); private QualifiedNameMap siblings = new QualifiedNameMap<>(new LinkedHashMap<>()); private BMap currentNode; private String attributePrefix; private String textFieldName; private boolean allowDataProjection; private boolean useSemanticEquality; - - @SuppressWarnings("unchecked") - public static XmlParserData copy(XmlParserData analyzerData) { - XmlParserData data = new XmlParserData(); - data.nodesStack = (Stack) analyzerData.nodesStack.clone(); - data.fieldHierarchy = (Stack>) analyzerData.fieldHierarchy.clone(); - data.visitedFieldHierarchy = (Stack>) analyzerData.visitedFieldHierarchy.clone(); - data.attributeHierarchy = (Stack>) analyzerData.attributeHierarchy.clone(); - data.restTypes = (Stack) analyzerData.restTypes.clone(); - data.restFieldsPoints = (Stack) analyzerData.restFieldsPoints.clone(); - data.recordTypeStack = (Stack) analyzerData.recordTypeStack.clone(); - data.arrayIndexes = (Stack>) analyzerData.arrayIndexes.clone(); - data.rootRecord = analyzerData.rootRecord; - data.currentField = analyzerData.currentField; - data.rootElement = analyzerData.rootElement; - data.parents = (Stack>) analyzerData.parents.clone(); - data.siblings = new QualifiedNameMap<>(Map.copyOf(analyzerData.siblings.getMembers()), - Map.copyOf(analyzerData.siblings.getStringToQnamesMap())); - data.currentNode = analyzerData.currentNode; - data.attributePrefix = analyzerData.attributePrefix; - data.textFieldName = analyzerData.textFieldName; - data.allowDataProjection = analyzerData.allowDataProjection; - data.useSemanticEquality = analyzerData.useSemanticEquality; - - return data; - } - - public void resetFrom(XmlParserData analyzerData) { - this.nodesStack = analyzerData.nodesStack; - this.fieldHierarchy = analyzerData.fieldHierarchy; - this.visitedFieldHierarchy = analyzerData.visitedFieldHierarchy; - this.attributeHierarchy = analyzerData.attributeHierarchy; - this.restTypes = analyzerData.restTypes; - this.restFieldsPoints = analyzerData.restFieldsPoints; - this.recordTypeStack = analyzerData.recordTypeStack; - this.arrayIndexes = analyzerData.arrayIndexes; - this.rootRecord = analyzerData.rootRecord; - this.currentField = analyzerData.currentField; - this.rootElement = analyzerData.rootElement; - this.parents = analyzerData.parents; - this.siblings = analyzerData.siblings; - this.currentNode = analyzerData.currentNode; - this.attributePrefix = analyzerData.attributePrefix; - this.textFieldName = analyzerData.textFieldName; - this.allowDataProjection = analyzerData.allowDataProjection; - this.useSemanticEquality = analyzerData.useSemanticEquality; - } } } From 46d0f1c9b7f59c269894836e8bd40945c78399cd Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Tue, 27 Aug 2024 13:37:31 +0530 Subject: [PATCH 07/16] Add tests for union type implementation --- ballerina/tests/parse_string_union_test.bal | 576 +++++++++++++++++++ ballerina/tests/parse_type_union_test.bal | 574 +++++++++++++++++++ ballerina/tests/union_type_test.bal | 578 -------------------- 3 files changed, 1150 insertions(+), 578 deletions(-) create mode 100644 ballerina/tests/parse_string_union_test.bal create mode 100644 ballerina/tests/parse_type_union_test.bal delete mode 100644 ballerina/tests/union_type_test.bal diff --git a/ballerina/tests/parse_string_union_test.bal b/ballerina/tests/parse_string_union_test.bal new file mode 100644 index 0000000..91c1323 --- /dev/null +++ b/ballerina/tests/parse_string_union_test.bal @@ -0,0 +1,576 @@ +import ballerina/data.xmldata; +import ballerina/test; + +string x1 = "42"; + +type A11 record { + int[]|string \#content; +}; + +type A12 record {int[] \#content;}|record {int \#content;}; + +type A13 record {| + int[]|int...; +|}; + +type A14 record { + boolean|int \#content; +}; + +@test:Config +function testParseStringUnionTypes1() { + A11|error a11 = xmldata:parseString(x1); + test:assertEquals(a11, {"#content": "42"}); + + A12|error a12 = xmldata:parseString(x1); + test:assertEquals(a12, {"#content":42}); + + // // bug #9 + // A13|error a13 = xmldata:parseString(x1); + // test:assertEquals(a13, {"#content":42}); + + A14|error a14 = xmldata:parseString(x1); + test:assertEquals(a14, {"#content": 42}); +} + +string x2 = string `Sample Text`; + +type A21 record { + int[]|string \#content; + int|boolean|string a1; +}; + +type A22 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {int \#content; int a1;}; + +type A23 record{int \#content;}|record {string \#content; int|decimal a1;}; + +// type A24 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|float|string|int...;|}; + +type A25 record{int \#content;}|record {string \#content; int|decimal a1; int|decimal a2;}; + +type A26 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|boolean?|string?...;|}; + +@test:Config +function testParseStringUnionTypes2() { + A21|error a21 = xmldata:parseString(x2); + test:assertEquals(a21, {"#content":"Sample Text","a1":2024}); + + A22|error a22 = xmldata:parseString(x2); + test:assertTrue(a22 is xmldata:Error); + test:assertEquals(( a22).message(), "source value cannot convert into 'wso2/xml_data_dev:0:A22'"); + + // // bug #4 + // A23|error a23 = xmldata:parseString(x2); + // test:assertEquals(a23, {"#content":"Sample Text","a1":2024, "a2": 3.14}); + + // // bug #5 + // A24|error a24 = xmldata:parseString(x2); + // test:assertEquals(a24, {"a1":2024, "a2": 3.14}); + + A25|error a25 = xmldata:parseString(x2); + test:assertEquals(a25, {"#content":"Sample Text","a1":2024, "a2": 3.14}); + + A26|error a26 = xmldata:parseString(x2); + test:assertEquals(a26, {"#content":"Sample Text"}); +} + +string x3 = string `100`; + +type A31 record { + int[]|string B; +}; + +type A31P2 record { + @xmldata:Name { + value: "B" + } + string|int[] b; +}; + +type A32 record { + @xmldata:Name { + value: "B" + } + boolean|record{int \#content;}|int[] b; +}; + +type A33 record{string|int[] b1;}|record {|int|string B;|}; + +type A34 record { + record{int \#content; int b1;}|record{int \#content;}[]|record{int \#content;} B; +}; + +type A35 record {| + record{|string...;|}...; +|}; + +@test:Config +function testParseStringUnionTypes3() { +// custom bug + // A31|error a31 = xmldata:parseString(x3); + // test:assertEquals(a31, {"B":"100"}); + + A31P2|error a31p2 = xmldata:parseString(x3); + test:assertEquals(a31p2, {"b":"100"}); + + A32|error a32 = xmldata:parseString(x3); + test:assertEquals(a32, {"b":{"#content":100}}); + + A33|error a33 = xmldata:parseString(x3); + test:assertEquals(a33, {"B":100}); + + A34|error a34 = xmldata:parseString(x3); + test:assertEquals(a34, {"B":[{"#content":100}]}); + +// custom bug + // A35|error a35 = xmldata:parseString(x3); + // test:assertEquals(a35, {"B":{"#content":"100"}}); +} + +string x4 = string `Nested Content`; + +type A41 record {| + int|record{|string \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; +|}; + +type A41P2 record {| + int|record{|boolean \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; +|}; + +type A42 record {| + int|record{|int...;|}|record{string \#content; int[]|int b1;}|record{} B; +|}; + +type A43P2 record {|int[]|record{|string \#content;|} B;|}; +type A43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|A43P2; + +@test:Config +function testParseStringUnionTypes4() { + // // bug #2 + // A41|error a41 = xmldata:parseString(x4); + // test:assertEquals(a41, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); + + A41P2|error a41p2 = xmldata:parseString(x4); + test:assertEquals(a41p2, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); + + A42|error a42 = xmldata:parseString(x4); + test:assertEquals(a42, {"B":{"#content":"Nested Content","b1":99}}); + + A43|error a43 = xmldata:parseString(x4); + test:assertEquals(a43, {"B":{"#content":"Nested Content"}}); +} + +string x5 = string `123456`; + +type Ref record {|int...;|}; +type RefArr Ref[]; + +type A51 record {RefArr|int[] B;}; +type A52 record {int[]|RefArr B;}; +type A53 record {Ref|int[] B;}; +type A54 record {|Ref|int[]...;|}; +type A55 record {|Ref[]|int[]...;|}; +type A56 record {|(Ref|int)[]...;|}; +type A57 record {|(Ref|int)[] B;|}; +type A58 record {|(int|Ref)[]...;|}; + +@test:Config +function testParseStringUnionTypes5() { + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A51|error a51 = xmldata:parseString(x5); + // test:assertEquals(a51, {"B":[{"#content":123},{"#content":456}]}); + + A52|error a52 = xmldata:parseString(x5); + test:assertEquals(a52, {"B":[123,456]}); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A53|error a53 = xmldata:parseString(x5); + // test:assertEquals(a53, {); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A54|error a54 = xmldata:parseString(x5); + // test:assertEquals(a54, {}); + + // // bug #6 + // A55|error a55 = xmldata:parseString(x5); + // test:assertEquals(a55, {"B":[123,456]}); + + A56|error a56 = xmldata:parseString(x5); + test:assertEquals(a56, {"B":[{"#content":123},{"#content":456}]}); + + A57|error a57 = xmldata:parseString(x5); + test:assertEquals(a57, {"B":[{"#content":123},{"#content":456}]}); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A58|error a58 = xmldata:parseString(x5); + // test:assertEquals(a58, {"B":[{"#content":123},{"#content":456}]}); +} + +string x6 = string `ToyotaYamaha`; + +type A61 record {string C; record {|string \#content;|}[]|string B;}; +type A62 record {record {|boolean|record{(record{}|int[])[]|string \#content;}|string \#content;|}|string B; string C;}; +type A63 record {|record {|string \#content;|}[]|record {|string \#content;|}...;|}; +type A64 record {|record {|boolean|record{}|record{}[]|string \#content;|}[]|string B;|}; + +@test:Config +function testParseStringUnionTypes6() { + A61|error a61 = xmldata:parseString(x6); + test:assertEquals(a61, {"C":"Yamaha","B":[{"#content":"Toyota"}]}); + + A62|error a62 = xmldata:parseString(x6); + test:assertEquals(a62, {"B":"Toyota","C":"Yamaha"}); + + A63|error a63 = xmldata:parseString(x6); + test:assertEquals(a63, {"B":[{"#content":"Toyota"}],"C":[{"#content":"Yamaha"}]}); + + A64|error a64 = xmldata:parseString(x6); + test:assertEquals(a64, {"B":[{"#content":"Toyota"}]}); +} + +string x7 = string `BrickWaterAir`; + +type A71 record {record {|string...;|}[]|string[] B;}; +type A72 record {string[]|record {|string...;|}[] B;}; +type A73 record {record {|string \@content;|}|string[] B;}; +type A74 record {|record {|string...;|}|string[]...;|}; +type A75 record {|record {|string...;|}[]|string[]...;|}; +type A76 record {|(record {|string...;|}|string)[]...;|}; +type A77 record {|(record {|string...;|}|string)[] B;|}; +type A78 record {|(string|record {|string...;|})[]...;|}; + +@test:Config +function testParseStringUnionTypes7() { + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A71|error a71 = xmldata:parseString(x7); + // test:assertEquals(a71, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); + + A72|error a72 = xmldata:parseString(x7); + test:assertEquals(a72, {"B":["Brick","Water"],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); + + A73|error a73 = xmldata:parseString(x7); + test:assertTrue(a73 is xmldata:Error); + test:assertEquals((a73).message(), "unsupported input type"); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A74|error a74 = xmldata:parseString(x7); + // test:assertEquals(a74, {"B":{"#content":"Water"},"C":{"#content":"Air"}); + + // // bug #6 + // A75|error a75 = xmldata:parseString(x7); + // test:assertEquals(a75, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); + + // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A76|error a76 = xmldata:parseString(x7); + // test:assertEquals(a76, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); + + // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A77|error a77 = xmldata:parseString(x7); + // test:assertEquals(a77, {"B":[{"#content":"Brick"},{"#content":"Water"}]}); + + // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A78|error a78 = xmldata:parseString(x7); + // test:assertEquals(a78, {"B":{"#content":"Water"},"C":{"#content":"Air"}}); +} + +string x8 = string ` + + First + + + Second + Third + + + Fourth + Fifth + + `; + +type A81P2 record{string \#content;}[]; +type A81P1 record{string \#content;}; +type A81 record {record{|(A81P1|A81P2)[] C?;|}[] B;}; +type A81Part2 record {record{(A81P1|A81P2)[] C?;}[] B;}; +type A82P2 record{string \#content;}[][]; +type A82P1 record{string \#content;}[]; +type A82 record {record{|A82P1|A82P2 C?;|}[] B;}; +type A82Part2 record {record{A82P1|A82P2 C?;}[] B;}; +type A83P2 record{string \#content;}[]; +type A83P1 record{string \#content;}; +type A83 record {|record{|(A83P1|A83P2)[] C?;|}...;|}; +type A84P2 record{string \#content;}[]; +type A84P1 record{string \#content;}; +type A84 record {|record{|(A84P1|A84P2)[] C?;|}[]...;|}; +type A85 record{|record{}...;|}|record{|record{}[]...;|}; +type A86 record{|record{}[]...;|}|record{|record{}...;|}; + +@test:Config +function testParseStringUnionTypes8() { + A81|error a81 = xmldata:parseString(x8); + test:assertEquals(a81, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + + A81Part2|error a81p2 = xmldata:parseString(x8); + test:assertEquals(a81p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, + {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); + + A82|error a82 = xmldata:parseString(x8); + test:assertEquals(a82, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + + A82Part2|error a82p2 = xmldata:parseString(x8); + test:assertEquals(a82p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, + {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); + + A83|error a83 = xmldata:parseString(x8); + test:assertEquals(a83, {B: {}}); + + A84|error a84 = xmldata:parseString(x8); + test:assertEquals(a84, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + + A85|error a85 = xmldata:parseString(x8); + test:assertEquals(a85, {"B":{"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}}); + + A86|error a86 = xmldata:parseString(x8); + test:assertEquals(a86, {"B":[{"C":{"c1":"inner1","c2":"value","#content":"First"}},{"C":[{"c1":"inner2","c2":"value","#content":"Second"}, + {"c1":"inner3","c2":"value","#content":"Third"}]},{"D":{"d1":"inner4","d2":"value","#content":"Fourth"}, + "E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); +} + +string x9 = string ` + + 100 + 200 + 300 + + + 400 + 500 + 600 + + `; + +type A91P1 record{string[]|record{string \#content;}[] C;}; +type A91 record {A91P1[] B;}; +type A92P1 record{(string|record{string \#content;})[] C;}; +type A92 record {A92P1[] B;}; +type A93P1 record{record{string \#content;}[]|string[] C;}; +type A93 record {A93P1[] B;}; +type A94P1 record{|(record{string \#content;}|string)[]...;|}; +type A94 record {A94P1[] B;}; + +@test:Config +function testParseStringUnionTypes9() { + A91|error a91 = xmldata:parseString(x9); + test:assertEquals(a91, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); + + A92|error a92 = xmldata:parseString(x9); + test:assertEquals(a92, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); + + A93|error a93 = xmldata:parseString(x9); + test:assertEquals(a93, {"B":[{"C":[{"#content":"100"}, + {"#content":"200"},{"#content":"300"}]}, + {"C":[{"#content":"400"},{"#content":"500"}, + {"#content":"600"}]}]}); + + A94|error a94 = xmldata:parseString(x9); + test:assertEquals(a94, {"B":[{"C":[{"#content":"100"}, + {"#content":"200"},{"#content":"300"}]}, + {"C":[{"#content":"400"},{"#content":"500"}, + {"#content":"600"}]}]}); +} + +string x10 = string ` + + Deep Value1 + Deep Value2 + + + Deep Value3 + Deep Value4 + + `; + +type A101P1 record{string[]|record{string \#content;}[] C;}; +type A101 record {A101P1[] B;}; +type A102P1 record{(string|record{string \#content;})[] C;}; +type A102 record {A102P1[] B;}; +type A103P1 record{record{string \#content;}[]|string[] C;}; +type A103 record {A103P1[] B;}; +type A104P1 record{(record{string \#content;}|string)[] C;}; +type A104 record {A104P1[] B;}; + +@test:Config +function testParseStringUnionTypes10() { + A101|error a101 = xmldata:parseString(x10); + test:assertEquals(a101, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); + + A102|error a102 = xmldata:parseString(x10); + test:assertEquals(a102, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); + + A103|error a103 = xmldata:parseString(x10); + test:assertEquals(a103, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, + {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); + + A104|error a104 = xmldata:parseString(x10); + test:assertEquals(a104, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, + {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); +} + +string x11 = string ` + + Deep Value1 + Deep Value2 + + + Deep Value3 + Deep Value2 + + `; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type A111 record { + string a1; + (B111|B112)[] B; +}; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type A112 record {| + string a1; + (B111|B112)[]...; +|}; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type B111 record { + @xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string b1; + (C111|C112)[] C; +}; + +@xmldata:Namespace { + prefix: "ns2", + uri: "http://example.com/ns2" +} +type B112 record { + @xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string b1; + (C111|C112)[] C; +}; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type C111 record { + @xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string c1; + string \#content; +}; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type C112 record { + @xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string c1; + string \#content; +}; + +@test:Config +function testParseStringUnionTypes11() { + A111|error a111 = xmldata:parseString(x11); + test:assertEquals(a111, {"a1":"outer","B":[{"b1":"middle","C":[{"c1":"inner","#content":"Deep Value1"}, + {"c1":"inner","#content":"Deep Value2"}]}, + {"b1":"middle","C":[{"c1":"inner","#content":"Deep Value3"}, + {"c1":"inner","#content":"Deep Value2"}]}]}); + + A112|error a112 = xmldata:parseString(x11); + test:assertEquals(a112, {"a1":"outer","B":[{"b1":"middle","C":[{"c1":"inner","#content":"Deep Value1"}, + {"c1":"inner","#content":"Deep Value2"}]}, + {"b1":"middle","C":[{"c1":"inner","#content":"Deep Value3"}, + {"c1":"inner","#content":"Deep Value2"}]}]}); +} + +string x12 = string ` + + Deep Value1 + Deep Value2 + + + Deep Value3 + Deep Value4 + + `; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type A121 record { + string a1; + (B121|B122)[] B; +}; + +type A122 record {| + string a1; + (B121|B122)[]...; +|}; + +@xmldata:Namespace { + prefix: "ns222", + uri: "http://example.com/ns2" +} +type B121 record { + string b1; + C121[] C; +}; + +@xmldata:Namespace { + prefix: "ns2", + uri: "http://example.com/ns2" +} +type B122 record { + string b1; + C121[] C; +}; + +@xmldata:Namespace { + prefix: "ns3", + uri: "http://example.com/ns3" +} +type C121 record { + string c1; + string \#content; +}; + +@test:Config +function testParseStringUnionTypes12() { + A121|error a121 = xmldata:parseString(x12); + test:assertEquals(a121, {"a1":"outer","B":[{"b1":"middle", "C":[{"c1":"inner","#content":"Deep Value1"}, + {"c1":"inner","#content":"Deep Value2"}]},{"b1":"middle", + "C":[{"c1":"inner","#content":"Deep Value3"},{"c1":"inner","#content":"Deep Value4"}]}]}); + A122|error a122 = xmldata:parseString(x12); + test:assertEquals(a122, {"a1":"outer","B":[{"b1":"middle", "C":[{"c1":"inner","#content":"Deep Value1"}, + {"c1":"inner","#content":"Deep Value2"}]},{"b1":"middle", + "C":[{"c1":"inner","#content":"Deep Value3"},{"c1":"inner","#content":"Deep Value4"}]}]}); +} diff --git a/ballerina/tests/parse_type_union_test.bal b/ballerina/tests/parse_type_union_test.bal new file mode 100644 index 0000000..7f35f0b --- /dev/null +++ b/ballerina/tests/parse_type_union_test.bal @@ -0,0 +1,574 @@ +import ballerina/data.xmldata; +import ballerina/test; + +xml x1 = xml `42`; + +type A11 record { + int[]|string \#content; +}; + +type A12 record {int[] \#content;}|record {int \#content;}; + +type A13 record {| + int[]|string...; +|}; + +type A14 record { + boolean|int \#content; +}; + +@test:Config +function testTraverseUnionTypes1() { + // // bug #3 + A11|error a11 = xmldata:parseAsType(x1); + test:assertEquals(a11, {"#content": "42"}); + + A12|error a12 = xmldata:parseAsType(x1); + test:assertEquals(a12, {"#content":42}); + + A13|error a13 = xmldata:parseAsType(x1); + test:assertEquals(a13, {"#content":"42"}); + + A14|error a14 = xmldata:parseAsType(x1); + test:assertEquals(a14, {"#content": 42}); +} + +xml x2 = xml `Sample Text`; + +type A21 record { + int[]|string \#content; + int|boolean|string a1; +}; + +type A22 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {int \#content; int a1;}; + +type A23 record{int \#content;}|record {string \#content; int|decimal a1;}; + +// type A24 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|float|string|int...;|}; + +type A25 record{int \#content;}|record {string \#content; int|decimal a1; int|decimal a2;}; + +type A26 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|boolean?|string?...;|}; + +@test:Config +function testTraverseUnionTypes2() { + A21|error a21 = xmldata:parseAsType(x2); + test:assertEquals(a21, {"#content":"Sample Text","a1":2024}); + + A22|error a22 = xmldata:parseAsType(x2); + test:assertTrue(a22 is xmldata:Error); + test:assertEquals(( a22).message(), "source value cannot convert into 'wso2/xml_data_dev.traverseTest:0:A22'"); + + // // bug #4 + // A23|error a23 = xmldata:parseAsType(x2); + // test:assertEquals(a23, {"#content":"Sample Text","a1":2024, "a2": 3.14}); + + // // bug #5 + // A24|error a24 = xmldata:parseAsType(x2); + // test:assertEquals(a24, {"a1":2024, "a2": 3.14}); + + A25|error a25 = xmldata:parseAsType(x2); + test:assertEquals(a25, {"#content":"Sample Text","a1":2024, "a2": 3.14}); + + A26|error a26 = xmldata:parseAsType(x2); + test:assertEquals(a26, {"#content":"Sample Text"}); +} + +xml x3 = xml `100`; + +type A31 record { + int[]|string B; +}; + +type A31P2 record { + @xmldata:Name { + value: "B" + } + string|int[] b; +}; + +type A32 record { + @xmldata:Name { + value: "B" + } + boolean|record{int \#content;}|int[] b; +}; + +type A33 record{string|int[] b1;}|record {|int|string B;|}; + +type A34 record { + record{int \#content; int b1;}|record{int \#content;}[]|record{int \#content;} B; +}; + +type A35 record {| + record{|boolean|string...;|}...; +|}; + +@test:Config +function testTraverseUnionTypes3() { + A31|error a31 = xmldata:parseAsType(x3); + test:assertEquals(a31, {"B":[100]}); + + A31P2|error a31p2 = xmldata:parseAsType(x3); + test:assertEquals(a31p2, {"b":"100"}); + + A32|error a32 = xmldata:parseAsType(x3); + test:assertEquals(a32, {"b":{"#content":100}}); + + A33|error a33 = xmldata:parseAsType(x3); + test:assertEquals(a33, {"B":100}); + + A34|error a34 = xmldata:parseAsType(x3); + test:assertEquals(a34, {"B":[{"#content":100}]}); + + A35|error a35 = xmldata:parseAsType(x3); + test:assertEquals(a35, {"B":{"#content":"100"}}); +} + +xml x4 = xml `Nested Content`; + +type A41 record {| + int|record{|string \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; +|}; + +type A41P2 record {| + int|record{|boolean \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; +|}; + +type A42 record {| + int|record{|int...;|}|record{string \#content; int[]|int b1;}|record{} B; +|}; + +type A43P2 record {|int[]|record{|string \#content;|} B;|}; +type A43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|A43P2; + +@test:Config +function testTraverseUnionTypes4() { + // // bug #2 + // A41|error a41 = xmldata:parseAsType(x4); + // test:assertEquals(a41, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); + + A41P2|error a41p2 = xmldata:parseAsType(x4); + test:assertEquals(a41p2, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); + + A42|error a42 = xmldata:parseAsType(x4); + test:assertEquals(a42, {"B":{"#content":"Nested Content","b1":99}}); + + A43|error a43 = xmldata:parseAsType(x4); + test:assertEquals(a43, {"B":{"#content":"Nested Content"}}); +} + +xml x5 = xml `123456`; + +type Ref record {|int...;|}; +type RefArr Ref[]; + +type A51 record {RefArr|int[] B;}; +type A52 record {int[]|RefArr B;}; +type A53 record {Ref|int[] B;}; +type A54 record {|Ref|int[]...;|}; +type A55 record {|Ref[]|int[]...;|}; +type A56 record {|(Ref|int)[]...;|}; +type A57 record {|(Ref|int)[] B;|}; +type A58 record {|(int|Ref)[]...;|}; + +@test:Config +function testTraverseUnionTypes5() { + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A51|error a51 = xmldata:parseAsType(x5); + // test:assertEquals(a51, {"B":[{"#content":123},{"#content":456}]}); + + A52|error a52 = xmldata:parseAsType(x5); + test:assertEquals(a52, {"B":[123,456]}); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A53|error a53 = xmldata:parseAsType(x5); + // test:assertEquals(a53, {); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A54|error a54 = xmldata:parseAsType(x5); + // test:assertEquals(a54, {}); + + // // bug #6 + // A55|error a55 = xmldata:parseAsType(x5); + // test:assertEquals(a55, {"B":[123,456]}); + + A56|error a56 = xmldata:parseAsType(x5); + test:assertEquals(a56, {"B":[{"#content":123},{"#content":456}]}); + + A57|error a57 = xmldata:parseAsType(x5); + test:assertEquals(a57, {"B":[{"#content":123},{"#content":456}]}); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A58|error a58 = xmldata:parseAsType(x5); + // test:assertEquals(a58, {"B":[{"#content":123},{"#content":456}]}); +} + +xml x6 = xml `ToyotaYamaha`; + +type A61 record {string C; record {|string \#content;|}[]|string B;}; +type A62 record {record {|boolean|record{(record{}|int[])[]|string \#content;}|string \#content;|}|string B; string C;}; +type A63 record {|record {|string \#content;|}[]|record {|string \#content;|}...;|}; +type A64 record {|record {|boolean|record{}|record{}[]|string \#content;|}[]|string B;|}; + +@test:Config +function testTraverseUnionTypes6() { + A61|error a61 = xmldata:parseAsType(x6); + test:assertEquals(a61, {"C":"Yamaha","B":[{"#content":"Toyota"}]}); + + A62|error a62 = xmldata:parseAsType(x6); + test:assertEquals(a62, {"B":"Toyota","C":"Yamaha"}); + + A63|error a63 = xmldata:parseAsType(x6); + test:assertEquals(a63, {"B":[{"#content":"Toyota"}],"C":[{"#content":"Yamaha"}]}); + + A64|error a64 = xmldata:parseAsType(x6); + test:assertEquals(a64, {"B":[{"#content":"Toyota"}]}); +} + +xml x7 = xml `BrickWaterAir`; + +type A71 record {record {|string...;|}[]|string[] B;}; +type A72 record {string[]|record {|string...;|}[] B;}; +type A73 record {record {|string \@content;|}|string[] B;}; +type A74 record {|record {|string...;|}|string[]...;|}; +type A75 record {|record {|string...;|}[]|string[]...;|}; +type A76 record {|(record {|string...;|}|string)[]...;|}; +type A77 record {|(record {|string...;|}|string)[] B;|}; +type A78 record {|(string|record {|string...;|})[]...;|}; + +@test:Config +function testTraverseUnionTypes7() { + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A71|error a71 = xmldata:parseAsType(x7); + // test:assertEquals(a71, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); + + A72|error a72 = xmldata:parseAsType(x7); + test:assertEquals(a72, {"B":["Brick","Water"],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); + + A73|error a73 = xmldata:parseAsType(x7); + test:assertTrue(a73 is xmldata:Error); + test:assertEquals((a73).message(), "unsupported input type"); + + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A74|error a74 = xmldata:parseAsType(x7); + // test:assertEquals(a74, {"B":{"#content":"Water"},"C":{"#content":"Air"}); + + // // bug #6 + // A75|error a75 = xmldata:parseAsType(x7); + // test:assertEquals(a75, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); + + // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A76|error a76 = xmldata:parseAsType(x7); + // test:assertEquals(a76, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); + + // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A77|error a77 = xmldata:parseAsType(x7); + // test:assertEquals(a77, {"B":[{"#content":"Brick"},{"#content":"Water"}]}); + + // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // A78|error a78 = xmldata:parseAsType(x7); + // test:assertEquals(a78, {"B":{"#content":"Water"},"C":{"#content":"Air"}}); +} + +xml x8 = xml ` + + First + + + Second + Third + + + Fourth + Fifth + + `; + +type A81P2 record{string \#content;}[]; +type A81P1 record{string \#content;}; +type A81 record {record{|(A81P1|A81P2)[] C?;|}[] B;}; +type A81Part2 record {record{(A81P1|A81P2)[] C?;}[] B;}; +type A82P2 record{string \#content;}[][]; +type A82P1 record{string \#content;}[]; +type A82 record {record{|A82P1|A82P2 C?;|}[] B;}; +type A82Part2 record {record{A82P1|A82P2 C?;}[] B;}; +type A83P2 record{string \#content;}[]; +type A83P1 record{string \#content;}; +type A83 record {|record{|(A83P1|A83P2)[] C?;|}...;|}; +type A84P2 record{string \#content;}[]; +type A84P1 record{string \#content;}; +type A84 record {|record{|(A84P1|A84P2)[] C?;|}[]...;|}; +type A85 record{|record{}...;|}|record{|record{}[]...;|}; +type A86 record{|record{}[]...;|}|record{|record{}...;|}; + +@test:Config +function testTraverseUnionTypes8() { + A81|error a81 = xmldata:parseAsType(x8); + test:assertEquals(a81, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + + A81Part2|error a81p2 = xmldata:parseAsType(x8); + test:assertEquals(a81p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, + {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); + + A82|error a82 = xmldata:parseAsType(x8); + test:assertEquals(a82, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + + A82Part2|error a82p2 = xmldata:parseAsType(x8); + test:assertEquals(a82p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, + {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); + + A83|error a83 = xmldata:parseAsType(x8); + test:assertEquals(a83, {B: {}}); + + A84|error a84 = xmldata:parseAsType(x8); + test:assertEquals(a84, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); + + A85|error a85 = xmldata:parseAsType(x8); + test:assertEquals(a85, {"B":{"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}}); + + A86|error a86 = xmldata:parseAsType(x8); + test:assertEquals(a86, {"B":[{"C":{"c1":"inner1","c2":"value","#content":"First"}},{"C":[{"c1":"inner2","c2":"value","#content":"Second"}, + {"c1":"inner3","c2":"value","#content":"Third"}]},{"D":{"d1":"inner4","d2":"value","#content":"Fourth"}, + "E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); +} + +xml x9 = xml ` + + 100 + 200 + 300 + + + 400 + 500 + 600 + + `; + +type A91P1 record{string[]|record{string \#content;}[] C;}; +type A91 record {A91P1[] B;}; +type A92P1 record{(string|record{string \#content;})[] C;}; +type A92 record {A92P1[] B;}; +type A93P1 record{record{string \#content;}[]|string[] C;}; +type A93 record {A93P1[] B;}; +type A94P1 record{|(record{string \#content;}|string)[]...;|}; +type A94 record {A94P1[] B;}; + +@test:Config +function testTraverseUnionTypes9() { + A91|error a91 = xmldata:parseAsType(x9); + test:assertEquals(a91, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); + + A92|error a92 = xmldata:parseAsType(x9); + test:assertEquals(a92, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); + + A93|error a93 = xmldata:parseAsType(x9); + test:assertEquals(a93, {"B":[{"C":[{"#content":"100"}, + {"#content":"200"},{"#content":"300"}]}, + {"C":[{"#content":"400"},{"#content":"500"}, + {"#content":"600"}]}]}); + + A94|error a94 = xmldata:parseAsType(x9); + test:assertEquals(a94, {"B":[{"C":[{"#content":"100"}, + {"#content":"200"},{"#content":"300"}]}, + {"C":[{"#content":"400"},{"#content":"500"}, + {"#content":"600"}]}]}); +} + +xml x10 = xml ` + + Deep Value1 + Deep Value2 + + + Deep Value3 + Deep Value4 + + `; + +type A101P1 record{string[]|record{string \#content;}[] C;}; +type A101 record {A101P1[] B;}; +type A102P1 record{(string|record{string \#content;})[] C;}; +type A102 record {A102P1[] B;}; +type A103P1 record{record{string \#content;}[]|string[] C;}; +type A103 record {A103P1[] B;}; +type A104P1 record{(record{string \#content;}|string)[] C;}; +type A104 record {A104P1[] B;}; + +@test:Config +function testTraverseUnionTypes10() { + A101|error a101 = xmldata:parseAsType(x10); + test:assertEquals(a101, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); + + A102|error a102 = xmldata:parseAsType(x10); + test:assertEquals(a102, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); + + A103|error a103 = xmldata:parseAsType(x10); + test:assertEquals(a103, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, + {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); + + A104|error a104 = xmldata:parseAsType(x10); + test:assertEquals(a104, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, + {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); +} + +xml x11 = xml ` + + Deep Value1 + Deep Value2 + + + Deep Value3 + Deep Value2 + + `; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type A111 record { + string a1; + (B111|B112)[] B; +}; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type A112 record {| + string a1; + (B111|B112)[]...; +|}; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type B111 record { + @xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string b1; + (C111|C112)[] C; +}; + +@xmldata:Namespace { + prefix: "ns2", + uri: "http://example.com/ns2" +} +type B112 record { + @xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string b1; + (C111|C112)[] C; +}; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type C111 record { + @xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string c1; + string \#content; +}; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type C112 record { + @xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string c1; + string \#content; +}; + +@test:Config +function testTraverseUnionTypes11() { + A111|error a111 = xmldata:parseAsType(x11); + test:assertEquals(a111, {"a1":"outer","B":[{"b1":"middle","C":[{"c1":"inner","#content":"Deep Value1"}, + {"c1":"inner","#content":"Deep Value2"}]}, + {"b1":"middle","C":[{"c1":"inner","#content":"Deep Value3"}, + {"c1":"inner","#content":"Deep Value2"}]}]}); + + A112|error a112 = xmldata:parseAsType(x11); + test:assertEquals(a112, {"a1":"outer","B":[{"b1":"middle","C":[{"c1":"inner","#content":"Deep Value1"}, + {"c1":"inner","#content":"Deep Value2"}]}, + {"b1":"middle","C":[{"c1":"inner","#content":"Deep Value3"}, + {"c1":"inner","#content":"Deep Value2"}]}]}); +} + +xml x12 = xml ` + + Deep Value1 + Deep Value2 + + + Deep Value3 + Deep Value4 + + `; + +@xmldata:Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type A121 record { + string a1; + (B121|B122)[] B; +}; + +type A122 record {| + string a1; + (B121|B122)[]...; +|}; + +@xmldata:Namespace { + prefix: "ns2", + uri: "http://example.com/ns2" +} +type B121 record { + string b1; + C121[] C; +}; + +@xmldata:Namespace { + prefix: "ns2", + uri: "http://example.com/ns2" +} +type B122 record { + string b1; + C121[] C; +}; + +@xmldata:Namespace { + prefix: "ns3", + uri: "http://example.com/ns3" +} +type C121 record { + string c1; + string \#content; +}; + +@test:Config +function testTraverseUnionTypes12() { + A121|error a121 = xmldata:parseAsType(x12); + test:assertEquals(a121, {"a1":"outer","B":[{"b1":"middle", "C":[{"c1":"inner","#content":"Deep Value1"}, + {"c1":"inner","#content":"Deep Value2"}]},{"b1":"middle", + "C":[{"c1":"inner","#content":"Deep Value3"},{"c1":"inner","#content":"Deep Value4"}]}]}); + A122|error a122 = xmldata:parseAsType(x12); + test:assertEquals(a122, {"a1":"outer","B":[{"b1":"middle", "C":[{"c1":"inner","#content":"Deep Value1"}, + {"c1":"inner","#content":"Deep Value2"}]},{"b1":"middle", + "C":[{"c1":"inner","#content":"Deep Value3"},{"c1":"inner","#content":"Deep Value4"}]}]}); +} diff --git a/ballerina/tests/union_type_test.bal b/ballerina/tests/union_type_test.bal deleted file mode 100644 index 85029b1..0000000 --- a/ballerina/tests/union_type_test.bal +++ /dev/null @@ -1,578 +0,0 @@ -// import ballerina/data.xmldata; -// // import ballerina/io; -// import ballerina/test; - -// xml x1 = xml `42`; - -// type A11 record { -// int[]|string \#content; -// }; - -// type A12 record {int[] \#content;}|record {int \#content;}; - -// type A13 record {| -// int[]|string...; -// |}; - -// type A14 record { -// boolean|int \#content; -// }; - -// function testUnionTypes1() { -// // // bug #3 -// A11|error a11 = xmldata:parseAsType(x1); -// test:assertEquals(a11, {"#content": "42"}); - -// A12|error a12 = xmldata:parseAsType(x1); -// test:assertEquals(a12, {"#content":42}); - -// A13|error a13 = xmldata:parseAsType(x1); -// test:assertEquals(a13, {"#content":"42"}); - -// A14|error a14 = xmldata:parseAsType(x1); -// test:assertEquals(a14, {"#content": 42}); -// } - -// xml x2 = xml `Sample Text`; - -// type A21 record { -// int[]|string \#content; -// int|boolean|string a1; -// }; - -// type A22 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {int \#content; int a1;}; - -// type A23 record{int \#content;}|record {string \#content; int|decimal a1;}; - -// // type A24 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|float|string|int...;|}; - -// type A25 record{int \#content;}|record {string \#content; int|decimal a1; int|decimal a2;}; - -// type A26 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|boolean?|string?...;|}; - -// function testUnionTypes2() { -// A21|error a21 = xmldata:parseAsType(x2); -// test:assertEquals(a21, {"#content":"Sample Text","a1":2024}); - -// A22|error a22 = xmldata:parseAsType(x2); -// test:assertTrue(a22 is xmldata:Error); -// test:assertEquals(( a22).message(), "source value cannot convert into 'wso2/xml_data_dev:0:A22'"); - -// // // bug #4 -// // A23|error a23 = xmldata:parseAsType(x2); -// // test:assertEquals(a23, {"#content":"Sample Text","a1":2024, "a2": 3.14}); - -// // // bug #5 -// // A24|error a24 = xmldata:parseAsType(x2); -// // test:assertEquals(a24, {"a1":2024, "a2": 3.14}); - -// A25|error a25 = xmldata:parseAsType(x2); -// test:assertEquals(a25, {"#content":"Sample Text","a1":2024, "a2": 3.14}); - -// A26|error a26 = xmldata:parseAsType(x2); -// test:assertEquals(a26, {"#content":"Sample Text"}); -// } - -// xml x3 = xml `100`; - -// type A31 record { -// int[]|string B; -// }; - -// type A31P2 record { -// @xmldata:Name { -// value: "B" -// } -// string|int[] b; -// }; - -// type A32 record { -// @xmldata:Name { -// value: "B" -// } -// boolean|record{int \#content;}|int[] b; -// }; - -// type A33 record{string|int[] b1;}|record {|int|string B;|}; - -// type A34 record { -// record{int \#content; int b1;}|record{int \#content;}[]|record{int \#content;} B; -// }; - -// type A35 record {| -// record{|boolean|string...;|}...; -// |}; - -// function testUnionTypes3() { -// A31|error a31 = xmldata:parseAsType(x3); -// test:assertEquals(a31, {"B":[100]}); - -// A31P2|error a31p2 = xmldata:parseAsType(x3); -// test:assertEquals(a31p2, {"b":"100"}); - -// A32|error a32 = xmldata:parseAsType(x3); -// test:assertEquals(a32, {"b":{"#content":100}}); - -// A33|error a33 = xmldata:parseAsType(x3); -// test:assertEquals(a33, {"B":100}); - -// A34|error a34 = xmldata:parseAsType(x3); -// test:assertEquals(a34, {"B":[{"#content":100}]}); - -// A35|error a35 = xmldata:parseAsType(x3); -// test:assertEquals(a35, {"B":{"#content":"100"}}); -// } - -// xml x4 = xml `Nested Content`; - -// type A41 record {| -// int|record{|string \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; -// |}; - -// type A41P2 record {| -// int|record{|boolean \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; -// |}; - -// type A42 record {| -// int|record{|int...;|}|record{string \#content; int[]|int b1;}|record{} B; -// |}; - -// type A43P2 record {|int[]|record{|string \#content;|} B;|}; -// type A43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|A43P2; - -// function testUnionTypes4() { -// // // bug #2 -// // A41|error a41 = xmldata:parseAsType(x4); -// // test:assertEquals(a41, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); - -// A41P2|error a41p2 = xmldata:parseAsType(x4); -// test:assertEquals(a41p2, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); - -// A42|error a42 = xmldata:parseAsType(x4); -// test:assertEquals(a42, {"B":{"#content":"Nested Content","b1":99}}); - -// A43|error a43 = xmldata:parseAsType(x4); -// test:assertEquals(a43, {"B":{"#content":"Nested Content"}}); -// } - -// xml x5 = xml `123456`; - -// type Ref record {|int...;|}; -// type RefArr Ref[]; - -// type A51 record {RefArr|int[] B;}; -// type A52 record {int[]|RefArr B;}; -// type A53 record {Ref|int[] B;}; -// type A54 record {|Ref|int[]...;|}; -// type A55 record {|Ref[]|int[]...;|}; -// type A56 record {|(Ref|int)[]...;|}; -// type A57 record {|(Ref|int)[] B;|}; -// type A58 record {|(int|Ref)[]...;|}; - -// function testUnionTypes5() { -// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 -// // A51|error a51 = xmldata:parseAsType(x5); -// // test:assertEquals(a51, {"B":[{"#content":123},{"#content":456}]}); - -// A52|error a52 = xmldata:parseAsType(x5); -// test:assertEquals(a52, {"B":[123,456]}); - -// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 -// // A53|error a53 = xmldata:parseAsType(x5); -// // test:assertEquals(a53, {); - -// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 -// // A54|error a54 = xmldata:parseAsType(x5); -// // test:assertEquals(a54, {}); - -// // // bug #6 -// // A55|error a55 = xmldata:parseAsType(x5); -// // test:assertEquals(a55, {"B":[123,456]}); - -// A56|error a56 = xmldata:parseAsType(x5); -// test:assertEquals(a56, {"B":[{"#content":123},{"#content":456}]}); - -// A57|error a57 = xmldata:parseAsType(x5); -// test:assertEquals(a57, {"B":[{"#content":123},{"#content":456}]}); - -// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 -// // A58|error a58 = xmldata:parseAsType(x5); -// // test:assertEquals(a58, {"B":[{"#content":123},{"#content":456}]}); -// } - -// xml x6 = xml `ToyotaYamaha`; - -// type A61 record {string C; record {|string \#content;|}[]|string B;}; -// type A62 record {record {|boolean|record{(record{}|int[])[]|string \#content;}|string \#content;|}|string B; string C;}; -// type A63 record {|record {|string \#content;|}[]|record {|string \#content;|}...;|}; -// type A64 record {|record {|boolean|record{}|record{}[]|string \#content;|}[]|string B;|}; - -// function testUnionTypes6() { -// A61|error a61 = xmldata:parseAsType(x6); -// test:assertEquals(a61, {"C":"Yamaha","B":[{"#content":"Toyota"}]}); - -// A62|error a62 = xmldata:parseAsType(x6); -// test:assertEquals(a62, {"B":"Toyota","C":"Yamaha"}); - -// A63|error a63 = xmldata:parseAsType(x6); -// test:assertEquals(a63, {"B":[{"#content":"Toyota"}],"C":[{"#content":"Yamaha"}]}); - -// A64|error a64 = xmldata:parseAsType(x6); -// test:assertEquals(a64, {"B":[{"#content":"Toyota"}]}); -// } - -// xml x7 = xml `BrickWaterAir`; - -// type A71 record {record {|string...;|}[]|string[] B;}; -// type A72 record {string[]|record {|string...;|}[] B;}; -// type A73 record {record {|string \@content;|}|string[] B;}; -// type A74 record {|record {|string...;|}|string[]...;|}; -// type A75 record {|record {|string...;|}[]|string[]...;|}; -// type A76 record {|(record {|string...;|}|string)[]...;|}; -// type A77 record {|(record {|string...;|}|string)[] B;|}; -// type A78 record {|(string|record {|string...;|})[]...;|}; - -// function testUnionTypes7() { -// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 -// // A71|error a71 = xmldata:parseAsType(x7); -// // test:assertEquals(a71, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); - -// A72|error a72 = xmldata:parseAsType(x7); -// test:assertEquals(a72, {"B":["Brick","Water"],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); - -// A73|error a73 = xmldata:parseAsType(x7); -// test:assertTrue(a73 is xmldata:Error); -// test:assertEquals((a73).message(), "unsupported input type"); - -// // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 -// // A74|error a74 = xmldata:parseAsType(x7); -// // test:assertEquals(a74, {"B":{"#content":"Water"},"C":{"#content":"Air"}); - -// // // bug #6 -// // A75|error a75 = xmldata:parseAsType(x7); -// // test:assertEquals(a75, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); - -// // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 -// // A76|error a76 = xmldata:parseAsType(x7); -// // test:assertEquals(a76, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); - -// // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 -// // A77|error a77 = xmldata:parseAsType(x7); -// // test:assertEquals(a77, {"B":[{"#content":"Brick"},{"#content":"Water"}]}); - -// // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 -// // A78|error a78 = xmldata:parseAsType(x7); -// // test:assertEquals(a78, {"B":{"#content":"Water"},"C":{"#content":"Air"}}); -// } - -// xml x8 = xml ` -// -// First -// -// -// Second -// Third -// -// -// Fourth -// Fifth -// -// `; - -// type A81P2 record{string \#content;}[]; -// type A81P1 record{string \#content;}; -// type A81 record {record{|(A81P1|A81P2)[] C?;|}[] B;}; -// type A81Part2 record {record{(A81P1|A81P2)[] C?;}[] B;}; -// type A82P2 record{string \#content;}[][]; -// type A82P1 record{string \#content;}[]; -// type A82 record {record{|A82P1|A82P2 C?;|}[] B;}; -// type A82Part2 record {record{A82P1|A82P2 C?;}[] B;}; -// type A83P2 record{string \#content;}[]; -// type A83P1 record{string \#content;}; -// type A83 record {|record{|(A83P1|A83P2)[] C?;|}...;|}; -// type A84P2 record{string \#content;}[]; -// type A84P1 record{string \#content;}; -// type A84 record {|record{|(A84P1|A84P2)[] C?;|}[]...;|}; -// type A85 record{|record{}...;|}|record{|record{}[]...;|}; -// type A86 record{|record{}[]...;|}|record{|record{}...;|}; - -// function testUnionTypes8() { -// A81|error a81 = xmldata:parseAsType(x8); -// test:assertEquals(a81, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - -// A81Part2|error a81p2 = xmldata:parseAsType(x8); -// test:assertEquals(a81p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, -// {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); - -// A82|error a82 = xmldata:parseAsType(x8); -// test:assertEquals(a82, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - -// A82Part2|error a82p2 = xmldata:parseAsType(x8); -// test:assertEquals(a82p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, -// {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); - -// A83|error a83 = xmldata:parseAsType(x8); -// test:assertEquals(a83, {B: {}}); - -// A84|error a84 = xmldata:parseAsType(x8); -// test:assertEquals(a84, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - -// A85|error a85 = xmldata:parseAsType(x8); -// test:assertEquals(a85, {"B":{"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}}); - -// A86|error a86 = xmldata:parseAsType(x8); -// test:assertEquals(a86, {"B":[{"C":{"c1":"inner1","c2":"value","#content":"First"}},{"C":[{"c1":"inner2","c2":"value","#content":"Second"}, -// {"c1":"inner3","c2":"value","#content":"Third"}]},{"D":{"d1":"inner4","d2":"value","#content":"Fourth"}, -// "E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); -// } - -// xml x9 = xml ` -// -// 100 -// 200 -// 300 -// -// -// 400 -// 500 -// 600 -// -// `; - -// type A91P1 record{string[]|record{string \#content;}[] C;}; -// type A91 record {A91P1[] B;}; -// type A92P1 record{(string|record{string \#content;})[] C;}; -// type A92 record {A92P1[] B;}; -// type A93P1 record{record{string \#content;}[]|string[] C;}; -// type A93 record {A93P1[] B;}; -// type A94P1 record{|(record{string \#content;}|string)[]...;|}; -// type A94 record {A94P1[] B;}; - -// function testUnionTypes9() { -// A91|error a91 = xmldata:parseAsType(x9); -// test:assertEquals(a91, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); - -// A92|error a92 = xmldata:parseAsType(x9); -// test:assertEquals(a92, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); - -// A93|error a93 = xmldata:parseAsType(x9); -// test:assertEquals(a93, {"B":[{"C":[{"#content":"100"}, -// {"#content":"200"},{"#content":"300"}]}, -// {"C":[{"#content":"400"},{"#content":"500"}, -// {"#content":"600"}]}]}); - -// A94|error a94 = xmldata:parseAsType(x9); -// test:assertEquals(a94, {"B":[{"C":[{"#content":"100"}, -// {"#content":"200"},{"#content":"300"}]}, -// {"C":[{"#content":"400"},{"#content":"500"}, -// {"#content":"600"}]}]}); -// } - -// xml x10 = xml ` -// -// Deep Value1 -// Deep Value2 -// -// -// Deep Value3 -// Deep Value4 -// -// `; - -// type A101P1 record{string[]|record{string \#content;}[] C;}; -// type A101 record {A101P1[] B;}; -// type A102P1 record{(string|record{string \#content;})[] C;}; -// type A102 record {A102P1[] B;}; -// type A103P1 record{record{string \#content;}[]|string[] C;}; -// type A103 record {A103P1[] B;}; -// type A104P1 record{(record{string \#content;}|string)[] C;}; -// type A104 record {A104P1[] B;}; - -// function testUnionTypes10() { -// A101|error a101 = xmldata:parseAsType(x10); -// test:assertEquals(a101, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); - -// A102|error a102 = xmldata:parseAsType(x10); -// test:assertEquals(a102, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); - -// A103|error a103 = xmldata:parseAsType(x10); -// test:assertEquals(a103, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, -// {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); - -// A104|error a104 = xmldata:parseAsType(x10); -// test:assertEquals(a104, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, -// {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); -// } - -// xml x11 = xml ` -// -// Deep Value1 -// Deep Value2 -// -// -// Deep Value3 -// Deep Value2 -// -// `; - -// @xmldata:Namespace { -// prefix: "ns1", -// uri: "http://example.com/ns1" -// } -// type A111 record { -// string a1; -// (B111|B112)[] B; -// }; - -// @xmldata:Namespace { -// prefix: "ns1", -// uri: "http://example.com/ns1" -// } -// type A112 record {| -// string a1; -// (B111|B112)[]...; -// |}; - -// @xmldata:Namespace { -// prefix: "ns1", -// uri: "http://example.com/ns1" -// } -// type B111 record { -// @xmldata:Namespace { -// prefix: "ns1", -// uri: "http://example.com/ns1" -// } -// string b1; -// (C111|C112)[] C; -// }; - -// @xmldata:Namespace { -// prefix: "ns2", -// uri: "http://example.com/ns2" -// } -// type B112 record { -// @xmldata:Namespace { -// prefix: "ns1", -// uri: "http://example.com/ns1" -// } -// string b1; -// (C111|C112)[] C; -// }; - -// @xmldata:Namespace { -// prefix: "ns1", -// uri: "http://example.com/ns1" -// } -// type C111 record { -// @xmldata:Namespace { -// prefix: "ns1", -// uri: "http://example.com/ns1" -// } -// string c1; -// string \#content; -// }; - -// @xmldata:Namespace { -// prefix: "ns1", -// uri: "http://example.com/ns1" -// } -// type C112 record { -// @xmldata:Namespace { -// prefix: "ns1", -// uri: "http://example.com/ns1" -// } -// string c1; -// string \#content; -// }; - -// function testUnionTypes11() { -// A111|error a111 = xmldata:parseAsType(x11); -// test:assertEquals(a111, {"a1":"outer","B":[{"b1":"middle","C":[{"c1":"inner","#content":"Deep Value1"}, -// {"c1":"inner","#content":"Deep Value2"}]}, -// {"b1":"middle","C":[{"c1":"inner","#content":"Deep Value3"}, -// {"c1":"inner","#content":"Deep Value2"}]}]}); - -// A112|error a112 = xmldata:parseAsType(x11); -// test:assertEquals(a112, {"a1":"outer","B":[{"b1":"middle","C":[{"c1":"inner","#content":"Deep Value1"}, -// {"c1":"inner","#content":"Deep Value2"}]}, -// {"b1":"middle","C":[{"c1":"inner","#content":"Deep Value3"}, -// {"c1":"inner","#content":"Deep Value2"}]}]}); -// } - -// xml x12 = xml ` -// -// Deep Value1 -// Deep Value2 -// -// -// Deep Value3 -// Deep Value4 -// -// `; - -// @xmldata:Namespace { -// prefix: "ns1", -// uri: "http://example.com/ns1" -// } -// type A121 record { -// string a1; -// (B121|B122)[] B; -// }; - -// type A122 record {| -// string a1; -// (B121|B122)[]...; -// |}; - -// @xmldata:Namespace { -// prefix: "ns2", -// uri: "http://example.com/ns2" -// } -// type B121 record { -// string b1; -// C121[] C; -// }; - -// @xmldata:Namespace { -// prefix: "ns2", -// uri: "http://example.com/ns2" -// } -// type B122 record { -// string b1; -// C121[] C; -// }; - -// @xmldata:Namespace { -// prefix: "ns3", -// uri: "http://example.com/ns3" -// } -// type C121 record { -// string c1; -// string \#content; -// }; - -// function testUnionTypes12() { -// A121|error a121 = xmldata:parseAsType(x12); -// test:assertEquals(a121, {"a1":"outer","B":[{"b1":"middle", "C":[{"c1":"inner","#content":"Deep Value1"}, -// {"c1":"inner","#content":"Deep Value2"}]},{"b1":"middle", -// "C":[{"c1":"inner","#content":"Deep Value3"},{"c1":"inner","#content":"Deep Value4"}]}]}); -// A122|error a122 = xmldata:parseAsType(x12); -// test:assertEquals(a122, {"a1":"outer","B":[{"b1":"middle", "C":[{"c1":"inner","#content":"Deep Value1"}, -// {"c1":"inner","#content":"Deep Value2"}]},{"b1":"middle", -// "C":[{"c1":"inner","#content":"Deep Value3"},{"c1":"inner","#content":"Deep Value4"}]}]}); -// } - -// public function main() { -// testUnionTypes1(); -// testUnionTypes2(); -// testUnionTypes3(); -// testUnionTypes4(); -// testUnionTypes5(); -// testUnionTypes6(); -// testUnionTypes7(); -// testUnionTypes8(); -// testUnionTypes9(); -// testUnionTypes10(); -// testUnionTypes11(); -// testUnionTypes12(); -// } From cb3292ecb00f77710ba9a94040d18186c9cd5bb4 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Tue, 27 Aug 2024 13:37:49 +0530 Subject: [PATCH 08/16] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 81e9251..7dd6cb5 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -55,26 +55,6 @@ modules = [ {org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"} ] -[[package]] -org = "ballerina" -name = "lang.__internal" -version = "0.0.0" -scope = "testOnly" -dependencies = [ - {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.object"} -] - -[[package]] -org = "ballerina" -name = "lang.array" -version = "0.0.0" -scope = "testOnly" -dependencies = [ - {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.__internal"} -] - [[package]] org = "ballerina" name = "lang.error" @@ -84,12 +64,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] -[[package]] -org = "ballerina" -name = "lang.object" -version = "0.0.0" -scope = "testOnly" - [[package]] org = "ballerina" name = "lang.value" @@ -106,7 +80,6 @@ version = "0.0.0" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.array"}, {org = "ballerina", name = "lang.error"} ] modules = [ From bb05e1734bd73cd2727b094687ecedd0858dac61 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Tue, 27 Aug 2024 14:11:12 +0530 Subject: [PATCH 09/16] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 7dd6cb5..81e9251 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -55,6 +55,26 @@ modules = [ {org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"} ] +[[package]] +org = "ballerina" +name = "lang.__internal" +version = "0.0.0" +scope = "testOnly" +dependencies = [ + {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.object"} +] + +[[package]] +org = "ballerina" +name = "lang.array" +version = "0.0.0" +scope = "testOnly" +dependencies = [ + {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.__internal"} +] + [[package]] org = "ballerina" name = "lang.error" @@ -64,6 +84,12 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"} ] +[[package]] +org = "ballerina" +name = "lang.object" +version = "0.0.0" +scope = "testOnly" + [[package]] org = "ballerina" name = "lang.value" @@ -80,6 +106,7 @@ version = "0.0.0" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.array"}, {org = "ballerina", name = "lang.error"} ] modules = [ From ec41a1a3202b427debb044d0b6dd80ed0fa6ac37 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Tue, 27 Aug 2024 14:51:58 +0530 Subject: [PATCH 10/16] Refactor compiler plugin tests --- ballerina/tests/parse_string_union_test.bal | 367 +++++++++--------- ballerina/tests/parse_type_union_test.bal | 179 +++++---- .../xmldata/compiler/CompilerPluginTest.java | 70 +--- .../sample_package_11/Ballerina.toml | 4 - .../sample_package_11/main.bal | 8 - .../sample_package_12/Ballerina.toml | 4 - .../sample_package_12/file_1.bal | 6 - .../sample_package_12/file_2.bal | 6 - .../sample_package_12/file_3.bal | 6 - .../sample_package_12/types.bal | 1 - .../compiler/XmldataRecordFieldValidator.java | 32 -- .../lib/data/xmldata/xml/XmlTraversal.java | 6 +- 12 files changed, 294 insertions(+), 395 deletions(-) delete mode 100644 compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_11/Ballerina.toml delete mode 100644 compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_11/main.bal delete mode 100644 compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/Ballerina.toml delete mode 100644 compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_1.bal delete mode 100644 compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_2.bal delete mode 100644 compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_3.bal delete mode 100644 compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/types.bal diff --git a/ballerina/tests/parse_string_union_test.bal b/ballerina/tests/parse_string_union_test.bal index 91c1323..734dc44 100644 --- a/ballerina/tests/parse_string_union_test.bal +++ b/ballerina/tests/parse_string_union_test.bal @@ -1,279 +1,278 @@ -import ballerina/data.xmldata; import ballerina/test; -string x1 = "42"; +string s1 = "42"; -type A11 record { +type S11 record { int[]|string \#content; }; -type A12 record {int[] \#content;}|record {int \#content;}; +type S12 record {int[] \#content;}|record {int \#content;}; -type A13 record {| +type S13 record {| int[]|int...; |}; -type A14 record { +type S14 record { boolean|int \#content; }; @test:Config function testParseStringUnionTypes1() { - A11|error a11 = xmldata:parseString(x1); + S11|error a11 = parseString(s1); test:assertEquals(a11, {"#content": "42"}); - A12|error a12 = xmldata:parseString(x1); + S12|error a12 = parseString(s1); test:assertEquals(a12, {"#content":42}); // // bug #9 - // A13|error a13 = xmldata:parseString(x1); + // S13|error a13 = parseString(s1); // test:assertEquals(a13, {"#content":42}); - A14|error a14 = xmldata:parseString(x1); + S14|error a14 = parseString(s1); test:assertEquals(a14, {"#content": 42}); } -string x2 = string `Sample Text`; +string s2 = string `Sample Text`; -type A21 record { +type S21 record { int[]|string \#content; int|boolean|string a1; }; -type A22 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {int \#content; int a1;}; +type S22 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {int \#content; int a1;}; -type A23 record{int \#content;}|record {string \#content; int|decimal a1;}; +type S23 record{int \#content;}|record {string \#content; int|decimal a1;}; -// type A24 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|float|string|int...;|}; +// type S24 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|float|string|int...;|}; -type A25 record{int \#content;}|record {string \#content; int|decimal a1; int|decimal a2;}; +type S25 record{int \#content;}|record {string \#content; int|decimal a1; int|decimal a2;}; -type A26 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|boolean?|string?...;|}; +type S26 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; int a2;}|record {|boolean?|string?...;|}; @test:Config function testParseStringUnionTypes2() { - A21|error a21 = xmldata:parseString(x2); + S21|error a21 = parseString(s2); test:assertEquals(a21, {"#content":"Sample Text","a1":2024}); - A22|error a22 = xmldata:parseString(x2); - test:assertTrue(a22 is xmldata:Error); - test:assertEquals(( a22).message(), "source value cannot convert into 'wso2/xml_data_dev:0:A22'"); + S22|error a22 = parseString(s2); + test:assertTrue(a22 is Error); + test:assertEquals(( a22).message(), "source value cannot convert into 'ballerina/data.xmldata:1:S22'"); // // bug #4 - // A23|error a23 = xmldata:parseString(x2); + // S23|error a23 = parseString(s2); // test:assertEquals(a23, {"#content":"Sample Text","a1":2024, "a2": 3.14}); // // bug #5 - // A24|error a24 = xmldata:parseString(x2); + // S24|error a24 = parseString(s2); // test:assertEquals(a24, {"a1":2024, "a2": 3.14}); - A25|error a25 = xmldata:parseString(x2); + S25|error a25 = parseString(s2); test:assertEquals(a25, {"#content":"Sample Text","a1":2024, "a2": 3.14}); - A26|error a26 = xmldata:parseString(x2); + S26|error a26 = parseString(s2); test:assertEquals(a26, {"#content":"Sample Text"}); } -string x3 = string `100`; +string s3 = string `100`; -type A31 record { +type S31 record { int[]|string B; }; -type A31P2 record { - @xmldata:Name { +type S31P2 record { + @Name { value: "B" } string|int[] b; }; -type A32 record { - @xmldata:Name { +type S32 record { + @Name { value: "B" } boolean|record{int \#content;}|int[] b; }; -type A33 record{string|int[] b1;}|record {|int|string B;|}; +type S33 record{string|int[] b1;}|record {|int|string B;|}; -type A34 record { +type S34 record { record{int \#content; int b1;}|record{int \#content;}[]|record{int \#content;} B; }; -type A35 record {| +type S35 record {| record{|string...;|}...; |}; @test:Config function testParseStringUnionTypes3() { // custom bug - // A31|error a31 = xmldata:parseString(x3); + // S31|error a31 = parseString(s3); // test:assertEquals(a31, {"B":"100"}); - A31P2|error a31p2 = xmldata:parseString(x3); + S31P2|error a31p2 = parseString(s3); test:assertEquals(a31p2, {"b":"100"}); - A32|error a32 = xmldata:parseString(x3); + S32|error a32 = parseString(s3); test:assertEquals(a32, {"b":{"#content":100}}); - A33|error a33 = xmldata:parseString(x3); + S33|error a33 = parseString(s3); test:assertEquals(a33, {"B":100}); - A34|error a34 = xmldata:parseString(x3); + S34|error a34 = parseString(s3); test:assertEquals(a34, {"B":[{"#content":100}]}); // custom bug - // A35|error a35 = xmldata:parseString(x3); + // S35|error a35 = parseString(s3); // test:assertEquals(a35, {"B":{"#content":"100"}}); } -string x4 = string `Nested Content`; +string s4 = string `Nested Content`; -type A41 record {| +type S41 record {| int|record{|string \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; |}; -type A41P2 record {| +type S41P2 record {| int|record{|boolean \#content; int[]|int b1; record{}|boolean b2;|}|record{|string \#content; int[]|int b1; record{}|string b2;|}|record{} B; |}; -type A42 record {| +type S42 record {| int|record{|int...;|}|record{string \#content; int[]|int b1;}|record{} B; |}; -type A43P2 record {|int[]|record{|string \#content;|} B;|}; -type A43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|A43P2; +type S43P2 record {|int[]|record{|string \#content;|} B;|}; +type S43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|S43P2; @test:Config function testParseStringUnionTypes4() { // // bug #2 - // A41|error a41 = xmldata:parseString(x4); + // S41|error a41 = parseString(s4); // test:assertEquals(a41, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); - A41P2|error a41p2 = xmldata:parseString(x4); + S41P2|error a41p2 = parseString(s4); test:assertEquals(a41p2, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); - A42|error a42 = xmldata:parseString(x4); + S42|error a42 = parseString(s4); test:assertEquals(a42, {"B":{"#content":"Nested Content","b1":99}}); - A43|error a43 = xmldata:parseString(x4); + S43|error a43 = parseString(s4); test:assertEquals(a43, {"B":{"#content":"Nested Content"}}); } -string x5 = string `123456`; +string s5 = string `123456`; type Ref record {|int...;|}; type RefArr Ref[]; -type A51 record {RefArr|int[] B;}; -type A52 record {int[]|RefArr B;}; -type A53 record {Ref|int[] B;}; -type A54 record {|Ref|int[]...;|}; -type A55 record {|Ref[]|int[]...;|}; -type A56 record {|(Ref|int)[]...;|}; -type A57 record {|(Ref|int)[] B;|}; -type A58 record {|(int|Ref)[]...;|}; +type S51 record {RefArr|int[] B;}; +type S52 record {int[]|RefArr B;}; +type S53 record {Ref|int[] B;}; +type S54 record {|Ref|int[]...;|}; +type S55 record {|Ref[]|int[]...;|}; +type S56 record {|(Ref|int)[]...;|}; +type S57 record {|(Ref|int)[] B;|}; +type S58 record {|(int|Ref)[]...;|}; @test:Config function testParseStringUnionTypes5() { // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A51|error a51 = xmldata:parseString(x5); + // S51|error a51 = parseString(s5); // test:assertEquals(a51, {"B":[{"#content":123},{"#content":456}]}); - A52|error a52 = xmldata:parseString(x5); + S52|error a52 = parseString(s5); test:assertEquals(a52, {"B":[123,456]}); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A53|error a53 = xmldata:parseString(x5); + // S53|error a53 = parseString(s5); // test:assertEquals(a53, {); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A54|error a54 = xmldata:parseString(x5); + // S54|error a54 = parseString(s5); // test:assertEquals(a54, {}); // // bug #6 - // A55|error a55 = xmldata:parseString(x5); + // S55|error a55 = parseString(s5); // test:assertEquals(a55, {"B":[123,456]}); - A56|error a56 = xmldata:parseString(x5); + S56|error a56 = parseString(s5); test:assertEquals(a56, {"B":[{"#content":123},{"#content":456}]}); - A57|error a57 = xmldata:parseString(x5); + S57|error a57 = parseString(s5); test:assertEquals(a57, {"B":[{"#content":123},{"#content":456}]}); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A58|error a58 = xmldata:parseString(x5); + // S58|error a58 = parseString(s5); // test:assertEquals(a58, {"B":[{"#content":123},{"#content":456}]}); } -string x6 = string `ToyotaYamaha`; +string s6 = string `ToyotaYamaha`; -type A61 record {string C; record {|string \#content;|}[]|string B;}; -type A62 record {record {|boolean|record{(record{}|int[])[]|string \#content;}|string \#content;|}|string B; string C;}; -type A63 record {|record {|string \#content;|}[]|record {|string \#content;|}...;|}; -type A64 record {|record {|boolean|record{}|record{}[]|string \#content;|}[]|string B;|}; +type S61 record {string C; record {|string \#content;|}[]|string B;}; +type S62 record {record {|boolean|record{(record{}|int[])[]|string \#content;}|string \#content;|}|string B; string C;}; +type S63 record {|record {|string \#content;|}[]|record {|string \#content;|}...;|}; +type S64 record {|record {|boolean|record{}|record{}[]|string \#content;|}[]|string B;|}; @test:Config function testParseStringUnionTypes6() { - A61|error a61 = xmldata:parseString(x6); + S61|error a61 = parseString(s6); test:assertEquals(a61, {"C":"Yamaha","B":[{"#content":"Toyota"}]}); - A62|error a62 = xmldata:parseString(x6); + S62|error a62 = parseString(s6); test:assertEquals(a62, {"B":"Toyota","C":"Yamaha"}); - A63|error a63 = xmldata:parseString(x6); + S63|error a63 = parseString(s6); test:assertEquals(a63, {"B":[{"#content":"Toyota"}],"C":[{"#content":"Yamaha"}]}); - A64|error a64 = xmldata:parseString(x6); + S64|error a64 = parseString(s6); test:assertEquals(a64, {"B":[{"#content":"Toyota"}]}); } -string x7 = string `BrickWaterAir`; +string s7 = string `BrickWaterAir`; -type A71 record {record {|string...;|}[]|string[] B;}; -type A72 record {string[]|record {|string...;|}[] B;}; -type A73 record {record {|string \@content;|}|string[] B;}; -type A74 record {|record {|string...;|}|string[]...;|}; -type A75 record {|record {|string...;|}[]|string[]...;|}; -type A76 record {|(record {|string...;|}|string)[]...;|}; -type A77 record {|(record {|string...;|}|string)[] B;|}; -type A78 record {|(string|record {|string...;|})[]...;|}; +type S71 record {record {|string...;|}[]|string[] B;}; +type S72 record {string[]|record {|string...;|}[] B;}; +type S73 record {record {|string \@content;|}|string[] B;}; +type S74 record {|record {|string...;|}|string[]...;|}; +type S75 record {|record {|string...;|}[]|string[]...;|}; +type S76 record {|(record {|string...;|}|string)[]...;|}; +type S77 record {|(record {|string...;|}|string)[] B;|}; +type S78 record {|(string|record {|string...;|})[]...;|}; @test:Config function testParseStringUnionTypes7() { // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A71|error a71 = xmldata:parseString(x7); + // S71|error a71 = parseString(s7); // test:assertEquals(a71, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); - A72|error a72 = xmldata:parseString(x7); + S72|error a72 = parseString(s7); test:assertEquals(a72, {"B":["Brick","Water"],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); - A73|error a73 = xmldata:parseString(x7); - test:assertTrue(a73 is xmldata:Error); + S73|error a73 = parseString(s7); + test:assertTrue(a73 is Error); test:assertEquals((a73).message(), "unsupported input type"); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A74|error a74 = xmldata:parseString(x7); + // S74|error a74 = parseString(s7); // test:assertEquals(a74, {"B":{"#content":"Water"},"C":{"#content":"Air"}); // // bug #6 - // A75|error a75 = xmldata:parseString(x7); + // S75|error a75 = parseString(s7); // test:assertEquals(a75, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A76|error a76 = xmldata:parseString(x7); + // S76|error a76 = parseString(s7); // test:assertEquals(a76, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A77|error a77 = xmldata:parseString(x7); + // S77|error a77 = parseString(s7); // test:assertEquals(a77, {"B":[{"#content":"Brick"},{"#content":"Water"}]}); // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A78|error a78 = xmldata:parseString(x7); + // S78|error a78 = parseString(s7); // test:assertEquals(a78, {"B":{"#content":"Water"},"C":{"#content":"Air"}}); } -string x8 = string ` +string s8 = string ` First @@ -287,55 +286,55 @@ string x8 = string ` `; -type A81P2 record{string \#content;}[]; -type A81P1 record{string \#content;}; -type A81 record {record{|(A81P1|A81P2)[] C?;|}[] B;}; -type A81Part2 record {record{(A81P1|A81P2)[] C?;}[] B;}; -type A82P2 record{string \#content;}[][]; -type A82P1 record{string \#content;}[]; -type A82 record {record{|A82P1|A82P2 C?;|}[] B;}; -type A82Part2 record {record{A82P1|A82P2 C?;}[] B;}; -type A83P2 record{string \#content;}[]; -type A83P1 record{string \#content;}; -type A83 record {|record{|(A83P1|A83P2)[] C?;|}...;|}; -type A84P2 record{string \#content;}[]; -type A84P1 record{string \#content;}; -type A84 record {|record{|(A84P1|A84P2)[] C?;|}[]...;|}; -type A85 record{|record{}...;|}|record{|record{}[]...;|}; -type A86 record{|record{}[]...;|}|record{|record{}...;|}; +type S81P2 record{string \#content;}[]; +type S81P1 record{string \#content;}; +type S81 record {record{|(S81P1|S81P2)[] C?;|}[] B;}; +type S81Part2 record {record{(S81P1|S81P2)[] C?;}[] B;}; +type S82P2 record{string \#content;}[][]; +type S82P1 record{string \#content;}[]; +type S82 record {record{|S82P1|S82P2 C?;|}[] B;}; +type S82Part2 record {record{S82P1|S82P2 C?;}[] B;}; +type S83P2 record{string \#content;}[]; +type S83P1 record{string \#content;}; +type S83 record {|record{|(S83P1|S83P2)[] C?;|}...;|}; +type S84P2 record{string \#content;}[]; +type S84P1 record{string \#content;}; +type S84 record {|record{|(S84P1|S84P2)[] C?;|}[]...;|}; +type S85 record{|record{}...;|}|record{|record{}[]...;|}; +type S86 record{|record{}[]...;|}|record{|record{}...;|}; @test:Config function testParseStringUnionTypes8() { - A81|error a81 = xmldata:parseString(x8); + S81|error a81 = parseString(s8); test:assertEquals(a81, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - A81Part2|error a81p2 = xmldata:parseString(x8); + S81Part2|error a81p2 = parseString(s8); test:assertEquals(a81p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); - A82|error a82 = xmldata:parseString(x8); + S82|error a82 = parseString(s8); test:assertEquals(a82, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - A82Part2|error a82p2 = xmldata:parseString(x8); + S82Part2|error a82p2 = parseString(s8); test:assertEquals(a82p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); - A83|error a83 = xmldata:parseString(x8); + S83|error a83 = parseString(s8); test:assertEquals(a83, {B: {}}); - A84|error a84 = xmldata:parseString(x8); + S84|error a84 = parseString(s8); test:assertEquals(a84, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - A85|error a85 = xmldata:parseString(x8); + S85|error a85 = parseString(s8); test:assertEquals(a85, {"B":{"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}}); - A86|error a86 = xmldata:parseString(x8); + S86|error a86 = parseString(s8); test:assertEquals(a86, {"B":[{"C":{"c1":"inner1","c2":"value","#content":"First"}},{"C":[{"c1":"inner2","c2":"value","#content":"Second"}, {"c1":"inner3","c2":"value","#content":"Third"}]},{"D":{"d1":"inner4","d2":"value","#content":"Fourth"}, "E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); } -string x9 = string ` +string s9 = string ` 100 200 @@ -348,37 +347,37 @@ string x9 = string ` `; -type A91P1 record{string[]|record{string \#content;}[] C;}; -type A91 record {A91P1[] B;}; -type A92P1 record{(string|record{string \#content;})[] C;}; -type A92 record {A92P1[] B;}; -type A93P1 record{record{string \#content;}[]|string[] C;}; -type A93 record {A93P1[] B;}; -type A94P1 record{|(record{string \#content;}|string)[]...;|}; -type A94 record {A94P1[] B;}; +type S91P1 record{string[]|record{string \#content;}[] C;}; +type S91 record {S91P1[] B;}; +type S92P1 record{(string|record{string \#content;})[] C;}; +type S92 record {S92P1[] B;}; +type S93P1 record{record{string \#content;}[]|string[] C;}; +type S93 record {S93P1[] B;}; +type S94P1 record{|(record{string \#content;}|string)[]...;|}; +type S94 record {S94P1[] B;}; @test:Config function testParseStringUnionTypes9() { - A91|error a91 = xmldata:parseString(x9); + S91|error a91 = parseString(s9); test:assertEquals(a91, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); - A92|error a92 = xmldata:parseString(x9); + S92|error a92 = parseString(s9); test:assertEquals(a92, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); - A93|error a93 = xmldata:parseString(x9); + S93|error a93 = parseString(s9); test:assertEquals(a93, {"B":[{"C":[{"#content":"100"}, {"#content":"200"},{"#content":"300"}]}, {"C":[{"#content":"400"},{"#content":"500"}, {"#content":"600"}]}]}); - A94|error a94 = xmldata:parseString(x9); + S94|error a94 = parseString(s9); test:assertEquals(a94, {"B":[{"C":[{"#content":"100"}, {"#content":"200"},{"#content":"300"}]}, {"C":[{"#content":"400"},{"#content":"500"}, {"#content":"600"}]}]}); } -string x10 = string ` +string s10 = string ` Deep Value1 Deep Value2 @@ -389,33 +388,33 @@ string x10 = string ` `; -type A101P1 record{string[]|record{string \#content;}[] C;}; -type A101 record {A101P1[] B;}; -type A102P1 record{(string|record{string \#content;})[] C;}; -type A102 record {A102P1[] B;}; -type A103P1 record{record{string \#content;}[]|string[] C;}; -type A103 record {A103P1[] B;}; -type A104P1 record{(record{string \#content;}|string)[] C;}; -type A104 record {A104P1[] B;}; +type S101P1 record{string[]|record{string \#content;}[] C;}; +type S101 record {S101P1[] B;}; +type S102P1 record{(string|record{string \#content;})[] C;}; +type S102 record {S102P1[] B;}; +type S103P1 record{record{string \#content;}[]|string[] C;}; +type S103 record {S103P1[] B;}; +type S104P1 record{(record{string \#content;}|string)[] C;}; +type S104 record {S104P1[] B;}; @test:Config function testParseStringUnionTypes10() { - A101|error a101 = xmldata:parseString(x10); + S101|error a101 = parseString(s10); test:assertEquals(a101, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); - A102|error a102 = xmldata:parseString(x10); + S102|error a102 = parseString(s10); test:assertEquals(a102, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); - A103|error a103 = xmldata:parseString(x10); + S103|error a103 = parseString(s10); test:assertEquals(a103, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); - A104|error a104 = xmldata:parseString(x10); + S104|error a104 = parseString(s10); test:assertEquals(a104, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); } -string x11 = string ` +string s11 = string ` Deep Value1 Deep Value2 @@ -426,56 +425,56 @@ string x11 = string ` +string s12 = string ` Deep Value1 Deep Value2 @@ -522,54 +521,54 @@ string x12 = string `42`; @@ -20,16 +19,16 @@ type A14 record { @test:Config function testTraverseUnionTypes1() { // // bug #3 - A11|error a11 = xmldata:parseAsType(x1); + A11|error a11 = parseAsType(x1); test:assertEquals(a11, {"#content": "42"}); - A12|error a12 = xmldata:parseAsType(x1); + A12|error a12 = parseAsType(x1); test:assertEquals(a12, {"#content":42}); - A13|error a13 = xmldata:parseAsType(x1); + A13|error a13 = parseAsType(x1); test:assertEquals(a13, {"#content":"42"}); - A14|error a14 = xmldata:parseAsType(x1); + A14|error a14 = parseAsType(x1); test:assertEquals(a14, {"#content": 42}); } @@ -52,25 +51,25 @@ type A26 record {int[] \#content;}|record {|int[]...;|}|record {int \#content; i @test:Config function testTraverseUnionTypes2() { - A21|error a21 = xmldata:parseAsType(x2); + A21|error a21 = parseAsType(x2); test:assertEquals(a21, {"#content":"Sample Text","a1":2024}); - A22|error a22 = xmldata:parseAsType(x2); - test:assertTrue(a22 is xmldata:Error); - test:assertEquals(( a22).message(), "source value cannot convert into 'wso2/xml_data_dev.traverseTest:0:A22'"); + A22|error a22 = parseAsType(x2); + test:assertTrue(a22 is Error); + test:assertEquals(( a22).message(), "source value cannot convert into 'ballerina/data.xmldata:1:A22'"); // // bug #4 - // A23|error a23 = xmldata:parseAsType(x2); + // A23|error a23 = parseAsType(x2); // test:assertEquals(a23, {"#content":"Sample Text","a1":2024, "a2": 3.14}); // // bug #5 - // A24|error a24 = xmldata:parseAsType(x2); + // A24|error a24 = parseAsType(x2); // test:assertEquals(a24, {"a1":2024, "a2": 3.14}); - A25|error a25 = xmldata:parseAsType(x2); + A25|error a25 = parseAsType(x2); test:assertEquals(a25, {"#content":"Sample Text","a1":2024, "a2": 3.14}); - A26|error a26 = xmldata:parseAsType(x2); + A26|error a26 = parseAsType(x2); test:assertEquals(a26, {"#content":"Sample Text"}); } @@ -81,14 +80,14 @@ type A31 record { }; type A31P2 record { - @xmldata:Name { + @Name { value: "B" } string|int[] b; }; type A32 record { - @xmldata:Name { + @Name { value: "B" } boolean|record{int \#content;}|int[] b; @@ -106,22 +105,22 @@ type A35 record {| @test:Config function testTraverseUnionTypes3() { - A31|error a31 = xmldata:parseAsType(x3); + A31|error a31 = parseAsType(x3); test:assertEquals(a31, {"B":[100]}); - A31P2|error a31p2 = xmldata:parseAsType(x3); + A31P2|error a31p2 = parseAsType(x3); test:assertEquals(a31p2, {"b":"100"}); - A32|error a32 = xmldata:parseAsType(x3); + A32|error a32 = parseAsType(x3); test:assertEquals(a32, {"b":{"#content":100}}); - A33|error a33 = xmldata:parseAsType(x3); + A33|error a33 = parseAsType(x3); test:assertEquals(a33, {"B":100}); - A34|error a34 = xmldata:parseAsType(x3); + A34|error a34 = parseAsType(x3); test:assertEquals(a34, {"B":[{"#content":100}]}); - A35|error a35 = xmldata:parseAsType(x3); + A35|error a35 = parseAsType(x3); test:assertEquals(a35, {"B":{"#content":"100"}}); } @@ -145,62 +144,62 @@ type A43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|A43P2 @test:Config function testTraverseUnionTypes4() { // // bug #2 - // A41|error a41 = xmldata:parseAsType(x4); + // A41|error a41 = parseAsType(x4); // test:assertEquals(a41, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); - A41P2|error a41p2 = xmldata:parseAsType(x4); + A41P2|error a41p2 = parseAsType(x4); test:assertEquals(a41p2, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); - A42|error a42 = xmldata:parseAsType(x4); + A42|error a42 = parseAsType(x4); test:assertEquals(a42, {"B":{"#content":"Nested Content","b1":99}}); - A43|error a43 = xmldata:parseAsType(x4); + A43|error a43 = parseAsType(x4); test:assertEquals(a43, {"B":{"#content":"Nested Content"}}); } xml x5 = xml `123456`; -type Ref record {|int...;|}; -type RefArr Ref[]; +type Ref2 record {|int...;|}; +type RefArr2 Ref2[]; -type A51 record {RefArr|int[] B;}; -type A52 record {int[]|RefArr B;}; -type A53 record {Ref|int[] B;}; -type A54 record {|Ref|int[]...;|}; -type A55 record {|Ref[]|int[]...;|}; -type A56 record {|(Ref|int)[]...;|}; -type A57 record {|(Ref|int)[] B;|}; -type A58 record {|(int|Ref)[]...;|}; +type A51 record {RefArr2|int[] B;}; +type A52 record {int[]|RefArr2 B;}; +type A53 record {Ref2|int[] B;}; +type A54 record {|Ref2|int[]...;|}; +type A55 record {|Ref2[]|int[]...;|}; +type A56 record {|(Ref2|int)[]...;|}; +type A57 record {|(Ref2|int)[] B;|}; +type A58 record {|(int|Ref2)[]...;|}; @test:Config function testTraverseUnionTypes5() { // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A51|error a51 = xmldata:parseAsType(x5); + // A51|error a51 = parseAsType(x5); // test:assertEquals(a51, {"B":[{"#content":123},{"#content":456}]}); - A52|error a52 = xmldata:parseAsType(x5); + A52|error a52 = parseAsType(x5); test:assertEquals(a52, {"B":[123,456]}); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A53|error a53 = xmldata:parseAsType(x5); + // A53|error a53 = parseAsType(x5); // test:assertEquals(a53, {); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A54|error a54 = xmldata:parseAsType(x5); + // A54|error a54 = parseAsType(x5); // test:assertEquals(a54, {}); // // bug #6 - // A55|error a55 = xmldata:parseAsType(x5); + // A55|error a55 = parseAsType(x5); // test:assertEquals(a55, {"B":[123,456]}); - A56|error a56 = xmldata:parseAsType(x5); + A56|error a56 = parseAsType(x5); test:assertEquals(a56, {"B":[{"#content":123},{"#content":456}]}); - A57|error a57 = xmldata:parseAsType(x5); + A57|error a57 = parseAsType(x5); test:assertEquals(a57, {"B":[{"#content":123},{"#content":456}]}); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A58|error a58 = xmldata:parseAsType(x5); + // A58|error a58 = parseAsType(x5); // test:assertEquals(a58, {"B":[{"#content":123},{"#content":456}]}); } @@ -213,16 +212,16 @@ type A64 record {|record {|boolean|record{}|record{}[]|string \#content;|}[]|str @test:Config function testTraverseUnionTypes6() { - A61|error a61 = xmldata:parseAsType(x6); + A61|error a61 = parseAsType(x6); test:assertEquals(a61, {"C":"Yamaha","B":[{"#content":"Toyota"}]}); - A62|error a62 = xmldata:parseAsType(x6); + A62|error a62 = parseAsType(x6); test:assertEquals(a62, {"B":"Toyota","C":"Yamaha"}); - A63|error a63 = xmldata:parseAsType(x6); + A63|error a63 = parseAsType(x6); test:assertEquals(a63, {"B":[{"#content":"Toyota"}],"C":[{"#content":"Yamaha"}]}); - A64|error a64 = xmldata:parseAsType(x6); + A64|error a64 = parseAsType(x6); test:assertEquals(a64, {"B":[{"#content":"Toyota"}]}); } @@ -240,34 +239,34 @@ type A78 record {|(string|record {|string...;|})[]...;|}; @test:Config function testTraverseUnionTypes7() { // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A71|error a71 = xmldata:parseAsType(x7); + // A71|error a71 = parseAsType(x7); // test:assertEquals(a71, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); - A72|error a72 = xmldata:parseAsType(x7); + A72|error a72 = parseAsType(x7); test:assertEquals(a72, {"B":["Brick","Water"],"C":{"c1":"gas","c2":"transparent","#content":"Air"}}); - A73|error a73 = xmldata:parseAsType(x7); - test:assertTrue(a73 is xmldata:Error); + A73|error a73 = parseAsType(x7); + test:assertTrue(a73 is Error); test:assertEquals((a73).message(), "unsupported input type"); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A74|error a74 = xmldata:parseAsType(x7); + // A74|error a74 = parseAsType(x7); // test:assertEquals(a74, {"B":{"#content":"Water"},"C":{"#content":"Air"}); // // bug #6 - // A75|error a75 = xmldata:parseAsType(x7); + // A75|error a75 = parseAsType(x7); // test:assertEquals(a75, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A76|error a76 = xmldata:parseAsType(x7); + // A76|error a76 = parseAsType(x7); // test:assertEquals(a76, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A77|error a77 = xmldata:parseAsType(x7); + // A77|error a77 = parseAsType(x7); // test:assertEquals(a77, {"B":[{"#content":"Brick"},{"#content":"Water"}]}); // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 - // A78|error a78 = xmldata:parseAsType(x7); + // A78|error a78 = parseAsType(x7); // test:assertEquals(a78, {"B":{"#content":"Water"},"C":{"#content":"Air"}}); } @@ -304,30 +303,30 @@ type A86 record{|record{}[]...;|}|record{|record{}...;|}; @test:Config function testTraverseUnionTypes8() { - A81|error a81 = xmldata:parseAsType(x8); + A81|error a81 = parseAsType(x8); test:assertEquals(a81, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - A81Part2|error a81p2 = xmldata:parseAsType(x8); + A81Part2|error a81p2 = parseAsType(x8); test:assertEquals(a81p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); - A82|error a82 = xmldata:parseAsType(x8); + A82|error a82 = parseAsType(x8); test:assertEquals(a82, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - A82Part2|error a82p2 = xmldata:parseAsType(x8); + A82Part2|error a82p2 = parseAsType(x8); test:assertEquals(a82p2, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]}, {"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); - A83|error a83 = xmldata:parseAsType(x8); + A83|error a83 = parseAsType(x8); test:assertEquals(a83, {B: {}}); - A84|error a84 = xmldata:parseAsType(x8); + A84|error a84 = parseAsType(x8); test:assertEquals(a84, {"B":[{"C":[{"#content":"First"}]},{"C":[{"#content":"Second"},{"#content":"Third"}]},{}]}); - A85|error a85 = xmldata:parseAsType(x8); + A85|error a85 = parseAsType(x8); test:assertEquals(a85, {"B":{"D":{"d1":"inner4","d2":"value","#content":"Fourth"},"E":{"e1":"inner5","e2":"value","#content":"Fifth"}}}); - A86|error a86 = xmldata:parseAsType(x8); + A86|error a86 = parseAsType(x8); test:assertEquals(a86, {"B":[{"C":{"c1":"inner1","c2":"value","#content":"First"}},{"C":[{"c1":"inner2","c2":"value","#content":"Second"}, {"c1":"inner3","c2":"value","#content":"Third"}]},{"D":{"d1":"inner4","d2":"value","#content":"Fourth"}, "E":{"e1":"inner5","e2":"value","#content":"Fifth"}}]}); @@ -357,19 +356,19 @@ type A94 record {A94P1[] B;}; @test:Config function testTraverseUnionTypes9() { - A91|error a91 = xmldata:parseAsType(x9); + A91|error a91 = parseAsType(x9); test:assertEquals(a91, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); - A92|error a92 = xmldata:parseAsType(x9); + A92|error a92 = parseAsType(x9); test:assertEquals(a92, {"B":[{"C":["100","200","300"]},{"C":["400","500","600"]}]}); - A93|error a93 = xmldata:parseAsType(x9); + A93|error a93 = parseAsType(x9); test:assertEquals(a93, {"B":[{"C":[{"#content":"100"}, {"#content":"200"},{"#content":"300"}]}, {"C":[{"#content":"400"},{"#content":"500"}, {"#content":"600"}]}]}); - A94|error a94 = xmldata:parseAsType(x9); + A94|error a94 = parseAsType(x9); test:assertEquals(a94, {"B":[{"C":[{"#content":"100"}, {"#content":"200"},{"#content":"300"}]}, {"C":[{"#content":"400"},{"#content":"500"}, @@ -398,17 +397,17 @@ type A104 record {A104P1[] B;}; @test:Config function testTraverseUnionTypes10() { - A101|error a101 = xmldata:parseAsType(x10); + A101|error a101 = parseAsType(x10); test:assertEquals(a101, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); - A102|error a102 = xmldata:parseAsType(x10); + A102|error a102 = parseAsType(x10); test:assertEquals(a102, {"B":[{"C":["Deep Value1","Deep Value2"]},{"C":["Deep Value3","Deep Value4"]}]}); - A103|error a103 = xmldata:parseAsType(x10); + A103|error a103 = parseAsType(x10); test:assertEquals(a103, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); - A104|error a104 = xmldata:parseAsType(x10); + A104|error a104 = parseAsType(x10); test:assertEquals(a104, {"B":[{"C":[{"#content":"Deep Value1"},{"#content":"Deep Value2"}]}, {"C":[{"#content":"Deep Value3"},{"#content":"Deep Value4"}]}]}); } @@ -424,7 +423,7 @@ xml x11 = xml ` errorDiagnosticsList = diagnosticResult.diagnostics().stream() -// .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) -// .collect(Collectors.toList()); -// Assert.assertEquals(errorDiagnosticsList.size(), 6); -// Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), -// "invalid type: expected a record type"); -// Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), -// "invalid field: duplicate field found"); -// Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), -// "invalid field: duplicate field found"); -// Assert.assertEquals(errorDiagnosticsList.get(3).diagnosticInfo().messageFormat(), -// "invalid type: expected a record type"); -// Assert.assertEquals(errorDiagnosticsList.get(4).diagnosticInfo().messageFormat(), -// "invalid field: duplicate field found"); -// Assert.assertEquals(errorDiagnosticsList.get(5).diagnosticInfo().messageFormat(), -// "invalid field: duplicate field found"); -// } + @Test + public void testUnionTypeNegative() { + DiagnosticResult diagnosticResult = + CompilerPluginTestUtils.loadPackage("sample_package_9").getCompilation().diagnosticResult(); + List errorDiagnosticsList = diagnosticResult.diagnostics().stream() + .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) + .collect(Collectors.toList()); + Assert.assertEquals(errorDiagnosticsList.size(), 6); + Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), + "invalid type: expected a record type"); + Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), + "invalid field: duplicate field found"); + Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), + "invalid field: duplicate field found"); + Assert.assertEquals(errorDiagnosticsList.get(3).diagnosticInfo().messageFormat(), + "invalid type: expected a record type"); + Assert.assertEquals(errorDiagnosticsList.get(4).diagnosticInfo().messageFormat(), + "invalid field: duplicate field found"); + Assert.assertEquals(errorDiagnosticsList.get(5).diagnosticInfo().messageFormat(), + "invalid field: duplicate field found"); + } @Test public void testCompilerPluginWithAProjectWithSubModule() { @@ -125,32 +125,4 @@ public void testCompilerPluginWithAProjectWithSubModule() { Assert.assertEquals(warningDiagnosticsList.get(0).diagnosticInfo().messageFormat(), "invalid annotation attachment: child record does not allow name annotation"); } - -// @Test -// public void testComplexUnionTypeCaseWhenUserDefinedModulePrefix() { -// DiagnosticResult diagnosticResult = -// CompilerPluginTestUtils.loadPackage("sample_package_11").getCompilation().diagnosticResult(); -// List errorDiagnosticsList = diagnosticResult.diagnostics().stream() -// .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) -// .collect(Collectors.toList()); -// Assert.assertEquals(errorDiagnosticsList.size(), 1); -// Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), -// "invalid type: expected a record type"); -// } - -// @Test -// public void testComplexUnionTypeCaseWhenUserDefinedModulePrefix2() { -// DiagnosticResult diagnosticResult = -// CompilerPluginTestUtils.loadPackage("sample_package_12").getCompilation().diagnosticResult(); -// List errorDiagnosticsList = diagnosticResult.diagnostics().stream() -// .filter(r -> r.diagnosticInfo().severity().equals(DiagnosticSeverity.ERROR)) -// .collect(Collectors.toList()); -// Assert.assertEquals(errorDiagnosticsList.size(), 3); -// Assert.assertEquals(errorDiagnosticsList.get(0).diagnosticInfo().messageFormat(), -// "invalid type: expected a record type"); -// Assert.assertEquals(errorDiagnosticsList.get(1).diagnosticInfo().messageFormat(), -// "invalid type: expected a record type"); -// Assert.assertEquals(errorDiagnosticsList.get(2).diagnosticInfo().messageFormat(), -// "invalid type: expected a record type"); -// } } diff --git a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_11/Ballerina.toml b/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_11/Ballerina.toml deleted file mode 100644 index 0d3fd35..0000000 --- a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_11/Ballerina.toml +++ /dev/null @@ -1,4 +0,0 @@ -[package] -org = "xmldata_test" -name = "sample_11" -version = "0.1.0" diff --git a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_11/main.bal b/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_11/main.bal deleted file mode 100644 index 48ff508..0000000 --- a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_11/main.bal +++ /dev/null @@ -1,8 +0,0 @@ -import ballerina/data.xmldata as xd; - -type UnionType record {|int a;|}|record {|string b;|}; - -public function main() returns error? { - string str = string `{"a": 1, "b": "str"}`; - UnionType _ = check xd:parseString(str); -} diff --git a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/Ballerina.toml b/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/Ballerina.toml deleted file mode 100644 index 93df2bb..0000000 --- a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/Ballerina.toml +++ /dev/null @@ -1,4 +0,0 @@ -[package] -org = "xmldata_test" -name = "sample_12" -version = "0.1.0" diff --git a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_1.bal b/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_1.bal deleted file mode 100644 index 4cced6f..0000000 --- a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_1.bal +++ /dev/null @@ -1,6 +0,0 @@ -import ballerina/data.xmldata as xd; - -public function testFunc() returns error? { - string str = string `{"a": 1, "b": "str"}`; - UnionType _ = check xd:parseString(str); -} diff --git a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_2.bal b/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_2.bal deleted file mode 100644 index 710f15b..0000000 --- a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_2.bal +++ /dev/null @@ -1,6 +0,0 @@ -import ballerina/data.xmldata as xd2; - -public function testFunc2() returns error? { - string str = string `{"a": 1, "b": "str"}`; - UnionType _ = check xd2:parseString(str); -} diff --git a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_3.bal b/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_3.bal deleted file mode 100644 index ab8ee06..0000000 --- a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/file_3.bal +++ /dev/null @@ -1,6 +0,0 @@ -import ballerina/data.xmldata; - -public function testFunc3() returns error? { - string str = string `{"a": 1, "b": "str"}`; - UnionType _ = check xmldata:parseString(str); -} diff --git a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/types.bal b/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/types.bal deleted file mode 100644 index 4383f4d..0000000 --- a/compiler-plugin-test/src/test/resources/ballerina_sources/sample_package_12/types.bal +++ /dev/null @@ -1 +0,0 @@ -type UnionType record {|int a;|}|record {|string b;|}; diff --git a/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java b/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java index 07150eb..874d2a3 100644 --- a/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java +++ b/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java @@ -325,7 +325,6 @@ private void processRecordFieldsType(RecordTypeSymbol recordTypeSymbol, SyntaxNo private void validateRecordFieldType(TypeSymbol typeSymbol, Optional location, SyntaxNodeAnalysisContext ctx) { switch (typeSymbol.typeKind()) { -// case UNION -> validateUnionType((UnionTypeSymbol) typeSymbol, location, ctx); case NIL, TUPLE -> reportDiagnosticInfo(ctx, location, XmldataDiagnosticCodes.UNSUPPORTED_TYPE); case ARRAY -> validateRecordFieldType(((ArrayTypeSymbol) typeSymbol).memberTypeDescriptor(), location, ctx); case TYPE_REFERENCE -> @@ -333,37 +332,6 @@ private void validateRecordFieldType(TypeSymbol typeSymbol, Optional l } } -// private void validateUnionType(UnionTypeSymbol unionTypeSymbol, Optional location, -// SyntaxNodeAnalysisContext ctx) { -// int nonPrimitiveMemberCount = 0; -// boolean isNilPresent = false; -// List memberTypeSymbols = unionTypeSymbol.memberTypeDescriptors(); -// for (TypeSymbol memberTypeSymbol : memberTypeSymbols) { -// if (isPrimitiveType(memberTypeSymbol)) { -// continue; -// } -// -// if (memberTypeSymbol.typeKind() == TypeDescKind.NIL) { -// isNilPresent = true; -// } -// nonPrimitiveMemberCount++; -// } -// -// if (nonPrimitiveMemberCount > 1 || (memberTypeSymbols.size() > 1 && isNilPresent)) { -// reportDiagnosticInfo(ctx, location, XmldataDiagnosticCodes.UNSUPPORTED_UNION_TYPE); -// } -// } - - private boolean isPrimitiveType(TypeSymbol typeSymbol) { - TypeDescKind kind = typeSymbol.typeKind(); - if (kind == TypeDescKind.TYPE_REFERENCE) { - kind = ((TypeReferenceTypeSymbol) typeSymbol).typeDescriptor().typeKind(); - } - - return kind == TypeDescKind.INT || kind == TypeDescKind.FLOAT || kind == TypeDescKind.DECIMAL - || kind == TypeDescKind.STRING || kind == TypeDescKind.BOOLEAN || kind == TypeDescKind.BYTE; - } - private boolean isAnnotFromXmldata(AnnotationSymbol annotationSymbol) { Optional moduleSymbol = annotationSymbol.getModule(); if (moduleSymbol.isEmpty()) { diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java index 30b7b88..ea4c554 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java @@ -455,11 +455,7 @@ private BMap updateNextMappingValue(Type type, String fieldName Object temp = currentMapValue.get(StringUtils.fromString(fieldName)); if (temp instanceof BArray tempArray) { ArrayType arrayType = (ArrayType) fieldType; - Integer peek = analyzerData.arrayIndexes.peek().get(fieldName); - int currentIndex = tempArray.size(); - if (peek != null) { - currentIndex = peek; - } + int currentIndex = analyzerData.arrayIndexes.peek().get(fieldName); if (arrayType.getState() == ArrayType.ArrayState.OPEN || currentIndex < arrayType.getSize()) { tempArray.add(currentIndex, nextValue); From 8ce8ef99642d695c7095f6df1ebf5b2e8892bb2f Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Tue, 27 Aug 2024 17:56:29 +0530 Subject: [PATCH 11/16] Remove unused functions in compiler plugin module --- ballerina/tests/parse_string_union_test.bal | 2 +- ballerina/tests/parse_type_union_test.bal | 2 +- .../compiler/XmldataRecordFieldValidator.java | 10 ++++---- .../lib/data/xmldata/utils/DataUtils.java | 23 +------------------ .../data/xmldata/xml/QualifiedNameMap.java | 9 -------- .../lib/data/xmldata/xml/XmlParser.java | 3 +-- 6 files changed, 10 insertions(+), 39 deletions(-) diff --git a/ballerina/tests/parse_string_union_test.bal b/ballerina/tests/parse_string_union_test.bal index 734dc44..3821af9 100644 --- a/ballerina/tests/parse_string_union_test.bal +++ b/ballerina/tests/parse_string_union_test.bal @@ -229,7 +229,7 @@ function testParseStringUnionTypes6() { string s7 = string `BrickWaterAir`; -type S71 record {record {|string...;|}[]|string[] B;}; +type S71 record {record{[int, int] a;}|record {|string...;|}[]|string[] B;}; type S72 record {string[]|record {|string...;|}[] B;}; type S73 record {record {|string \@content;|}|string[] B;}; type S74 record {|record {|string...;|}|string[]...;|}; diff --git a/ballerina/tests/parse_type_union_test.bal b/ballerina/tests/parse_type_union_test.bal index 2eec7bc..f49ce1a 100644 --- a/ballerina/tests/parse_type_union_test.bal +++ b/ballerina/tests/parse_type_union_test.bal @@ -227,7 +227,7 @@ function testTraverseUnionTypes6() { xml x7 = xml `BrickWaterAir`; -type A71 record {record {|string...;|}[]|string[] B;}; +type A71 record {record{[int, int] a;}|record {|string...;|}[]|string[] B;}; type A72 record {string[]|record {|string...;|}[] B;}; type A73 record {record {|string \@content;|}|string[] B;}; type A74 record {|record {|string...;|}|string[]...;|}; diff --git a/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java b/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java index 874d2a3..d0da173 100644 --- a/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java +++ b/compiler-plugin/src/main/java/io/ballerina/lib/data/xmldata/compiler/XmldataRecordFieldValidator.java @@ -181,10 +181,11 @@ private void validateExpectedType(TypeSymbol typeSymbol, Optional loca case UNION -> { int recordCount = 0; for (TypeSymbol memberTSymbol : ((UnionTypeSymbol) typeSymbol).memberTypeDescriptors()) { - if (getReferredTypeSymbol(memberTSymbol).typeKind() == TypeDescKind.ERROR) { + TypeDescKind typeDescKind = getReferredTypeSymbol(memberTSymbol).typeKind(); + if (typeDescKind == TypeDescKind.ERROR) { continue; } - if (getReferredTypeSymbol(memberTSymbol).typeKind() == TypeDescKind.RECORD) { + if (typeDescKind == TypeDescKind.RECORD) { validateExpectedType(memberTSymbol, location, ctx); recordCount++; } @@ -213,11 +214,12 @@ private boolean isNotValidExpectedType(TypeSymbol typeSymbol) { } case UNION -> { for (TypeSymbol memberTSymbol : ((UnionTypeSymbol) typeSymbol).memberTypeDescriptors()) { - if (getReferredTypeSymbol(memberTSymbol).typeKind() == TypeDescKind.ERROR) { + TypeSymbol referredTypeSymbol = getReferredTypeSymbol(memberTSymbol); + if (referredTypeSymbol.typeKind() == TypeDescKind.ERROR) { continue; } - if (!(getReferredTypeSymbol(memberTSymbol).typeKind() == TypeDescKind.RECORD)) { + if (!(referredTypeSymbol.typeKind() == TypeDescKind.RECORD)) { return true; } } diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java index d8af0f3..4ac3fb0 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java @@ -528,17 +528,6 @@ private static void processRecordField(Type fieldType, BMap ann } processTypeReferenceType(fieldType, annotations, recordValue, key, value); } - case TypeTags.UNION_TAG -> { - for (Type memberType : ((UnionType) fieldType).getMemberTypes()) { - try { - processRecordField(memberType, annotations, recordValue, entry, key, value); - return; - } catch (Exception ex) { - //ignore - } - throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldType); - } - } default -> addPrimitiveValue(addFieldNamespaceAnnotation(key, key, annotations, recordValue), annotations, recordValue, value); } @@ -703,17 +692,7 @@ private static void processArray(Type elementType, BMap annotat processSubRecordAnnotation(annotations, annotationRecord); } BArray arrayValue = (BArray) entry.getValue(); - if (elementType.getTag() == TypeTags.UNION_TAG) { - for (Type memberType : ((UnionType) elementType).getMemberTypes()) { - try { - processArray(memberType, annotations, record, entry); - return; - } catch (Exception ex) { - //ignore - } - throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, elementType); - } - } else if (elementType.getTag() == TypeTags.RECORD_TYPE_TAG) { + if (elementType.getTag() == TypeTags.RECORD_TYPE_TAG) { List> records = new ArrayList<>(); for (int i = 0; i < arrayValue.getLength(); i++) { BMap subRecord = addFields(((BMap) arrayValue.get(i)), diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/QualifiedNameMap.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/QualifiedNameMap.java index 8aa0f64..f32cc75 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/QualifiedNameMap.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/QualifiedNameMap.java @@ -17,19 +17,10 @@ public QualifiedNameMap(Map fields) { this.stringToQNameMap = getStringToQNamesMap(fields.keySet()); } - public QualifiedNameMap(Map fields, Map> stringToQNameMap) { - this.members = fields; - this.stringToQNameMap = stringToQNameMap; - } - public Map getMembers() { return members; } - public Map> getStringToQnamesMap() { - return stringToQNameMap; - } - public V remove(QualifiedName qName) { V field = members.remove(qName); if (field == null) { diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java index 388970e..113f1b8 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlParser.java @@ -198,8 +198,7 @@ private boolean parseXmlElements(int next, XmlParserData xmlParserData) throws X return true; } case END_DOCUMENT -> buildDocument(xmlParserData); - case PROCESSING_INSTRUCTION, COMMENT, DTD -> { - } // Ignore + case PROCESSING_INSTRUCTION, COMMENT, DTD -> { } // Ignore default -> { assert false; } From e26e66de436b7916d5e6ff1d7781352677bca4d4 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Wed, 28 Aug 2024 07:14:13 +0530 Subject: [PATCH 12/16] Add negative tests for union types --- ballerina/tests/parse_string_union_test.bal | 19 ++- ballerina/tests/parse_type_union_test.bal | 14 +- ballerina/tests/union_error_tests.bal | 149 ++++++++++++++++++ .../lib/data/xmldata/xml/XmlTraversal.java | 8 +- 4 files changed, 169 insertions(+), 21 deletions(-) create mode 100644 ballerina/tests/union_error_tests.bal diff --git a/ballerina/tests/parse_string_union_test.bal b/ballerina/tests/parse_string_union_test.bal index 3821af9..bade260 100644 --- a/ballerina/tests/parse_string_union_test.bal +++ b/ballerina/tests/parse_string_union_test.bal @@ -58,11 +58,11 @@ function testParseStringUnionTypes2() { test:assertTrue(a22 is Error); test:assertEquals(( a22).message(), "source value cannot convert into 'ballerina/data.xmldata:1:S22'"); - // // bug #4 + // https://github.com/ballerina-platform/ballerina-library/issues/6925 // S23|error a23 = parseString(s2); // test:assertEquals(a23, {"#content":"Sample Text","a1":2024, "a2": 3.14}); - // // bug #5 + // https://github.com/ballerina-platform/ballerina-library/issues/6925 // S24|error a24 = parseString(s2); // test:assertEquals(a24, {"a1":2024, "a2": 3.14}); @@ -105,9 +105,8 @@ type S35 record {| @test:Config function testParseStringUnionTypes3() { -// custom bug - // S31|error a31 = parseString(s3); - // test:assertEquals(a31, {"B":"100"}); + S31|error a31 = parseString(s3); + test:assertEquals(a31, {"B":"100"}); S31P2|error a31p2 = parseString(s3); test:assertEquals(a31p2, {"b":"100"}); @@ -121,7 +120,7 @@ function testParseStringUnionTypes3() { S34|error a34 = parseString(s3); test:assertEquals(a34, {"B":[{"#content":100}]}); -// custom bug + // https://github.com/ballerina-platform/ballerina-library/issues/6929 // S35|error a35 = parseString(s3); // test:assertEquals(a35, {"B":{"#content":"100"}}); } @@ -145,7 +144,7 @@ type S43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|S43P2 @test:Config function testParseStringUnionTypes4() { - // // bug #2 + // https://github.com/ballerina-platform/ballerina-library/issues?q=is%3Aopen+is%3Aissue+author%3ASasinduDilshara+label%3Amodule%2Fdata.xmldata // S41|error a41 = parseString(s4); // test:assertEquals(a41, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); @@ -190,7 +189,7 @@ function testParseStringUnionTypes5() { // S54|error a54 = parseString(s5); // test:assertEquals(a54, {}); - // // bug #6 + // https://github.com/ballerina-platform/ballerina-library/issues?q=is%3Aopen+is%3Aissue+author%3ASasinduDilshara+label%3Amodule%2Fdata.xmldata // S55|error a55 = parseString(s5); // test:assertEquals(a55, {"B":[123,456]}); @@ -249,13 +248,13 @@ function testParseStringUnionTypes7() { S73|error a73 = parseString(s7); test:assertTrue(a73 is Error); - test:assertEquals((a73).message(), "unsupported input type"); + test:assertEquals((a73).message(), "field 'B' cannot convert into the type '(data.xmldata:record {| string @content; |}|string[])'"); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 // S74|error a74 = parseString(s7); // test:assertEquals(a74, {"B":{"#content":"Water"},"C":{"#content":"Air"}); - // // bug #6 + // https://github.com/ballerina-platform/ballerina-library/issues?q=is%3Aopen+is%3Aissue+author%3ASasinduDilshara+label%3Amodule%2Fdata.xmldata // S75|error a75 = parseString(s7); // test:assertEquals(a75, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); diff --git a/ballerina/tests/parse_type_union_test.bal b/ballerina/tests/parse_type_union_test.bal index f49ce1a..a5ca8d2 100644 --- a/ballerina/tests/parse_type_union_test.bal +++ b/ballerina/tests/parse_type_union_test.bal @@ -58,11 +58,11 @@ function testTraverseUnionTypes2() { test:assertTrue(a22 is Error); test:assertEquals(( a22).message(), "source value cannot convert into 'ballerina/data.xmldata:1:A22'"); - // // bug #4 + // https://github.com/ballerina-platform/ballerina-library/issues/6925 // A23|error a23 = parseAsType(x2); // test:assertEquals(a23, {"#content":"Sample Text","a1":2024, "a2": 3.14}); - // // bug #5 + // https://github.com/ballerina-platform/ballerina-library/issues/6925 // A24|error a24 = parseAsType(x2); // test:assertEquals(a24, {"a1":2024, "a2": 3.14}); @@ -143,7 +143,7 @@ type A43 record{|int[]|record{|int \#content; float|decimal|int...;|} B;|}|A43P2 @test:Config function testTraverseUnionTypes4() { - // // bug #2 + // https://github.com/ballerina-platform/ballerina-library/issues/6925 // A41|error a41 = parseAsType(x4); // test:assertEquals(a41, {"B":{"#content":"Nested Content","b1":99,"b2":"45.67"}}); @@ -188,7 +188,7 @@ function testTraverseUnionTypes5() { // A54|error a54 = parseAsType(x5); // test:assertEquals(a54, {}); - // // bug #6 + // https://github.com/ballerina-platform/ballerina-library/issues?q=is%3Aopen+is%3Aissue+author%3ASasinduDilshara+label%3Amodule%2Fdata.xmldata // A55|error a55 = parseAsType(x5); // test:assertEquals(a55, {"B":[123,456]}); @@ -247,13 +247,13 @@ function testTraverseUnionTypes7() { A73|error a73 = parseAsType(x7); test:assertTrue(a73 is Error); - test:assertEquals((a73).message(), "unsupported input type"); + test:assertEquals((a73).message(), "field 'B' cannot convert into the type '(data.xmldata:record {| string @content; |}|string[])'"); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 // A74|error a74 = parseAsType(x7); // test:assertEquals(a74, {"B":{"#content":"Water"},"C":{"#content":"Air"}); - // // bug #6 + // https://github.com/ballerina-platform/ballerina-library/issues?q=is%3Aopen+is%3Aissue+author%3ASasinduDilshara+label%3Amodule%2Fdata.xmldata // A75|error a75 = parseAsType(x7); // test:assertEquals(a75, {"B":[{"#content":"Brick"},{"#content":"Water"}],"C":[{"#content":"Air"}]}); @@ -265,7 +265,7 @@ function testTraverseUnionTypes7() { // A77|error a77 = parseAsType(x7); // test:assertEquals(a77, {"B":[{"#content":"Brick"},{"#content":"Water"}]}); - // // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 + // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 // A78|error a78 = parseAsType(x7); // test:assertEquals(a78, {"B":{"#content":"Water"},"C":{"#content":"Air"}}); } diff --git a/ballerina/tests/union_error_tests.bal b/ballerina/tests/union_error_tests.bal new file mode 100644 index 0000000..acfc32f --- /dev/null +++ b/ballerina/tests/union_error_tests.bal @@ -0,0 +1,149 @@ +import ballerina/test; + +xml xe1 = xml `text`; +xml xe2 = xml `text`; +xml xe3 = xml `texttext`; +xml xe4 = xml ` + texttexttext + texttexttext + `; +xml xe5 = xml ` + + Deep Value1 + Deep Value2 + + + Deep Value3 + Deep Value2 + + `; + +type E1 record { + boolean|()|int|decimal|record {} \#content; +}; + +type E2 record { + record {boolean|()|int|decimal|record {} \#content;} B; +}; + +type E22 record { + record {boolean|()|int|decimal|record {} \#content;}|record {record {int \#content;} \#content;} B; +}; + +type E3 record { + (record {int \#content;}|record {boolean \#content;})[] B; +}; + +type E32 record { + record {int \#content;}[]|record {boolean \#content;}[] B; +}; + +type E4P1 record {boolean \#content;}; +type E4P12 record {int \#content;}|E4P1; + +type E4 record { + record{E4P12[] C;}[] B; +}; + +type E4P2 record {boolean \#content;}[]; +type E4P22 record {int \#content;}[]|E4P2; + +type E42 record { + record{E4P22 C;}[] B; +}; + +@Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type E5 record { + string a1; + (F111|F112)[] B; +}; + +@Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" +} +type F111 record { + @Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string b1; + (G111|G112)[] C; +}; + +@Namespace { + prefix: "ns2", + uri: "http://example.com/ns2" +} +type F112 record { + @Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string b1; + (G111|G112)[] C; +}; + +@Namespace { + prefix: "ns2", + uri: "http://example.com/ns1" +} +type G111 record { + @Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string c1; + string \#content; +}; + +@Namespace { + prefix: "ns2", + uri: "http://example.com/ns1" +} +type G112 record { + @Namespace { + prefix: "ns1", + uri: "http://example.com/ns1" + } + string c1; + string \#content; +}; + +@test:Config +function testErrorUnion() { + E1|error e1 = parseAsType(xe1); + test:assertTrue(e1 is error); + test:assertEquals((e1).message(), "field '#content' cannot convert into the type '(boolean|int|decimal|data.xmldata:record {| anydata...; |})?'"); + + E2|error e2 = parseAsType(xe2); + test:assertTrue(e2 is error); + test:assertEquals((e2).message(), "field '#content' cannot convert into the type '(boolean|int|decimal|data.xmldata:record {| anydata...; |})?'"); + + E22|error e22 = parseAsType(xe2); + test:assertTrue(e22 is error); + test:assertEquals((e22).message(), "field 'B' cannot convert into the type '(data.xmldata:record {| (boolean|int|decimal|record {| anydata...; |})? #content; anydata...; |}|data.xmldata:record {| record {| int #content; anydata...; |} #content; anydata...; |})'"); + + E3|error e3 = parseAsType(xe3); + test:assertTrue(e3 is error); + test:assertEquals((e3).message(), "field 'B' cannot convert into the type '(data.xmldata:record {| int #content; anydata...; |}|data.xmldata:record {| boolean #content; anydata...; |})[]'"); + + E32|error e32 = parseAsType(xe3); + test:assertTrue(e32 is error); + test:assertEquals((e32).message(), "field 'B' cannot convert into the type '(data.xmldata:record {| int #content; anydata...; |}[]|data.xmldata:record {| boolean #content; anydata...; |}[])'"); + + E4|error e4 = parseAsType(xe4); + test:assertTrue(e4 is error); + test:assertEquals((e4).message(), "field 'C' cannot convert into the type 'data.xmldata:E4P12[]'"); + + E42|error e42 = parseAsType(xe4); + test:assertTrue(e42 is error); + test:assertEquals((e42).message(), "field 'C' cannot convert into the type 'ballerina/data.xmldata:1:E4P22'"); + + E5|error e5 = parseAsType(xe5); + test:assertTrue(e5 is error); + test:assertEquals((e5).message(), "field 'B' cannot convert into the type '(data.xmldata:F111|data.xmldata:F112)[]'"); +} diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java index ea4c554..67063c1 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java @@ -196,7 +196,7 @@ private void convertText(String text, XmlAnalyzerData analyzerData) { } } if (convertedValue == null) { - throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldType); + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldName, fieldType); } } else { convertedValue = DataUtils.convertStringToExpType(StringUtils.fromString(text), fieldType); @@ -222,7 +222,7 @@ private void convertText(String text, XmlAnalyzerData analyzerData) { ((BArray) value).add(currentIndex, convertedValue); } else { if (fieldType.getTag() == TypeTags.ARRAY_TAG) { - throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldType); + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldName, fieldType); } mapValue.put(fieldName, convertedValue); } @@ -322,7 +322,7 @@ private void convertFieldTypeToUnion(BXmlItem xmlItem, Field currentField, Strin // ignore } } - throw DiagnosticLog.error(DiagnosticErrorCode.UNSUPPORTED_TYPE); + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, fieldName, currentFieldType); } private void convertToArrayType(BXmlItem xmlItem, Field field, BMap mapValue, @@ -541,7 +541,7 @@ private void checkRestTypeAndConvertForUnionTypes(BXmlItem xmlItem, String elemN // ignore } } - throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, elementType); + throw DiagnosticLog.error(DiagnosticErrorCode.FIELD_CANNOT_CAST_INTO_TYPE, elemName, elementType); } private void handleArrayValueForRestType(BXmlItem xmlItem, String elemName, Type restType, From 161b66cd2c73c0e688ecee9e0f08701f9759c793 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Wed, 28 Aug 2024 18:05:30 +0530 Subject: [PATCH 13/16] [Automated] Update the native jar versions --- ballerina/Dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 81e9251..0180731 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -37,7 +37,7 @@ modules = [ [[package]] org = "ballerina" name = "io" -version = "1.6.2" +version = "1.6.1" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}, @@ -116,7 +116,7 @@ modules = [ [[package]] org = "ballerina" name = "time" -version = "2.4.1" +version = "2.4.0" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"} From e0f2437bd4efb8b3471cba12f9b91a1cbdcba1ca Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Wed, 4 Sep 2024 11:17:35 +0530 Subject: [PATCH 14/16] Updatre code owner file and refactor errors --- .github/CODEOWNERS | 2 +- ballerina/tests/parse_string_union_test.bal | 4 ++-- ballerina/tests/parse_type_union_test.bal | 4 ++-- ballerina/tests/union_error_tests.bal | 16 +++++++------- .../lib/data/xmldata/utils/DataUtils.java | 1 - .../lib/data/xmldata/xml/XmlTraversal.java | 22 ++++++------------- native/src/main/resources/error.properties | 4 ++-- 7 files changed, 22 insertions(+), 31 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8d17e9c..d0878e0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,4 +4,4 @@ # See: https://help.github.com/articles/about-codeowners/ # These owners will be the default owners for everything in the repo. -* @hasithaa @prakanth97 @SasinduDilshara +* @hasithaa @SasinduDilshara diff --git a/ballerina/tests/parse_string_union_test.bal b/ballerina/tests/parse_string_union_test.bal index bade260..33b2041 100644 --- a/ballerina/tests/parse_string_union_test.bal +++ b/ballerina/tests/parse_string_union_test.bal @@ -56,7 +56,7 @@ function testParseStringUnionTypes2() { S22|error a22 = parseString(s2); test:assertTrue(a22 is Error); - test:assertEquals(( a22).message(), "source value cannot convert into 'ballerina/data.xmldata:1:S22'"); + test:assertEquals(( a22).message(), "source value cannot be converted into 'ballerina/data.xmldata:1:S22'"); // https://github.com/ballerina-platform/ballerina-library/issues/6925 // S23|error a23 = parseString(s2); @@ -248,7 +248,7 @@ function testParseStringUnionTypes7() { S73|error a73 = parseString(s7); test:assertTrue(a73 is Error); - test:assertEquals((a73).message(), "field 'B' cannot convert into the type '(data.xmldata:record {| string @content; |}|string[])'"); + test:assertEquals((a73).message(), "field 'B' cannot be converted into the type '(data.xmldata:record {| string @content; |}|string[])'"); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 // S74|error a74 = parseString(s7); diff --git a/ballerina/tests/parse_type_union_test.bal b/ballerina/tests/parse_type_union_test.bal index a5ca8d2..18992ee 100644 --- a/ballerina/tests/parse_type_union_test.bal +++ b/ballerina/tests/parse_type_union_test.bal @@ -56,7 +56,7 @@ function testTraverseUnionTypes2() { A22|error a22 = parseAsType(x2); test:assertTrue(a22 is Error); - test:assertEquals(( a22).message(), "source value cannot convert into 'ballerina/data.xmldata:1:A22'"); + test:assertEquals(( a22).message(), "source value cannot be converted into 'ballerina/data.xmldata:1:A22'"); // https://github.com/ballerina-platform/ballerina-library/issues/6925 // A23|error a23 = parseAsType(x2); @@ -247,7 +247,7 @@ function testTraverseUnionTypes7() { A73|error a73 = parseAsType(x7); test:assertTrue(a73 is Error); - test:assertEquals((a73).message(), "field 'B' cannot convert into the type '(data.xmldata:record {| string @content; |}|string[])'"); + test:assertEquals((a73).message(), "field 'B' cannot be converted into the type '(data.xmldata:record {| string @content; |}|string[])'"); // //bug https://github.com/ballerina-platform/ballerina-library/issues/6907 // A74|error a74 = parseAsType(x7); diff --git a/ballerina/tests/union_error_tests.bal b/ballerina/tests/union_error_tests.bal index acfc32f..ff7a5de 100644 --- a/ballerina/tests/union_error_tests.bal +++ b/ballerina/tests/union_error_tests.bal @@ -117,33 +117,33 @@ type G112 record { function testErrorUnion() { E1|error e1 = parseAsType(xe1); test:assertTrue(e1 is error); - test:assertEquals((e1).message(), "field '#content' cannot convert into the type '(boolean|int|decimal|data.xmldata:record {| anydata...; |})?'"); + test:assertEquals((e1).message(), "field '#content' cannot be converted into the type '(boolean|int|decimal|data.xmldata:record {| anydata...; |})?'"); E2|error e2 = parseAsType(xe2); test:assertTrue(e2 is error); - test:assertEquals((e2).message(), "field '#content' cannot convert into the type '(boolean|int|decimal|data.xmldata:record {| anydata...; |})?'"); + test:assertEquals((e2).message(), "field '#content' cannot be converted into the type '(boolean|int|decimal|data.xmldata:record {| anydata...; |})?'"); E22|error e22 = parseAsType(xe2); test:assertTrue(e22 is error); - test:assertEquals((e22).message(), "field 'B' cannot convert into the type '(data.xmldata:record {| (boolean|int|decimal|record {| anydata...; |})? #content; anydata...; |}|data.xmldata:record {| record {| int #content; anydata...; |} #content; anydata...; |})'"); + test:assertEquals((e22).message(), "field 'B' cannot be converted into the type '(data.xmldata:record {| (boolean|int|decimal|record {| anydata...; |})? #content; anydata...; |}|data.xmldata:record {| record {| int #content; anydata...; |} #content; anydata...; |})'"); E3|error e3 = parseAsType(xe3); test:assertTrue(e3 is error); - test:assertEquals((e3).message(), "field 'B' cannot convert into the type '(data.xmldata:record {| int #content; anydata...; |}|data.xmldata:record {| boolean #content; anydata...; |})[]'"); + test:assertEquals((e3).message(), "field 'B' cannot be converted into the type '(data.xmldata:record {| int #content; anydata...; |}|data.xmldata:record {| boolean #content; anydata...; |})[]'"); E32|error e32 = parseAsType(xe3); test:assertTrue(e32 is error); - test:assertEquals((e32).message(), "field 'B' cannot convert into the type '(data.xmldata:record {| int #content; anydata...; |}[]|data.xmldata:record {| boolean #content; anydata...; |}[])'"); + test:assertEquals((e32).message(), "field 'B' cannot be converted into the type '(data.xmldata:record {| int #content; anydata...; |}[]|data.xmldata:record {| boolean #content; anydata...; |}[])'"); E4|error e4 = parseAsType(xe4); test:assertTrue(e4 is error); - test:assertEquals((e4).message(), "field 'C' cannot convert into the type 'data.xmldata:E4P12[]'"); + test:assertEquals((e4).message(), "field 'C' cannot be converted into the type 'data.xmldata:E4P12[]'"); E42|error e42 = parseAsType(xe4); test:assertTrue(e42 is error); - test:assertEquals((e42).message(), "field 'C' cannot convert into the type 'ballerina/data.xmldata:1:E4P22'"); + test:assertEquals((e42).message(), "field 'C' cannot be converted into the type 'ballerina/data.xmldata:1:E4P22'"); E5|error e5 = parseAsType(xe5); test:assertTrue(e5 is error); - test:assertEquals((e5).message(), "field 'B' cannot convert into the type '(data.xmldata:F111|data.xmldata:F112)[]'"); + test:assertEquals((e5).message(), "field 'B' cannot be converted into the type '(data.xmldata:F111|data.xmldata:F112)[]'"); } diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java index 4ac3fb0..0a8cd06 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/utils/DataUtils.java @@ -258,7 +258,6 @@ private static Object convertStringToUnionExpType(BString value, Type expType) { try { return convertStringToExpType(value, memberType); } catch (Exception ex) { - int a = 1; // ignore } } diff --git a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java index 67063c1..0d1776f 100644 --- a/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java +++ b/native/src/main/java/io/ballerina/lib/data/xmldata/xml/XmlTraversal.java @@ -93,21 +93,20 @@ public Object traverseXml(BXml xml, XmlAnalyzerData analyzerData, Type type) { Type referredType = TypeUtils.getReferredType(type); switch (referredType.getTag()) { case TypeTags.RECORD_TYPE_TAG -> { - return traverseXmlWithRecordAsExpectedType(xml, analyzerData, referredType); + return traverseXmlWithRecordAsExpectedType(xml, analyzerData, (RecordType) referredType); } case TypeTags.MAP_TAG -> { - return traverseXmlWithMapAsExpectedType(xml, referredType, analyzerData); + return traverseXmlWithMapAsExpectedType(xml, (MapType) referredType, analyzerData); } case TypeTags.UNION_TAG -> { - return traverseXmlToUnion(xml, analyzerData, referredType); + return traverseXmlToUnion(xml, analyzerData, (UnionType) referredType); } default -> throw DiagnosticLog.error(DiagnosticErrorCode.INVALID_TYPE, Constants.RECORD_OR_MAP, type); } } private Object traverseXmlWithRecordAsExpectedType(BXml xml, - XmlAnalyzerData analyzerData, Type referredType) { - RecordType recordType = (RecordType) referredType; + XmlAnalyzerData analyzerData, RecordType recordType) { currentNode = ValueCreator.createRecordValue(recordType.getPackage(), recordType.getName()); BXml nextXml = validateRootElement(xml, recordType, analyzerData); Object resultRecordValue = traverseXml(nextXml, recordType, analyzerData); @@ -115,15 +114,13 @@ private Object traverseXmlWithRecordAsExpectedType(BXml xml, return resultRecordValue; } - private Object traverseXmlWithMapAsExpectedType(BXml xml, Type referredType, XmlAnalyzerData analyzerData) { - MapType mapType = (MapType) referredType; + private Object traverseXmlWithMapAsExpectedType(BXml xml, MapType mapType, XmlAnalyzerData analyzerData) { RecordType anonRecType = TypeCreator.createRecordType(Constants.ANON_TYPE, mapType.getPackage(), 0, new HashMap<>(), mapType.getConstrainedType(), false, 0); return traverseXml(xml, analyzerData, anonRecType); } - private Object traverseXmlToUnion(BXml xml, XmlAnalyzerData options, Type type) { - UnionType unionType = (UnionType) type; + private Object traverseXmlToUnion(BXml xml, XmlAnalyzerData options, UnionType unionType) { XmlAnalyzerData clonedAnalyzerData = XmlAnalyzerData.copy(options); for (Type memberType: unionType.getMemberTypes()) { memberType = TypeUtils.getReferredType(memberType); @@ -133,12 +130,11 @@ private Object traverseXmlToUnion(BXml xml, XmlAnalyzerData options, Type type) } return traverseXml(xml, options, memberType); } catch (Exception ex) { - int a = 1; options.resetFrom(clonedAnalyzerData); // ignore } } - throw DiagnosticLog.error(DiagnosticErrorCode.CANNOT_CONVERT_SOURCE_INTO_EXP_TYPE, type); + throw DiagnosticLog.error(DiagnosticErrorCode.CANNOT_CONVERT_SOURCE_INTO_EXP_TYPE, unionType); } private Object traverseXml(BXml xml, Type type, XmlAnalyzerData analyzerData) { @@ -190,7 +186,6 @@ private void convertText(String text, XmlAnalyzerData analyzerData) { fieldType = memberType; break; } catch (Exception ex) { - int a = 1; analyzerData.resetFrom(clonedAnalyzerData); // ignore } @@ -318,7 +313,6 @@ private void convertFieldTypeToUnion(BXmlItem xmlItem, Field currentField, Strin } catch (Exception ex) { analyzerData.resetFrom(clonedAnalyzerData); mapValue.put(StringUtils.fromString(fieldName), null); - int a = 1; // ignore } } @@ -381,7 +375,6 @@ private void convertToUnionMemberType(BXmlItem xmlItem, String fieldName, ArrayT return; } catch (Exception ex) { analyzerData.resetFrom(clonedAnalyzerData); - int a = 1; // ignore } } @@ -537,7 +530,6 @@ private void checkRestTypeAndConvertForUnionTypes(BXmlItem xmlItem, String elemN if (restType.getTag() != TypeTags.ARRAY_TAG) { mapValue.put(StringUtils.fromString(elemName), null); } - int a = 1; // ignore } } diff --git a/native/src/main/resources/error.properties b/native/src/main/resources/error.properties index 108ea74..65e56ee 100644 --- a/native/src/main/resources/error.properties +++ b/native/src/main/resources/error.properties @@ -72,7 +72,7 @@ error.undefined.field=\ undefined field ''{0}'' in record ''{1}'' error.cannot.convert.source.into.expected.type=\ - source value cannot convert into ''{0}'' + source value cannot be converted into ''{0}'' error.field.cannot.convert.into.type=\ - field ''{0}'' cannot convert into the type ''{1}'' + field ''{0}'' cannot be converted into the type ''{1}'' From a57880a5b2bdfb7dc910abc310177d8e8ef35627 Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Wed, 4 Sep 2024 11:41:44 +0530 Subject: [PATCH 15/16] update string union tests with relevent issue links --- ballerina/tests/parse_string_union_test.bal | 2 +- ballerina/tests/parse_type_union_test.bal | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ballerina/tests/parse_string_union_test.bal b/ballerina/tests/parse_string_union_test.bal index 33b2041..923ebe5 100644 --- a/ballerina/tests/parse_string_union_test.bal +++ b/ballerina/tests/parse_string_union_test.bal @@ -24,7 +24,7 @@ function testParseStringUnionTypes1() { S12|error a12 = parseString(s1); test:assertEquals(a12, {"#content":42}); - // // bug #9 + // https://github.com/ballerina-platform/ballerina-library/issues/6929 // S13|error a13 = parseString(s1); // test:assertEquals(a13, {"#content":42}); diff --git a/ballerina/tests/parse_type_union_test.bal b/ballerina/tests/parse_type_union_test.bal index 18992ee..a81b33e 100644 --- a/ballerina/tests/parse_type_union_test.bal +++ b/ballerina/tests/parse_type_union_test.bal @@ -18,7 +18,6 @@ type A14 record { @test:Config function testTraverseUnionTypes1() { - // // bug #3 A11|error a11 = parseAsType(x1); test:assertEquals(a11, {"#content": "42"}); From 76f370b273d695e5ae2bedc3deacf4a70f3d357c Mon Sep 17 00:00:00 2001 From: Sasindu Alahakoon Date: Fri, 6 Sep 2024 14:07:33 +0530 Subject: [PATCH 16/16] revert changes in dependencies.toml --- ballerina/Dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 0180731..81e9251 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -37,7 +37,7 @@ modules = [ [[package]] org = "ballerina" name = "io" -version = "1.6.1" +version = "1.6.2" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}, @@ -116,7 +116,7 @@ modules = [ [[package]] org = "ballerina" name = "time" -version = "2.4.0" +version = "2.4.1" scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"}