Skip to content

Commit

Permalink
Merge pull request #58 from SasinduDilshara/finite_types_1.0.x
Browse files Browse the repository at this point in the history
Add enum and finite type support for 1.0.x
  • Loading branch information
gimantha authored Nov 29, 2024
2 parents 93ec414 + e2ffd01 commit f181f9e
Show file tree
Hide file tree
Showing 14 changed files with 251 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-timestamped-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ jobs:
call_workflow:
name: Run Build Workflow
if: ${{ github.repository_owner == 'ballerina-platform' }}
uses: ballerina-platform/ballerina-library/.github/workflows/build-timestamp-master-template.yml@main
uses: ballerina-platform/ballerina-library/.github/workflows/build-timestamp-master-template.yml@2201.10.x
secrets: inherit
3 changes: 2 additions & 1 deletion .github/workflows/build-with-bal-test-graalvm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ on:
pull_request:
branches:
- main
- 1.0.x
types: [ opened, synchronize, reopened, labeled, unlabeled ]

concurrency:
Expand All @@ -30,7 +31,7 @@ jobs:
call_stdlib_workflow:
name: Run StdLib Workflow
if: ${{ github.event_name != 'schedule' || (github.event_name == 'schedule' && github.repository_owner == 'ballerina-platform') }}
uses: ballerina-platform/ballerina-library/.github/workflows/build-with-bal-test-graalvm-template.yml@main
uses: ballerina-platform/ballerina-library/.github/workflows/build-with-bal-test-graalvm-template.yml@2201.10.x
with:
lang_tag: ${{ inputs.lang_tag }}
lang_version: ${{ inputs.lang_version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/central-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
call_workflow:
name: Run Central Publish Workflow
if: ${{ github.repository_owner == 'ballerina-platform' }}
uses: ballerina-platform/ballerina-library/.github/workflows/central-publish-template.yml@main
uses: ballerina-platform/ballerina-library/.github/workflows/central-publish-template.yml@2201.10.x
secrets: inherit
with:
environment: ${{ github.event.inputs.environment }}
2 changes: 1 addition & 1 deletion .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
call_workflow:
name: Run Release Workflow
if: ${{ github.repository_owner == 'ballerina-platform' }}
uses: ballerina-platform/ballerina-library/.github/workflows/release-package-template.yml@main
uses: ballerina-platform/ballerina-library/.github/workflows/release-package-template.yml@2201.10.x
secrets: inherit
with:
package-name: data.xmldata
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ jobs:
call_workflow:
name: Run PR Build Workflow
if: ${{ github.repository_owner == 'ballerina-platform' }}
uses: ballerina-platform/ballerina-library/.github/workflows/pull-request-build-template.yml@main
uses: ballerina-platform/ballerina-library/.github/workflows/pull-request-build-template.yml@2201.10.x
secrets: inherit
2 changes: 1 addition & 1 deletion .github/workflows/trivy-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ jobs:
call_workflow:
name: Run Trivy Scan Workflow
if: ${{ github.repository_owner == 'ballerina-platform' }}
uses: ballerina-platform/ballerina-library/.github/workflows/trivy-scan-template.yml@main
uses: ballerina-platform/ballerina-library/.github/workflows/trivy-scan-template.yml@2201.10.x
secrets: inherit
6 changes: 3 additions & 3 deletions ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
org = "ballerina"
name = "data.xmldata"
version = "1.0.0"
version = "1.1.0"
authors = ["Ballerina"]
keywords = ["xml"]
repository = "https://github.com/ballerina-platform/module-ballerina-data-xmldata"
Expand All @@ -12,8 +12,8 @@ export = ["data.xmldata"]
[[platform.java17.dependency]]
groupId = "io.ballerina.lib"
artifactId = "data-native"
version = "1.0.0"
path = "../native/build/libs/data.xmldata-native-1.0.0.jar"
version = "1.1.0"
path = "../native/build/libs/data.xmldata-native-1.1.0-SNAPSHOT.jar"

[[platform.java17.dependency]]
groupId = "io.ballerina.stdlib"
Expand Down
2 changes: 1 addition & 1 deletion ballerina/CompilerPlugin.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ id = "constraint-compiler-plugin"
class = "io.ballerina.lib.data.xmldata.compiler.XmldataCompilerPlugin"

[[dependency]]
path = "../compiler-plugin/build/libs/data.xmldata-compiler-plugin-1.0.0.jar"
path = "../compiler-plugin/build/libs/data.xmldata-compiler-plugin-1.1.0-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ modules = [
[[package]]
org = "ballerina"
name = "data.xmldata"
version = "1.0.0"
version = "1.1.0"
dependencies = [
{org = "ballerina", name = "constraint"},
{org = "ballerina", name = "io"},
Expand Down
199 changes: 199 additions & 0 deletions ballerina/tests/test_finite_types.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
//
// WSO2 LLC. licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import ballerina/test;

enum EnumA {
A = "A",
B,
C = "C2"
}

type FiniteType true|"A"|1|2;

@test:Config
function testFiniteTypes() returns error? {
record {|
EnumA a;
"A"|"B"|"C" b;
record {|
"A"|"B"|"C" c;
EnumA d;
|} nested;
|} r = check parseAsType(xml `<Root><a>A</a><b>B</b><nested><c>B</c><d>B</d></nested></Root>`);
test:assertEquals(r, {a: "A", b: "B", nested: {c: "B", d: "B"}});
}

@test:Config
function testFiniteTypesWithNestedRecords() returns error? {
record {|
EnumA a;
FiniteType b;
record {|
FiniteType c;
FiniteType e;
EnumA d;
|} nested;
|} r = check parseAsType(xml `<Root><a>C2</a><b>1</b><nested><c>2</c><d>A</d><e>true</e></nested></Root>`);
test:assertEquals(r, {a: "C2", b: 1, nested: {c: 2, d: "A", e: true}});
}

@test:Config
function testFiniteTypeArrays() returns error? {
record {|
EnumA[] a;
("A"|"B"|"C")[] b;
record {|
("A"|"B"|"C")[] c;
EnumA[] d;
|} nested;
|} r = check parseAsType(xml `<Root><a>A</a><a>A</a><b>B</b><b>B</b><nested><c>B</c><c>B</c><d>B</d><d>B</d></nested></Root>`);
test:assertEquals(r, {a: ["A", "A"], b: ["B", "B"], nested: {c: ["B", "B"], d: ["B", "B"]}});
}

@test:Config
function testFiniteTypeArrays2() returns error? {
record {|
EnumA[] a;
FiniteType[] b;
record {|
FiniteType[] c;
FiniteType[] e;
EnumA[] d;
|} nested;
|} r = check parseAsType(xml `<Root><a>C2</a><a>C2</a><b>1</b><b>1</b><nested><c>2</c><c>2</c><d>A</d><d>A</d><e>true</e><e>true</e></nested></Root>`);
test:assertEquals(r, {a: ["C2", "C2"], b: [1, 1], nested: {c: [2, 2], d: ["A", "A"], e: [true, true]}});
}

@test:Config
function testFiniteTypesWithXmlString() returns error? {
record {|
EnumA a;
"A"|"B"|"C" b;
record {|
"A"|"B"|"C" c;
EnumA d;
|} nested;
|} r = check parseString(string `<Root><a>A</a><b>B</b><nested><c>B</c><d>B</d></nested></Root>`);
test:assertEquals(r, {a: "A", b: "B", nested: {c: "B", d: "B"}});
}

@test:Config
function testFiniteTypesWithNestedRecordsWithXmlString() returns error? {
record {|
EnumA a;
FiniteType b;
record {|
FiniteType c;
FiniteType e;
EnumA d;
|} nested;
|} r = check parseString(string `<Root><a>C2</a><b>1</b><nested><c>2</c><d>A</d><e>true</e></nested></Root>`);
test:assertEquals(r, {a: "C2", b: 1, nested: {c: 2, d: "A", e: true}});
}

@test:Config
function testFiniteTypeArraysWithXmlString() returns error? {
record {|
EnumA[] a;
("A"|"B"|"C")[] b;
record {|
("A"|"B"|"C")[] c;
EnumA[] d;
|} nested;
|} r = check parseString(string `<Root><a>A</a><a>A</a><b>B</b><b>B</b><nested><c>B</c><c>B</c><d>B</d><d>B</d></nested></Root>`);
test:assertEquals(r, {a: ["A", "A"], b: ["B", "B"], nested: {c: ["B", "B"], d: ["B", "B"]}});
}

@test:Config
function testFiniteTypeArraysWithXmlString2() returns error? {
record {|
EnumA[] a;
FiniteType[] b;
record {|
FiniteType[] c;
FiniteType[] e;
EnumA[] d;
|} nested;
|} r = check parseString(string `<Root><a>C2</a><a>C2</a><b>1</b><b>1</b><nested><c>2</c><c>2</c><d>A</d><d>A</d><e>true</e><e>true</e></nested></Root>`);
test:assertEquals(r, {a: ["C2", "C2"], b: [1, 1], nested: {c: [2, 2], d: ["A", "A"], e: [true, true]}});
}
type NestedRec record {|
@Name {
value: "c2"
}
FiniteType c;
FiniteType e;
@Name {
value: "d2"
}
EnumA d;
|};

@test:Config
function testFiniteTypesWithNameAnnotations() returns error? {
record {|
EnumA a;
FiniteType b;
NestedRec nested;
|} r = check parseAsType(xml `<Root><a>C2</a><b>1</b><nested><c2>2</c2><d2>A</d2><e>true</e></nested></Root>`);
test:assertEquals(r, {a: "C2", b: 1, nested: {c: 2, d: "A", e: true}});
}

type FiniteValue 100f;

@test:Config
function testRecordFieldWithSingleFiniteType() returns error? {
record {|
EnumA a;
"A" b;
record {|
FiniteValue c;
EnumA d;
|} nested;
|} r = check parseAsType(xml `<Root><a>A</a><b>A</b><nested><c>100.0</c><d>B</d></nested></Root>`);
test:assertEquals(r, {a: "A", b: "A", nested: {c: 100f, d: "B"}});
}

@test:Config
function testRecordFieldWithSingleFiniteType2() returns error? {
record {|
100f a;
200.1d b;
100d c;
200.1f d;
100f e;
200.1d f;
100d g;
200.1f h;
|} r = check parseAsType(xml `<Root><a>100</a><b>200.1</b><c>100</c><d>200.1</d><e>100.0</e><f>200.1</f><g>100.0</g><h>200.1</h></Root>`);
test:assertEquals(r, {a: 100f, b: 200.1d, c: 100d, d: 200.1f, e: 100f, f: 200.1d, g: 100d, h: 200.1f});
}

@test:Config
function testRecordFieldWithSingleFiniteType3() returns error? {
record {|
100f a;
|}|Error r = parseAsType(xml `<Root><a>100.01</a></Root>`);
test:assertTrue(r is Error);
test:assertEquals((<Error>r).message(), "'string' value '100.01' cannot be converted to '100.0f'");

record {|
100d a;
|}|Error r2 = parseAsType(xml `<Root><a>100.01</a></Root>`);
test:assertTrue(r2 is Error);
test:assertEquals((<Error>r2).message(), "'string' value '100.01' cannot be converted to '100d'");
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
org.gradle.caching=true
group=io.ballerina.lib
version=1.0.0
version=1.1.0-SNAPSHOT
ballerinaLangVersion=2201.10.0

checkstyleToolVersion=10.12.0
Expand Down
37 changes: 37 additions & 0 deletions native/src/main/java/io/ballerina/lib/data/xmldata/FromString.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@
import io.ballerina.runtime.api.TypeTags;
import io.ballerina.runtime.api.creators.TypeCreator;
import io.ballerina.runtime.api.creators.ValueCreator;
import io.ballerina.runtime.api.types.FiniteType;
import io.ballerina.runtime.api.types.ReferenceType;
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.values.BDecimal;
import io.ballerina.runtime.api.values.BError;
import io.ballerina.runtime.api.values.BString;
import io.ballerina.runtime.api.values.BTypedesc;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
Expand Down Expand Up @@ -96,6 +99,8 @@ public static Object fromStringWithType(BString string, Type expType) {
return stringToUnion(string, JSON_TYPE_WITH_BASIC_TYPES);
case TypeTags.TYPE_REFERENCED_TYPE_TAG:
return fromStringWithType(string, ((ReferenceType) expType).getReferredType());
case TypeTags.FINITE_TYPE_TAG:
return stringToFiniteType(value, (FiniteType) expType);
default:
return returnError(value, expType.toString());
}
Expand All @@ -104,6 +109,38 @@ public static Object fromStringWithType(BString string, Type expType) {
}
}

private static Object stringToFiniteType(String value, FiniteType finiteType) {
return finiteType.getValueSpace().stream()
.filter(finiteValue -> !(convertToSingletonValue(value, finiteValue) instanceof BError))
.findFirst()
.orElseGet(() -> returnError(value, finiteType.toString()));
}

private static Object convertToSingletonValue(String str, Object singletonValue) {
String singletonStr = String.valueOf(singletonValue);
Type type = TypeUtils.getType(singletonValue);

if (singletonValue instanceof BDecimal decimalValue) {
BigDecimal bigDecimal = decimalValue.decimalValue();
if (bigDecimal.compareTo(new BigDecimal(str)) == 0) {
return fromStringWithType(StringUtils.fromString(str), type);
}
return returnError(str, singletonStr);
}

if (singletonValue instanceof Double doubleValue) {
if (doubleValue.compareTo(Double.valueOf(str)) == 0) {
return fromStringWithType(StringUtils.fromString(str), type);
}
return returnError(str, singletonStr);
}

if (str.equals(singletonStr)) {
return fromStringWithType(StringUtils.fromString(str), type);
}
return returnError(str, singletonStr);
}

private static Long stringToInt(String value) throws NumberFormatException {
return Long.parseLong(value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ 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.JSON_TAG, TypeTags.ANYDATA_TAG, TypeTags.FINITE_TYPE_TAG -> {
return true;
}
case TypeTags.ARRAY_TAG -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,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, TypeTags.FINITE_TYPE_TAG -> {
return convertStringToExpType(value, expType);
}
case TypeTags.ANYDATA_TAG, TypeTags.JSON_TAG -> {
Expand Down

0 comments on commit f181f9e

Please sign in to comment.