Skip to content

Commit

Permalink
Merge pull request #35 from MohamedSabthar/trailing-0
Browse files Browse the repository at this point in the history
  • Loading branch information
ThisaruGuruge authored Dec 1, 2023
2 parents 987d4e2 + f262f5f commit c652283
Show file tree
Hide file tree
Showing 29 changed files with 102 additions and 80 deletions.
10 changes: 5 additions & 5 deletions ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
org = "ballerinax"
name = "copybook"
version = "0.1.3"
version = "0.2.0"
authors = ["Ballerina"]
keywords = ["copybook", "serdes", "cobol", "mainframe"]
repository = "https://github.com/ballerina-platform/module-ballerinax-copybook"
Expand All @@ -15,14 +15,14 @@ graalvmCompatible = true
[[platform.java17.dependency]]
groupId = "io.ballerina.lib"
artifactId = "copybook-native"
version = "0.1.3-SNAPSHOT"
path="../native/build/libs/copybook-native-0.1.3-SNAPSHOT.jar"
version = "0.2.0-SNAPSHOT"
path="../native/build/libs/copybook-native-0.2.0-SNAPSHOT.jar"

[[platform.java17.dependency]]
groupId = "io.ballerina.lib"
artifactId = "copybook-commons"
version = "0.1.3"
path = "../commons/build/libs/copybook-commons-0.1.3-SNAPSHOT.jar"
version = "0.2.0"
path = "../commons/build/libs/copybook-commons-0.2.0-SNAPSHOT.jar"

