Skip to content

Commit

Permalink
Merge pull request #44 from SasinduDilshara/issue_6926
Browse files Browse the repository at this point in the history
Fix incorrect null value for xml attributes when the expected field type is an array
  • Loading branch information
gimantha authored Nov 29, 2024
2 parents 139af66 + 89c7642 commit 8116c64
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 2 deletions.
1 change: 1 addition & 0 deletions ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,4 @@ dependencies = [
modules = [
{org = "ballerina", packageName = "time", moduleName = "time"}
]

57 changes: 57 additions & 0 deletions ballerina/tests/fromXml_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -3635,3 +3635,60 @@ function testXmlToRecordWithInvalidExpectedTypeForText() {
test:assertTrue(rec6 is Error);
test:assertEquals((<Error>rec6).message(), "unsupported input type");
}

@test:Config {
groups: ["fromXml"]
}
function testXmlToRecordWithInvalidExpectedTypeForAttributes() {
xml value = xml `<a id="2">1</a>`;
record {int[] id;}|error rec = parseAsType(value);
test:assertTrue(rec is Error);
test:assertEquals((<error>rec).message(), "attribute 'id' cannot be converted into the array type 'int[]'");

xml value2 = xml `<a id="2">
<id id="2">1</id>
<id id="2">2</id>
<id id="2">3</id>
</a>`;

record {int[] id;}|error rec2 = parseAsType(value2);
test:assertEquals(rec2, {id:[1,2,3]});

xml value3 = xml `<a id="1"><b id="2">3</b></a>`;
record {record{int[] id;} b;}|error rec3 = parseAsType(value3);
test:assertTrue(rec3 is Error);
test:assertEquals((<error>rec3).message(), "attribute 'id' cannot be converted into the array type 'int[]'");

xml value4 = xml `<a id="2">
<id id="2">1</id>
<id id="2">2</id>
<id id="2">3</id>
</a>`;
record {record{int[] id;}[] id;}|error rec4 = parseAsType(value4);
test:assertTrue(rec4 is Error);
test:assertEquals((<error>rec4).message(), "attribute 'id' cannot be converted into the array type 'int[]'");

xml value5 = xml `<a id="2">1</a>`;
record {map<int> id;}|error rec5 = parseAsType(value5);
test:assertTrue(rec5 is Error);
test:assertEquals((<error>rec5).message(), "attribute 'id' cannot be converted into the array type 'map<int>'");

xml value6 = xml `<a id="1"><b id="2">3</b></a>`;
record {record{map<int> id;} b;}|error rec6 = parseAsType(value6);
test:assertTrue(rec6 is Error);
test:assertEquals((<error>rec6).message(), "attribute 'id' cannot be converted into the array type 'map<int>'");

xml value7 = xml `<a id="2">1</a>`;
record {string:RegExp id;}|error rec7 = parseAsType(value7);
test:assertTrue(rec7 is Error);
test:assertEquals((<error>rec7).message(), "unsupported input type");

xml value8 = xml `<a id="2">
<id id="2">1</id>
<id id="2">2</id>
<id id="2">3</id>
</a>`;
record {record{string:RegExp id;}[] id;}|error rec8 = parseAsType(value8);
test:assertTrue(rec8 is Error);
test:assertEquals((<error>rec8).message(), "unsupported input type");
}
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,27 @@ public static String generateStringFromXmlReader(Reader reader) throws IOExcepti
return builder.toString();
}

public static boolean isSupportedTypeForAttributes(Type fieldType) {
if (TypeTags.isIntegerTypeTag(fieldType.getTag())) {
return true;
}

if (TypeTags.isStringTypeTag(fieldType.getTag())) {
return true;
}

if (TypeTags.isXMLTypeTag(fieldType.getTag())) {
return false;
}

return switch (fieldType.getTag()) {
case TypeTags.FLOAT_TAG, TypeTags.BOOLEAN_TAG, TypeTags.NULL_TAG,
TypeTags.DECIMAL_TAG, TypeTags.BYTE_TAG, TypeTags.UNION_TAG, TypeTags.ANYDATA_TAG,
TypeTags.ANY_TAG, TypeTags.JSON_TAG -> true;
default -> false;
};
}

public static boolean isContainsUnionType(Type expType) {
if (expType == null) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ public enum DiagnosticErrorCode {
INVALID_SEQUENCE_ANNOTATION("XML_ERROR_0026", "invalid.sequence.annotation"),
INVALID_CHOICE_ANNOTATION("XML_ERROR_0027", "invalid.choice.annotation"),
INVALID_XSD_ANNOTATION("XML_ERROR_0028", "invalid.xsd.annotation"),
INVALID_XML("XML_ERROR_0029", "invalid.xml");
INVALID_XML("XML_ERROR_0029", "invalid.xml"),
ATTRIBUTE_CANNOT_CONVERT_INTO_ARRAY_TYPE("XML_ERROR_0031",
"attributes.cannot.convert.to.array.type"),
CANNOT_CONVERT_ATTRIBUTE_TO_ARRAY_TYPE("XML_ERROR_0032", "cannot.convert.attributes.to.array.type");

String diagnosticId;
String messageKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -841,9 +841,20 @@ private void handleAttributes(BXmlItem xmlItem, BMap<BString, Object> currentNod
analyzerData.rootRecord);
}

Type fieldType = field.getFieldType();

if (DataUtils.isRegExpType(fieldType)) {
throw DiagnosticLog.error(DiagnosticErrorCode.UNSUPPORTED_TYPE);
}

if (!DataUtils.isSupportedTypeForAttributes(TypeUtils.getReferredType(fieldType))) {
throw DiagnosticLog.error(DiagnosticErrorCode.CANNOT_CONVERT_ATTRIBUTE_TO_ARRAY_TYPE,
field.getFieldName(), fieldType);
}

try {
currentNode.put(StringUtils.fromString(field.getFieldName()),
DataUtils.convertStringToExpType(attributeMap.get(key), field.getFieldType()));
DataUtils.convertStringToExpType(attributeMap.get(key), fieldType));
} catch (Exception e) {
// Ignore: Expected type will mismatch when element and attribute having same name.
}
Expand Down
2 changes: 2 additions & 0 deletions native/src/main/resources/error.properties
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,5 @@ error.invalid.xsd.annotation=\

error.invalid.xml=\
Invalid XML found: ''{0}''
error.cannot.convert.attributes.to.array.type=\
attribute ''{0}'' cannot be converted into the array type ''{1}''

0 comments on commit 8116c64

Please sign in to comment.