From fd3c9f65f1bb753f850c774a151673827d624577 Mon Sep 17 00:00:00 2001 From: Kalaiyarasiganeshalingam Date: Tue, 6 Dec 2022 20:10:57 +0530 Subject: [PATCH 1/8] [Automated] Update native jar versions in toml files --- ballerina/Dependencies.toml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index e4aa0e76..b6168056 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -6,6 +6,18 @@ [ballerina] dependencies-toml-version = "2" +[[package]] +org = "ballerina" +name = "io" +version = "1.3.1" +dependencies = [ + {org = "ballerina", name = "jballerina.java"}, + {org = "ballerina", name = "lang.value"} +] +modules = [ + {org = "ballerina", packageName = "io", moduleName = "io"} +] + [[package]] org = "ballerina" name = "jballerina.java" @@ -14,6 +26,14 @@ modules = [ {org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"} ] +[[package]] +org = "ballerina" +name = "lang.value" +version = "0.0.0" +dependencies = [ + {org = "ballerina", name = "jballerina.java"} +] + [[package]] org = "ballerina" name = "test" @@ -31,6 +51,7 @@ org = "ballerina" name = "xmldata" version = "2.3.1" dependencies = [ + {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "test"} ] From 650721b8af76254a326a807950efc73cdc4c45a9 Mon Sep 17 00:00:00 2001 From: Kalaiyarasiganeshalingam Date: Tue, 6 Dec 2022 20:58:30 +0530 Subject: [PATCH 2/8] [Automated] Update native jar versions in toml files --- ballerina/Dependencies.toml | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index b6168056..e4aa0e76 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -6,18 +6,6 @@ [ballerina] dependencies-toml-version = "2" -[[package]] -org = "ballerina" -name = "io" -version = "1.3.1" -dependencies = [ - {org = "ballerina", name = "jballerina.java"}, - {org = "ballerina", name = "lang.value"} -] -modules = [ - {org = "ballerina", packageName = "io", moduleName = "io"} -] - [[package]] org = "ballerina" name = "jballerina.java" @@ -26,14 +14,6 @@ modules = [ {org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"} ] -[[package]] -org = "ballerina" -name = "lang.value" -version = "0.0.0" -dependencies = [ - {org = "ballerina", name = "jballerina.java"} -] - [[package]] org = "ballerina" name = "test" @@ -51,7 +31,6 @@ org = "ballerina" name = "xmldata" version = "2.3.1" dependencies = [ - {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "test"} ] From e62d50124865008d45545e4ce7b8557bc4fbaae7 Mon Sep 17 00:00:00 2001 From: Kalaiyarasiganeshalingam Date: Tue, 6 Dec 2022 20:59:35 +0530 Subject: [PATCH 3/8] Fix issues in toXml function --- ballerina/tests/to_xml_test.bal | 238 +++++++++++++----- ballerina/xmldata.bal | 23 +- .../stdlib/xmldata/utils/Constants.java | 1 + .../stdlib/xmldata/utils/XmlDataUtils.java | 74 ++++-- 4 files changed, 245 insertions(+), 91 deletions(-) diff --git a/ballerina/tests/to_xml_test.bal b/ballerina/tests/to_xml_test.bal index 9a278f88..80dd843c 100644 --- a/ballerina/tests/to_xml_test.bal +++ b/ballerina/tests/to_xml_test.bal @@ -74,7 +74,7 @@ isolated function testMapStringToXml2() returns error? { type Customer record { @Name { - value: "ns:employeeName" + value: "employeeName" } @Attribute string ns\:name; @@ -103,7 +103,7 @@ isolated function testRecordWithAnnotationToXml1() returns error? { type Customer2 record { @Name { - value: "ns:employeeName" + value: "employeeName" } @Attribute string ns\:name; @@ -133,7 +133,7 @@ type Customer3 record { @Attribute @Name { - value: "ns:employeeName" + value: "employeeName" } string ns\:name; @@ -162,7 +162,7 @@ type Customer4 record { @Attribute @Name { - value: "ns:employeeName" + value: "employeeName" } string ns\:name; @@ -537,8 +537,14 @@ type BookStore6 record { string storeName; int postalCode; boolean isOpen; - Address6 address; - Codes6 codes; + @Name{ + value: "address" + } + Address6 add; + @Name{ + value: "codes" + } + Codes6 codeValues; @Attribute string status; @Attribute @@ -552,7 +558,10 @@ type Address6 record { }; type Codes6 record { - int[] item; + @Name{ + value: "item" + } + int[] items; }; @test:Config { @@ -564,13 +573,13 @@ isolated function testComplexRecordToXml() returns error? { storeName: "foo", postalCode: 94, isOpen: true, - address: { + add: { street: "Galle Road", city: "Colombo", country: "Sri Lanka" }, - codes: { - item: [4, 8, 9] + codeValues: { + items: [4, 8, 9] }, 'xmlns\:ns0: "http://sample.com/test", status: "online" @@ -600,9 +609,9 @@ isolated function testComplexRecordToXml() returns error? { @Namespace { uri: "example.com" } -type Purchesed_Bill record { - Purchesed_Items PurchesedItems; - Purchesed_Address Address; +type Purchased_Bill record { + Purchased_Items PurchasedItems; + Purchased_Address Address; @Attribute string 'xmlns\:ns?; @Attribute @@ -611,16 +620,16 @@ type Purchesed_Bill record { string ns\:attr?; }; -type Purchesed_Items record { - Purchesed_Purchase[] PLine; +type Purchased_Items record { + Purchased_Purchase[] PLine; }; -type Purchesed_Purchase record { - string|Purchesed_ItemCode ItemCode; +type Purchased_Purchase record { + string|Purchased_ItemCode ItemCode; int Count; }; -type Purchesed_ItemCode record { +type Purchased_ItemCode record { @Attribute string discount; string \#content?; @@ -629,7 +638,7 @@ type Purchesed_ItemCode record { @Namespace { uri: "" } -type Purchesed_Address record { +type Purchased_Address record { string StreetAddress; string City; int Zip; @@ -639,9 +648,9 @@ type Purchesed_Address record { @test:Config { groups: ["toXml"] } -isolated function testRecordWithNamaspaceAnnotationToXml() returns error? { - Purchesed_Bill input = { - PurchesedItems: { +isolated function testRecordWithNamespaceAnnotationToXml() returns error? { + Purchased_Bill input = { + PurchasedItems: { PLine: [ {ItemCode: "223345", Count: 10}, {ItemCode: "223300", Count: 7}, @@ -662,8 +671,8 @@ isolated function testRecordWithNamaspaceAnnotationToXml() returns error? { ns\:attr: "ns-attr-val" }; string expected = - "" + - "" + + "" + + "" + "" + "223345" + "10" + @@ -676,14 +685,14 @@ isolated function testRecordWithNamaspaceAnnotationToXml() returns error? { "200777" + "7" + "" + - "" + - "
" + + "" + + "
" + "20, Palm grove, Colombo 3" + "Colombo" + "300" + "LK" + "
" + - ""; + ""; xml result = check toXml(input); test:assertEquals(result.toString(), expected, msg = "testComplexRecordToXml result incorrect"); } @@ -691,8 +700,11 @@ isolated function testRecordWithNamaspaceAnnotationToXml() returns error? { @Namespace { uri: "example.com" } -type Purchesed_Bill1 record { - Purchesed_Items1 PurchesedItems; +type Purchased_Bill1 record { + @Name{ + value: "PurchasedItems" + } + Purchased_Items1 PurchasedItem; @Attribute string 'xmlns\:ns?; @Attribute @@ -705,12 +717,12 @@ type Purchesed_Bill1 record { prefix: "ns0", uri: "example.com" } -type Purchesed_Items1 record { - Purchesed_Purchase1[] PLine; +type Purchased_Items1 record { + Purchased_Purchase1[] PLine; }; -type Purchesed_Purchase1 record { - string|Purchesed_ItemCode1 ItemCode; +type Purchased_Purchase1 record { + string|Purchased_ItemCode1 ItemCode; int Count; }; @@ -718,7 +730,7 @@ type Purchesed_Purchase1 record { prefix: "ns2", uri: "example1.com" } -type Purchesed_ItemCode1 record { +type Purchased_ItemCode1 record { @Attribute string discount; string \#content?; @@ -728,8 +740,8 @@ type Purchesed_ItemCode1 record { groups: ["toXml"] } isolated function testRecordWithNamaspaceAnnotationToXml1() returns error? { - Purchesed_Bill1 input = { - PurchesedItems: { + Purchased_Bill1 input = { + PurchasedItem: { PLine: [ {ItemCode: "223345", Count: 10}, {ItemCode: "223300", Count: 7}, @@ -744,8 +756,8 @@ isolated function testRecordWithNamaspaceAnnotationToXml1() returns error? { ns\:attr: "ns-attr-val" }; string expected = - "" + - "" + + "" + + "" + "" + "223345" + "10" + @@ -758,8 +770,8 @@ isolated function testRecordWithNamaspaceAnnotationToXml1() returns error? { "200777" + "7" + "" + - "" + - ""; + "" + + ""; xml result = check toXml(input); test:assertEquals(result.toString(), expected, msg = "testRecordWithNamaspaceAnnotationToXml1 result incorrect"); } @@ -768,8 +780,8 @@ isolated function testRecordWithNamaspaceAnnotationToXml1() returns error? { prefix: "ns0", uri: "example.com" } -type Purchesed_Bill2 record { - Purchesed_Items2 purchesedItems; +type Purchased_Bill2 record { + Purchased_Items2 PurchasedItems; @Attribute string 'xmlns\:ns?; @Attribute @@ -782,23 +794,23 @@ type Purchesed_Bill2 record { prefix: "ns1", uri: "example1.com" } -type Purchesed_Items2 record { - Purchesed_Purchase2[] pLine; +type Purchased_Items2 record { + Purchased_Purchase2[] pLine; }; @Namespace { prefix: "ns2", uri: "example2.com" } -type Purchesed_Purchase2 record { - string|Purchesed_ItemCode2 itemCode; +type Purchased_Purchase2 record { + string|Purchased_ItemCode2 itemCode; int count; }; @Namespace { uri: "example1.com" } -type Purchesed_ItemCode2 record { +type Purchased_ItemCode2 record { @Attribute string discount; string \#content?; @@ -808,8 +820,8 @@ type Purchesed_ItemCode2 record { groups: ["toXml"] } isolated function testRecordWithNamaspaceAnnotationToXml2() returns error? { - Purchesed_Bill2 input = { - purchesedItems: { + Purchased_Bill2 input = { + PurchasedItems: { pLine: [ {itemCode: "223345", count: 10}, {itemCode: "223300", count: 7}, @@ -824,8 +836,8 @@ isolated function testRecordWithNamaspaceAnnotationToXml2() returns error? { ns\:attr: "ns-attr-val" }; string expected = - "" + - "" + + "" + + "" + "" + "223345" + "10" + @@ -838,8 +850,8 @@ isolated function testRecordWithNamaspaceAnnotationToXml2() returns error? { "200777" + "7" + "" + - "" + - ""; + "" + + ""; xml result = check toXml(input); test:assertEquals(result.toString(), expected, msg = "testRecordWithNamaspaceAnnotationToXml2 result incorrect"); } @@ -869,7 +881,7 @@ isolated function testRecordWithAnnotationToXml5() returns error? { CustomerDetails data = {ns\:name: "Asha", age: 10}; xml result = check toXml(data); test:assertEquals(result, - xml `10`, + xml `10`, msg = "testRecordWithAnnotationToXml5 result incorrect"); } @@ -879,7 +891,7 @@ isolated function testRecordWithAnnotationToXml5() returns error? { } type Invoices record { int id; - string purchesedItem; + string PurchasedItem; @Attribute string 'xmlns?; @Attribute @@ -894,7 +906,7 @@ type Invoices record { isolated function testRecordWithAnnotationToXml6() returns error? { Invoices data = { id: 1, - purchesedItem: "soap", + PurchasedItem: "soap", attr: "attr-val", 'xmlns: "example2.com", ns\:attr: "example1.com" @@ -902,7 +914,7 @@ isolated function testRecordWithAnnotationToXml6() returns error? { string expected = "" + "1" + - "soap" + + "soap" + ""; xml result = check toXml(data); test:assertEquals(result.toString(), expected, msg = "testRecordWithAnnotationToXml6 result incorrect"); @@ -957,3 +969,115 @@ isolated function testRecordWithAnnotationToXml7() returns error? { xml result = check toXml(data); test:assertEquals(result.toString(), expected, msg = "testRecordWithAnnotationToXml6 result incorrect"); } + +@Namespace { + prefix: "nso", + uri: "example.com" +} +@Name { + value: "PurchasedBill" +} +type Example record { + PurchasedItems PurchasedItems; + PurchasedAddress Address; + @Attribute + string 'xmlns\:ns?; + @Attribute + string attr?; + @Attribute + string ns\:attr?; +}; + +@Namespace { + prefix: "ns1", + uri: "example1.com" +} +@Name { + value: "PurchasedPurchase" +} +type PurchasedItems record { + Example1[] PLine; +}; + +@Namespace { + prefix: "ns2", + uri: "example1.com" +} +type Example1 record { + string|PurchasedItemCode ItemCode; + int Count; + @Attribute + string attr?; +}; + +@Namespace { + prefix: "ns3", + uri: "example1.com" +} +type PurchasedItemCode record { + @Attribute + string discount; + string \#content?; +}; + +@Namespace { + uri: "example3.com" +} +type PurchasedAddress record { + string StreetAddress; + string City; + int Zip; + string Country; +}; + +@test:Config { + groups: ["toXml"] +} +isolated function testRecordWithNamespaceAnnotationToXml1() returns error? { + Example input = { + PurchasedItems: { + PLine: [ + {ItemCode: "223345", Count: 10, attr: "1"}, + {ItemCode: "223300", Count: 7}, + { + ItemCode: {discount: "22%", \#content: "200777"}, + Count: 7 + } + ] + }, + Address: { + StreetAddress: "20, Palm grove, Colombo 3", + City: "Colombo", + Zip: 300, + Country: "LK" + }, + 'xmlns\:ns: "ns.com", + attr: "attr-val", + ns\:attr: "ns-attr-val" + }; + string expected = + "" + + "" + + "" + + "223345" + + "10" + + "" + + "" + + "223300" + + "7" + + "" + + "" + + "200777" + + "7" + + "" + + "" + + "
" + + "20, Palm grove, Colombo 3" + + "Colombo" + + "300" + + "LK" + + "
" + + "
"; + xml result = check toXml(input); + test:assertEquals(result.toString(), expected, msg = "testComplexRecordToXml result incorrect"); +} diff --git a/ballerina/xmldata.bal b/ballerina/xmldata.bal index d9380f47..b4c67a52 100644 --- a/ballerina/xmldata.bal +++ b/ballerina/xmldata.bal @@ -21,9 +21,9 @@ const string CONTENT = "#content"; const string ATTRIBUTE_PREFIX = "attribute_"; const string XMLNS = "xmlns"; -# Defines the new name of the name. +# Defines the name of the XML element. # -# + value - The value of the new name +# + value - The name of the XML element public type NameConfig record {| string value; |}; @@ -47,8 +47,8 @@ public annotation NamespaceConfig Namespace on type; public annotation Attribute on record field; # Converts a `Map` or `Record` representation to its XML representation. -# The record has annotations to configure namespaces and attributes, -# but others don't have these. +# If the data is a defined record type, namespaces and attributes can be +# defined using annotations. But other types do not have this support. # # + mapValue - The `Map` or `Record` representation source to be converted to XML # + return - XML representation of the given source if the source is @@ -373,7 +373,7 @@ public isolated function toJson(xml xmlValue, XmlOptions options = {}) returns j # + xmlValue - The XML source to be converted to a Record # + preserveNamespaces - Instructs whether to preserve the namespaces of the XML when converting # + returnType - The `typedesc` of the record that should be returned as a result. -# The optional value fields are not allowed in the record type. +# The optional value fields are not allowed in the record type. # + return - The Record representation of the given XML on success, else returns an `xmldata:Error` # # Deprecated # This function is going away in a future release. Use `fromXml` instead. @@ -383,14 +383,15 @@ returns returnType|Error = @java:Method { 'class: "io.ballerina.stdlib.xmldata.XmlToRecord" } external; -# Converts an XML to its `Map` or `Record` representation. -# The namespaces and attributes will not be considered a special case. +# Converts XML to its `map` or `Record` representation. +# If `returnType` is not a defined record type, namespaces and attributes are omitted by this conversion. # -# + xmlValue - The XML source to be converted to a given target type -# + returnType - The `typedesc` of the `map` that should be returned as a result +# + xmlValue - The XML source to be converted to a given target type. If the XML elements have a prefix and +# `returnType` is also a defined record, the field names of the record must also have the same prefix. +# + returnType - The `typedesc` of the `Map` or `Record` that should be returned as a result # + return - The given target type representation of the given XML on success, -# else returns an `xmldata:Error` -public isolated function fromXml(xml xmlValue, typedesc<(map)> returnType = <>) +# else returns an `xmldata:Error` +public isolated function fromXml(xml xmlValue, typedesc> returnType = <>) returns returnType|Error = @java:Method { 'class: "io.ballerina.stdlib.xmldata.MapFromXml" } external; diff --git a/native/src/main/java/io/ballerina/stdlib/xmldata/utils/Constants.java b/native/src/main/java/io/ballerina/stdlib/xmldata/utils/Constants.java index 5b60c42c..df3862ad 100644 --- a/native/src/main/java/io/ballerina/stdlib/xmldata/utils/Constants.java +++ b/native/src/main/java/io/ballerina/stdlib/xmldata/utils/Constants.java @@ -35,6 +35,7 @@ private Constants() {} public static final String OPTIONS_ATTRIBUTE_PREFIX = "attributePrefix"; public static final String OPTIONS_PRESERVE_NS = "preserveNamespaces"; public static final String UNDERSCORE = "_"; + public static final String COLON = ":"; public static final MapType JSON_MAP_TYPE = TypeCreator.createMapType(PredefinedTypes.TYPE_JSON); public static final ArrayType JSON_ARRAY_TYPE = TypeCreator.createArrayType(PredefinedTypes.TYPE_JSON); public static final String FIELD = "$field$."; diff --git a/native/src/main/java/io/ballerina/stdlib/xmldata/utils/XmlDataUtils.java b/native/src/main/java/io/ballerina/stdlib/xmldata/utils/XmlDataUtils.java index 826bc42c..8888c53a 100644 --- a/native/src/main/java/io/ballerina/stdlib/xmldata/utils/XmlDataUtils.java +++ b/native/src/main/java/io/ballerina/stdlib/xmldata/utils/XmlDataUtils.java @@ -41,6 +41,9 @@ import java.util.Locale; import java.util.Map; +import static io.ballerina.stdlib.xmldata.utils.Constants.COLON; +import static io.ballerina.stdlib.xmldata.utils.Constants.UNDERSCORE; + /** * A util class for the XmlData package's native implementation. * @@ -102,32 +105,42 @@ private static BMap addFields(BMap input, Type Map fields = ((RecordType) type).getFields(); BMap annotations = ((RecordType) type).getAnnotations(); for (Map.Entry entry: input.entrySet()) { - BString key = entry.getKey(); + String key = entry.getKey().getValue(); Object value = entry.getValue(); - if (fields.containsKey(key.getValue())) { - Type fieldType = fields.get(key.getValue()).getFieldType(); + if (fields.containsKey(key)) { + Type fieldType = fields.get(key).getFieldType(); fieldType = getTypeFromUnionType(fieldType, value); if (fieldType.getTag() == TypeTags.RECORD_TYPE_TAG) { processRecord(key, annotations, recordValue, value, fieldType); } else if (fieldType.getTag() == TypeTags.TYPE_REFERENCED_TYPE_TAG) { Type referredType = TypeUtils.getReferredType(fieldType); + if (annotations.size() > 0) { + key = getKeyNameFromAnnotation(annotations, key); + } BMap subRecordAnnotations = ((RecordType) referredType).getAnnotations(); - key = getElementName(subRecordAnnotations, key.getValue()); - recordValue.put(key, addFields(((BMap) value), referredType)); + key = getElementName(subRecordAnnotations, key); + BMap annotationRecord = ValueCreator.createMapValue(Constants.JSON_MAP_TYPE); + processSubRecordAnnotation(subRecordAnnotations, annotationRecord); + BMap subRecordValue = addFields(((BMap) value), referredType); + if (annotationRecord.size() > 0) { + subRecordValue.put(annotationRecord.getKeys()[0], + annotationRecord.get(annotationRecord.getKeys()[0])); + } + recordValue.put(StringUtils.fromString(key), subRecordValue); } else if (fieldType.getTag() == TypeTags.ARRAY_TAG) { processArray(fieldType, annotations, recordValue, entry); } else { - addPrimitiveValue(key, annotations, recordValue, value); + addPrimitiveValue(StringUtils.fromString(key), annotations, recordValue, value); } } else { - recordValue.put(key, value); + recordValue.put(StringUtils.fromString(key), value); } } return recordValue; } @SuppressWarnings("unchecked") - private static void processRecord(BString key, BMap parentAnnotations, + private static void processRecord(String key, BMap parentAnnotations, BMap record, Object value, Type childType) { BMap parentRecordAnnotations = ValueCreator.createMapValue(Constants.JSON_MAP_TYPE); BMap annotation = ((RecordType) childType).getAnnotations(); @@ -138,8 +151,8 @@ private static void processRecord(BString key, BMap parentAnnot if (annotation.size() > 0) { processSubRecordAnnotation(annotation, subRecord); } - key = getElementName(annotation, key.getValue()); - record.put(key, subRecord); + key = getElementName(annotation, key); + record.put(StringUtils.fromString(key), subRecord); if (parentRecordAnnotations.size() > 0) { record.put(parentRecordAnnotations.getKeys()[0], parentRecordAnnotations.get(parentRecordAnnotations.getKeys()[0])); @@ -153,8 +166,7 @@ private static void addPrimitiveValue(BString key, BMap annotat StringUtils.fromString((Constants.FIELD + key).replace(":", "\\:")); if (annotations.containsKey(annotationKey)) { BMap annotationValue = (BMap) annotations.get(annotationKey); - BString keyValue = processFieldAnnotation(annotationValue, key.getValue()); - record.put(keyValue, value); + record.put(StringUtils.fromString(processFieldAnnotation(annotationValue, key.getValue())), value); } else { record.put(key, value); } @@ -165,7 +177,9 @@ private static void processArray(Type childType, BMap annotatio 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) { + keyName = getKeyNameFromAnnotation(annotations, keyName); processSubRecordAnnotation(annotations, annotationRecord); } BArray arrayValue = (BArray) entry.getValue(); @@ -177,15 +191,16 @@ private static void processArray(Type childType, BMap annotatio subRecord = processParentAnnotation(elementType, subRecord); records.add((BMap) subRecord.get(subRecord.getKeys()[0])); } - record.put(getElementName(((RecordType) elementType).getAnnotations(), - entry.getKey().getValue()), ValueCreator.createArrayValue(records.toArray(), - TypeCreator.createArrayType(Constants.JSON_ARRAY_TYPE))); + record.put( + StringUtils.fromString(getElementName(((RecordType) elementType).getAnnotations(), keyName)), + ValueCreator.createArrayValue(records.toArray(), + TypeCreator.createArrayType(Constants.JSON_ARRAY_TYPE))); } else { List records = new ArrayList<>(); for (int i = 0; i < arrayValue.getLength(); i++) { records.add(arrayValue.get(i)); } - record.put(entry.getKey(), ValueCreator.createArrayValue(records.toArray(), + record.put(StringUtils.fromString(keyName), ValueCreator.createArrayValue(records.toArray(), TypeCreator.createArrayType(Constants.JSON_ARRAY_TYPE))); } if (annotationRecord.size() > 0) { @@ -194,6 +209,17 @@ private static void processArray(Type childType, BMap annotatio } } + @SuppressWarnings("unchecked") + private static String getKeyNameFromAnnotation(BMap annotations, String keyName) { + BString annotationKey = StringUtils.fromString((Constants.FIELD + keyName). + replace(":", "\\:")); + if (annotations.containsKey(annotationKey)) { + BMap annotationValue = (BMap) annotations.get(annotationKey); + return processFieldAnnotation(annotationValue, keyName); + } + return keyName; + } + public static Type getTypeFromUnionType(Type childType, Object value) { if (childType instanceof UnionType) { UnionType bUnionType = ((UnionType) childType); @@ -222,14 +248,16 @@ private static BMap processParentAnnotation(Type type, BMap annotation, String key) { + private static String processFieldAnnotation(BMap annotation, String key) { for (BString value : annotation.getKeys()) { String stringValue = value.getValue(); if (stringValue.endsWith(NAME)) { BMap names = (BMap) annotation.get(value); String name = names.get(StringUtils.fromString(VALUE)).toString(); - if (key.contains(ATTRIBUTE_PREFIX)) { - key = key.substring(0, key.indexOf("_") + 1) + name; + if (key.contains(COLON)) { + key = key.substring(0, key.indexOf(COLON) + 1) + name; + } else if (key.contains(ATTRIBUTE_PREFIX)) { + key = key.substring(0, key.indexOf(UNDERSCORE) + 1) + name; } else { key = name; } @@ -238,11 +266,11 @@ private static BString processFieldAnnotation(BMap annotation, key = ATTRIBUTE_PREFIX.concat(key); } } - return StringUtils.fromString(key); + return key; } private static BString processAnnotation(BMap annotation, String key, - BMap namespaces) { + BMap namespaces) { boolean hasNamespaceAnnotation = false; for (BString value : annotation.getKeys()) { if (!value.getValue().contains(Constants.FIELD)) { @@ -270,7 +298,7 @@ private static void processSubRecordAnnotation(BMap annotation, } @SuppressWarnings("unchecked") - private static BString getElementName(BMap annotation, String key) { + private static String getElementName(BMap annotation, String key) { BString[] keys = annotation.getKeys(); boolean hasNamespaceAnnotation = false; for (BString value : keys) { @@ -286,7 +314,7 @@ private static BString getElementName(BMap annotation, String k key = processNameAnnotation(annotation, key, value, hasNamespaceAnnotation); } } - return StringUtils.fromString(key); + return key; } @SuppressWarnings("unchecked") From bd090fc2c19fba79a761613dd2e9344d1dbcb79d Mon Sep 17 00:00:00 2001 From: Kalaiyarasiganeshalingam Date: Tue, 6 Dec 2022 21:06:01 +0530 Subject: [PATCH 4/8] Update doc --- ballerina/xmldata.bal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ballerina/xmldata.bal b/ballerina/xmldata.bal index b4c67a52..23f23a49 100644 --- a/ballerina/xmldata.bal +++ b/ballerina/xmldata.bal @@ -383,7 +383,7 @@ returns returnType|Error = @java:Method { 'class: "io.ballerina.stdlib.xmldata.XmlToRecord" } external; -# Converts XML to its `map` or `Record` representation. +# Converts an XML to its `Map` or `Record` representation. # If `returnType` is not a defined record type, namespaces and attributes are omitted by this conversion. # # + xmlValue - The XML source to be converted to a given target type. If the XML elements have a prefix and From 8bbe07461ec23f0e388ea93b629c3df777de7196 Mon Sep 17 00:00:00 2001 From: Kalaiyarasiganeshalingam Date: Tue, 6 Dec 2022 21:24:41 +0530 Subject: [PATCH 5/8] Update spec --- docs/spec/spec.md | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/docs/spec/spec.md b/docs/spec/spec.md index 9ef267eb..ea201268 100644 --- a/docs/spec/spec.md +++ b/docs/spec/spec.md @@ -3,7 +3,7 @@ _Owners_: @daneshk @kalaiyarasiganeshalingam @MadhukaHarith92 _Reviewers_: @daneshk _Created_: 2021/12/10 -_Updated_: 2022/06/07 +_Updated_: 2022/12/06 _Edition_: Swan Lake ## Introduction @@ -494,7 +494,7 @@ When `attributePrefix` is `&` and `arrayEntryTag` is `list`, the XML representat ### 4.4. Ballerina record/Map to XML Conversion This conversion provides a mapping between the different forms of Ballerina record/Map, to a corresponding matching XML representation. -The following API returns the XML data to the given Ballerina record/Map. The record has annotations to configure namespaces and attributes, but others don't have these. +The following API returns the XML data to the given Ballerina record/Map. The record has annotations to configure namespaces and attributes, but other types don't have these. ```ballerina public isolated function toXml(map mapValue) returns xml|Error ``` @@ -532,30 +532,27 @@ public annotation Attribute on record field; ``` #### 4.4.1. Sample1 ```ballerina -@Name { +@xmldata:Name { value: "Customers" } -@Namespace { +@xmldata:Namespace { prefix: "ns", uri: "http://sdf.com" } type Customer record { - @Name { + @xmldata:Name { value: "employeeName" } - @Namespace { - prefix: "ns" - } - @Attribute - string name; + @xmldata:Attribute + string ns\:name; int age; }; Customer input = { name: "Asha", age: 10 }; ``` -The XML representation of the above Record. +The XML representation of the above Record: ```ballerina @@ -571,15 +568,12 @@ map input = { genre: "Sci-Fi" }; ``` -The XML representation of the above map. +The XML representation of the above map: ```ballerina Dark Sci-Fi - German - 3 - 3296 ; ``` From 5f5a363208efc36233d54988a613da5f775eae6f Mon Sep 17 00:00:00 2001 From: Kalaiyarasiganeshalingam Date: Tue, 10 Jan 2023 23:16:40 +0530 Subject: [PATCH 6/8] Fix reviewed comments --- ballerina/xmldata.bal | 11 +++++------ docs/spec/spec.md | 4 +++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ballerina/xmldata.bal b/ballerina/xmldata.bal index 23f23a49..2f5febdd 100644 --- a/ballerina/xmldata.bal +++ b/ballerina/xmldata.bal @@ -47,8 +47,7 @@ public annotation NamespaceConfig Namespace on type; public annotation Attribute on record field; # Converts a `Map` or `Record` representation to its XML representation. -# If the data is a defined record type, namespaces and attributes can be -# defined using annotations. But other types do not have this support. +# XML `namespaces` and `attributes` can only defined through record annotations are only supported for record values. # # + mapValue - The `Map` or `Record` representation source to be converted to XML # + return - XML representation of the given source if the source is @@ -384,11 +383,11 @@ returns returnType|Error = @java:Method { } external; # Converts an XML to its `Map` or `Record` representation. -# If `returnType` is not a defined record type, namespaces and attributes are omitted by this conversion. +# XML `namespaces` and `attributes` can only defined through record annotations are only supported for record values. # -# + xmlValue - The XML source to be converted to a given target type. If the XML elements have a prefix and -# `returnType` is also a defined record, the field names of the record must also have the same prefix. -# + returnType - The `typedesc` of the `Map` or `Record` that should be returned as a result +# + xmlValue - The XML source to be converted to a given target type. If the XML elements have a prefix, +# the mapping field names of the record must also have the same prefix. +# + returnType - The `typedesc` of the returned value. this should be either `map` or `record` type. # + return - The given target type representation of the given XML on success, # else returns an `xmldata:Error` public isolated function fromXml(xml xmlValue, typedesc> returnType = <>) diff --git a/docs/spec/spec.md b/docs/spec/spec.md index ea201268..661950df 100644 --- a/docs/spec/spec.md +++ b/docs/spec/spec.md @@ -494,7 +494,9 @@ When `attributePrefix` is `&` and `arrayEntryTag` is `list`, the XML representat ### 4.4. Ballerina record/Map to XML Conversion This conversion provides a mapping between the different forms of Ballerina record/Map, to a corresponding matching XML representation. -The following API returns the XML data to the given Ballerina record/Map. The record has annotations to configure namespaces and attributes, but other types don't have these. +The following API returns the XML data to the given Ballerina record/Map. +The record has annotations to configure namespaces and attributes, +but other types(map|map|map|map|map|map|map>>) don't have these. ```ballerina public isolated function toXml(map mapValue) returns xml|Error ``` From 33e8332cdc5fd1bb583310c3143d06436450ffc4 Mon Sep 17 00:00:00 2001 From: Kalaiyarasiganeshalingam Date: Wed, 11 Jan 2023 10:54:01 +0530 Subject: [PATCH 7/8] Update change log file --- changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/changelog.md b/changelog.md index ef04ea19..8509f397 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +- [API docs update](https://github.com/ballerina-platform/ballerina-standard-library/issues/3713) + +### Fixed +-[Fix the name annotation not seems to apply for toXML() issue](https://github.com/ballerina-platform/ballerina-standard-library/issues/3716) + +## [2.3.1] - 2022-11-29 + ### Changed - [API docs updated](https://github.com/ballerina-platform/ballerina-standard-library/issues/3463) From 0ede59991598a76f1d90be7b0fd0ea4e68fa7d21 Mon Sep 17 00:00:00 2001 From: Kalaiyarasiganeshalingam Date: Wed, 11 Jan 2023 10:57:10 +0530 Subject: [PATCH 8/8] Add white space --- changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index 8509f397..b5692b07 100644 --- a/changelog.md +++ b/changelog.md @@ -7,10 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Changed -- [API docs update](https://github.com/ballerina-platform/ballerina-standard-library/issues/3713) +- [Update API docs](https://github.com/ballerina-platform/ballerina-standard-library/issues/3713) ### Fixed --[Fix the name annotation not seems to apply for toXML() issue](https://github.com/ballerina-platform/ballerina-standard-library/issues/3716) +- [Fix the name annotation not seems to apply for toXML() issue](https://github.com/ballerina-platform/ballerina-standard-library/issues/3716) ## [2.3.1] - 2022-11-29