[[platform.java17.dependency]]
groupId = "org.antlr"
Expand Down
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ dependencies = [
[[package]]
org = "ballerinax"
name = "copybook"
version = "0.1.3"
version = "0.2.0"
dependencies = [
{org = "ballerina", name = "constraint"},
{org = "ballerina", name = "file"},
Expand Down
16 changes: 8 additions & 8 deletions ballerina/convertor.bal
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import ballerina/constraint;
import ballerina/file;
import ballerina/jballerina.java;

# This class represents a copybook convertor that facilitates the conversion of ASCII data to and from JSON data.
public isolated class Convertor {
# This class represents a copybook converter that facilitates the conversion of ASCII data to and from JSON data.
public isolated class Converter {
private final Schema schema;

# Initializes the convertor with a schema.
# Initializes the converter with a schema.
# + schemaFilePath - The path of the copybook file
# + return - `copybook:Error` on failure, Nil otherwise
public isolated function init(string schemaFilePath) returns Error? {
Expand Down Expand Up @@ -61,9 +61,9 @@ public isolated class Convertor {
readonly & map<json> readonlyJson = check input.cloneWithType();
lock {
check self.validateTargetRecordName(targetRecordName);
JsonToCopybookConvertor convertor = new (self.schema, targetRecordName);
convertor.visitSchema(self.schema, readonlyJson);
return convertor.getValue();
JsonToCopybookConverter converter = new (self.schema, targetRecordName);
converter.visitSchema(self.schema, readonlyJson);
return converter.getValue();
}
} on fail error err {
return createError(err);
Expand Down Expand Up @@ -96,7 +96,7 @@ public isolated class Convertor {
# + return - A record value on success, a `copybook:Error` in case of coercion errors
public isolated function fromCopybook(string copybookData, string? targetRecordName = (),
typedesc<record {}> t = <>) returns t|Error = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

private isolated function toRecord(string copybookData, typedesc<record {}> t,
Expand All @@ -114,5 +114,5 @@ public isolated class Convertor {
}

isolated function parseSchemaFile(string schemaFilePath) returns Schema|Error = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;
18 changes: 9 additions & 9 deletions ballerina/data_item.bal
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,43 @@ isolated distinct class DataItem {
*Node;

isolated function getLevel() returns int = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getName() returns string = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getElementCount() returns int = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function isNumeric() returns boolean = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function isSigned() returns boolean = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getReadLength() returns int = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function isDecimal() returns boolean {
return self.isNumeric() && self.getFloatingPointLength() != 0;
}

isolated function getFloatingPointLength() returns int = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getPicture() returns string = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getRedefinedItemName() returns string? = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function accept(Visitor visitor, anydata data = ()) {
Expand Down
10 changes: 5 additions & 5 deletions ballerina/group_item.bal
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ distinct class GroupItem {
*Node;

isolated function getLevel() returns int = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getName() returns string = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getElementCount() returns int = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getRedefinedItemName() returns string? = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getChildren() returns Node[] = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function accept(Visitor visitor, anydata data = ()) {
Expand Down
2 changes: 1 addition & 1 deletion ballerina/init.bal
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ isolated function init() {
}

isolated function setModule() = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.ModuleUtils"
'class: "io.ballerina.lib.copybook.runtime.converter.ModuleUtils"
} external;
10 changes: 7 additions & 3 deletions ballerina/json_to_copybook_convertor.bal
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// specific language governing permissions and limitations
// under the License.

class JsonToCopybookConvertor {
class JsonToCopybookConverter {
*Visitor;

private final string[] value = [];
Expand Down Expand Up @@ -220,7 +220,11 @@ class JsonToCopybookConvertor {

check self.checkDecimalLength(wholeNumber, fraction, input, dataItem);
// Handle trailing zeros in decimal
fraction = fraction.substring(0, dataItem.getFloatingPointLength());
if fraction.length() < dataItem.getFloatingPointLength() {
fraction = fraction.padEnd(dataItem.getFloatingPointLength(), "0");
} else if fraction.length() > dataItem.getFloatingPointLength() {
fraction = fraction.substring(0, dataItem.getFloatingPointLength());
}
// Handle supress zero ex: Z(9)9.8;
int supressZeroCount = getSupressZeroCount(dataItem.getPicture());
string decimalString = wholeNumber + "." + fraction.padEnd(dataItem.getFloatingPointLength(), "0");
Expand All @@ -238,7 +242,7 @@ class JsonToCopybookConvertor {
}

private isolated function checkDecimalLength(string wholeNumber, string fraction, decimal input,
DataItem dataItem) returns error? {
DataItem dataItem) returns error? {
// A deducted of 1 made from readLength for decimal seperator "."
int expectedWholeNumberLength = dataItem.getReadLength() - dataItem.getFloatingPointLength() - 1;
// If PIC has + or -, then remove the space allocated for the sign
Expand Down
4 changes: 2 additions & 2 deletions ballerina/schema.bal
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ distinct class Schema {
}

isolated function getTypeDefinitions() returns Node[] = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getRedefinedItems() returns map<Node> = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function accept(Visitor visitor, anydata data = ()) {
Expand Down
1 change: 1 addition & 0 deletions ballerina/tests/resources/copybook-ascii/copybook-10.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10.00
3 changes: 3 additions & 0 deletions ballerina/tests/resources/copybook-json/copybook-10.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Decimal": 10
}
1 change: 1 addition & 0 deletions ballerina/tests/resources/copybooks/copybook-10.cpy
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
01 Decimal PIC 9(2).99.
69 changes: 39 additions & 30 deletions ballerina/tests/test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -25,42 +25,42 @@ isolated function testParseSchemaFile() returns error? {
}

@test:Config {
dataProvider: testConvertorDataProvider
dataProvider: testConverterDataProvider
}
isolated function testConvertor(string copybookFilePath, string inputFilePath) returns error? {
Convertor convertor = check new (copybookFilePath);
isolated function testConverter(string copybookFilePath, string inputFilePath) returns error? {
Converter converter = check new (copybookFilePath);
string[] input = check io:fileReadLines(inputFilePath);
foreach string line in input {
map<json> jsonData = check (check convertor.toJson(line)).get(DATA).ensureType();
string output = check convertor.toCopybook(jsonData);
map<json> jsonData = check (check converter.toJson(line)).get(DATA).ensureType();
string output = check converter.toCopybook(jsonData);
test:assertEquals(output, line);
}
}

isolated function testConvertorDataProvider() returns [string, string][] {
isolated function testConverterDataProvider() returns [string, string][] {
[string, string][] filePaths = [];
foreach int i in 1 ... 5 {
filePaths.push([getCopybookPath(string `copybook-${i}`), getInputPath(string `copybook-${i}`)]);
filePaths.push([getCopybookPath(string `copybook-${i}`), getAsciiFilePath(string `copybook-${i}`)]);
}
return filePaths;
}

@test:Config
isolated function testConvertorWithTargetRecordName() returns error? {
Convertor convertor = check new (getCopybookPath("copybook-6"));
string[] input = check io:fileReadLines(getInputPath("copybook-6"));
isolated function testConverterWithTargetRecordName() returns error? {
Converter converter = check new (getCopybookPath("copybook-6"));
string[] input = check io:fileReadLines(getAsciiFilePath("copybook-6"));
foreach string line in input {
map<json> jsonData = check (check convertor.toJson(line, "DATA-DETAIL-REGISTRY")).get(DATA).ensureType();
string output = check convertor.toCopybook(jsonData, "DATA-DETAIL-REGISTRY");
map<json> jsonData = check (check converter.toJson(line, "DATA-DETAIL-REGISTRY")).get(DATA).ensureType();
string output = check converter.toCopybook(jsonData, "DATA-DETAIL-REGISTRY");
test:assertEquals(output, line);
}
}

@test:Config
isolated function testToJsonWithInvalidTargetRecordName() returns error? {
Convertor convertor = check new (getCopybookPath("copybook-7"));
string input = check io:fileReadString(getInputPath("copybook-7"));
Copybook7|Error copybook = convertor.fromCopybook(input, "InvalidName");
Converter converter = check new (getCopybookPath("copybook-7"));
string input = check io:fileReadString(getAsciiFilePath("copybook-7"));
Copybook7|Error copybook = converter.fromCopybook(input, "InvalidName");
if copybook !is Error {
test:assertFail("Expected a 'copybook:Error'");
}
Expand All @@ -69,9 +69,9 @@ isolated function testToJsonWithInvalidTargetRecordName() returns error? {

@test:Config
isolated function testToJsonRequiresTargetRecordName() returns error? {
Convertor convertor = check new (getCopybookPath("copybook-7"));
string input = check io:fileReadString(getInputPath("copybook-7"));
Copybook7|Error copybook = convertor.fromCopybook(input);
Converter converter = check new (getCopybookPath("copybook-7"));
string input = check io:fileReadString(getAsciiFilePath("copybook-7"));
Copybook7|Error copybook = converter.fromCopybook(input);
if copybook !is Error {
test:assertFail("Expected a 'copybook:Error'");
}
Expand All @@ -80,20 +80,20 @@ isolated function testToJsonRequiresTargetRecordName() returns error? {

@test:Config
isolated function testfromCopybookApi() returns error? {
Convertor convertor = check new (getCopybookPath("copybook-7"));
string[] input = check io:fileReadLines(getInputPath("copybook-7"));
Converter converter = check new (getCopybookPath("copybook-7"));
string[] input = check io:fileReadLines(getAsciiFilePath("copybook-7"));
foreach string line in input {
Copybook7 copybook = check convertor.fromCopybook(line, "Record2");
string output = check convertor.toCopybook(copybook, "Record2");
Copybook7 copybook = check converter.fromCopybook(line, "Record2");
string output = check converter.toCopybook(copybook, "Record2");
test:assertEquals(output, line);
}
}

@test:Config
isolated function testfromCopybookReturningError() returns error? {
Convertor convertor = check new (getCopybookPath("copybook-8"));
string input = check io:fileReadString(getInputPath("copybook-8"));
Copybook8|Error copybook = convertor.fromCopybook(input);
Converter converter = check new (getCopybookPath("copybook-8"));
string input = check io:fileReadString(getAsciiFilePath("copybook-8"));
Copybook8|Error copybook = converter.fromCopybook(input);
if copybook !is Error {
test:assertFail("Expected a 'copybook:Error' but found a 'string'");
}
Expand All @@ -104,22 +104,31 @@ isolated function testfromCopybookReturningError() returns error? {

@test:Config
isolated function testToCopybookWithoutRedefinedItems() returns error? {
Convertor convertor = check new (getCopybookPath("copybook-1"));
Converter converter = check new (getCopybookPath("copybook-1"));
json jsonInput = check io:fileReadJson(getCopybookJsonPath("copybook-1"));
string asciiData = check convertor.toCopybook(check jsonInput.cloneWithType());
string expectedAscii = check io:fileReadString(getInputPath("copybook-1"));
string asciiData = check converter.toCopybook(check jsonInput.cloneWithType());
string expectedAscii = check io:fileReadString(getAsciiFilePath("copybook-1"));
test:assertEquals(asciiData, expectedAscii);
}

@test:Config
isolated function testToCopybookReturningError() returns error? {
Convertor convertor = check new (getCopybookPath("copybook-9"));
Converter converter = check new (getCopybookPath("copybook-9"));
json jsonInput = check io:fileReadJson(getCopybookJsonPath("copybook-9"));
string|Error copybook = convertor.toCopybook(check jsonInput.cloneWithType());
string|Error copybook = converter.toCopybook(check jsonInput.cloneWithType());
if copybook !is Error {
test:assertFail("Expected a 'copybook:Error' but found a 'string'");
}
json expectedErrorDetail = check getErrorDetail("copybook-9");
json actualErrorDetail = check copybook.detail().ensureType();
test:assertEquals(actualErrorDetail.toJson(), expectedErrorDetail);
}

@test:Config
isolated function testDecimalWithoutFraction() returns error? {
Converter converter = check new (getCopybookPath("copybook-10"));
json jsonInput = check io:fileReadJson(getCopybookJsonPath("copybook-10"));
string copybook = check converter.toCopybook(check jsonInput.cloneWithType());
string expectedAscii = check io:fileReadString(getAsciiFilePath("copybook-10"));
test:assertEquals(copybook, expectedAscii);
}
4 changes: 2 additions & 2 deletions ballerina/tests/utils.bal
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ isolated function getCopybookPath(string fileName) returns string {
return string `tests/resources/copybooks/${fileName}.cpy`;
}

isolated function getInputPath(string fileName) returns string {
return string `tests/resources/copybook-inputs/${fileName}.txt`;
isolated function getAsciiFilePath(string fileName) returns string {
return string `tests/resources/copybook-ascii/${fileName}.txt`;
}

isolated function getSchemaPath(string fileName) returns string {
Expand Down
2 changes: 1 addition & 1 deletion ballerina/utils.bal
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ isolated function decimalToString(decimal value) returns string {
}

isolated function externToString(Node node) returns string = @java:Method {
'class: "io.ballerina.lib.copybook.runtime.convertor.Utils"
'class: "io.ballerina.lib.copybook.runtime.converter.Utils"
} external;

isolated function getTypeDefinition(Schema schema, string? targetRecordName) returns Node {
Expand Down
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Fixed
- [[#5783] Fix Incorrect Length Validation in Negative Decimals](https://github.com/ballerina-platform/ballerina-library/issues/5783)
- [[#5848] Fix String Index Out Of Range Error During Decimal to String Conversion](https://github.com/ballerina-platform/ballerina-library/issues/5848)

### Changed
- [[#5849] Rename Copybook Convertor Object to Converter](https://github.com/ballerina-platform/ballerina-library/issues/5849)

## [0.1.2] - 2023-11-15

Expand Down
Loading

0 comments on commit c652283

Please sign in to comment.