Skip to content

Commit

Permalink
Merge pull request #346 from ballerina-platform/csverror
Browse files Browse the repository at this point in the history
Fix csv parsing logic
  • Loading branch information
NipunaRanasinghe authored May 29, 2024
2 parents 2ee27fc + 41a23b6 commit 9786f34
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 35 deletions.
6 changes: 6 additions & 0 deletions ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ path = "../native/build/libs/salesforce-native-8.0.1-SNAPSHOT.jar"
groupId = "io.ballerinax"
artifactId = "salesforce"
version = "8.0.1-SNAPSHOT"

[[platform.java17.dependency]]
groupId = "com.opencsv"
artifactId = "opencsv"
version = "5.9"
path = "./lib/opencsv-5.9.jar"
6 changes: 3 additions & 3 deletions ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

[ballerina]
dependencies-toml-version = "2"
distribution-version = "2201.8.5"
distribution-version = "2201.8.4"

[[package]]
org = "ballerina"
Expand Down Expand Up @@ -61,7 +61,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "http"
version = "2.10.12"
version = "2.10.13"
dependencies = [
{org = "ballerina", name = "auth"},
{org = "ballerina", name = "cache"},
Expand Down Expand Up @@ -289,7 +289,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "observe"
version = "1.2.2"
version = "1.2.3"
dependencies = [
{org = "ballerina", name = "jballerina.java"}
]
Expand Down
10 changes: 10 additions & 0 deletions ballerina/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,19 @@ task updateTomlFiles {
doLast {
def newConfig = ballerinaTomlFilePlaceHolder.text.replace('@project.version@', project.version.toString())
newConfig = newConfig.replace('@toml.version@', tomlVersion)
newConfig = newConfig.replace("@opencsv.version@", openCsvVersion)
ballerinaTomlFile.text = newConfig
}
}

configurations {
externalJars
}

dependencies {
externalJars(group: 'com.opencsv', name: 'opencsv', version: '5.9')
}

task commitTomlFiles {
doLast {
project.exec {
Expand Down Expand Up @@ -93,6 +102,7 @@ clean {
delete 'build'
}

updateTomlFiles.dependsOn copyStdlibs
build.dependsOn ":${project.packageName}-native:build"
build.dependsOn "generatePomFileForMavenPublication"
publishToMavenLocal.dependsOn build
Expand Down
4 changes: 2 additions & 2 deletions ballerina/client.bal
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ public isolated client class Client {
if textPayload == "" {
return [];
}
string[][] result = check convertStringToStringList(textPayload);
string[][] result = check parseCsvString(textPayload);
return result;
} else {
json responsePayload = check response.getJsonPayload();
Expand All @@ -663,7 +663,7 @@ public isolated client class Client {
if textPayload == "" {
return [];
}
string[][] result = check convertStringToStringList(textPayload);
string[][] result = check parseCsvString(textPayload);
return result;
} else {
json responsePayload = check response.getJsonPayload();
Expand Down
35 changes: 12 additions & 23 deletions ballerina/utils.bal
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,26 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import ballerina/io;
import ballerina/log;
import ballerina/time;
import ballerina/io;
import ballerina/jballerina.java;
import ballerina/lang.'string as strings;

isolated string csvContent = EMPTY_STRING;

# Remove decimal places from a civil seconds value
#
#
# + civilTime - a time:civil record
# + return - a time:civil record with decimal places removed
#
#
isolated function removeDecimalPlaces(time:Civil civilTime) returns time:Civil {
time:Civil result = civilTime;
time:Seconds seconds= (result.second is ())? 0 : <time:Seconds>result.second;
time:Seconds seconds = (result.second is ()) ? 0 : <time:Seconds>result.second;
decimal floor = decimal:floor(seconds);
result.second = floor;
return result;
}

}

# Convert ReadableByteChannel to string.
#
Expand Down Expand Up @@ -65,7 +64,6 @@ isolated function convertToString(io:ReadableByteChannel rbc) returns string|err
return textContent;
}


# Convert string[][] to string.
#
# + stringCsvInput - Multi dimentional array of strings
Expand All @@ -77,15 +75,15 @@ isolated function convertStringListToString(string[][]|stream<string[], error?>
if stringCsvInput is string[][] {
foreach var row in stringCsvInput {
lock {
csvContent += row.reduce(isolated function (string s, string t) returns string {
csvContent += row.reduce(isolated function(string s, string t) returns string {
return s.concat(",", t);
}, EMPTY_STRING).substring(1) + NEW_LINE;
}
}
} else {
check stringCsvInput.forEach(isolated function(string[] row) {
lock {
csvContent += row.reduce(isolated function (string s, string t) returns string {
csvContent += row.reduce(isolated function(string s, string t) returns string {
return s.concat(",", t);
}, EMPTY_STRING).substring(1) + NEW_LINE;

Expand All @@ -97,16 +95,7 @@ isolated function convertStringListToString(string[][]|stream<string[], error?>
}
}

isolated function convertStringToStringList(string content) returns string[][]|error {
string[][] result = [];
string[] lines = re `\n`.split(content);
foreach string item in lines {
string processedItem = re `"`.replaceAll(item, EMPTY_STRING);
if item == "" {
continue;
}
string[] row = re `,`.split(processedItem);
result.push(row);
}
return result;
};
isolated function parseCsvString(string stringContent) returns string[][]|error = @java:Method {
'class: "io.ballerinax.salesforce.CsvParserUtils",
name: "parseCsvToStringArray"
} external;
6 changes: 6 additions & 0 deletions build-config/resources/Ballerina.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ path = "../native/build/libs/[email protected]@.jar"
groupId = "io.ballerinax"
artifactId = "salesforce"
version = "@project.version@"

[[platform.java17.dependency]]
groupId = "com.opencsv"
artifactId = "opencsv"
version = "@opencsv.version@"
path = "./lib/[email protected]@.jar"
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ shadowJarPluginVersion=8.1.1
downloadPluginVersion=5.4.0
releasePluginVersion=2.8.0
testngVersion=7.6.1
openCsvVersion=5.9
ballerinaGradlePluginVersion=2.2.3

ballerinaLangVersion=2201.8.4
1 change: 1 addition & 0 deletions native/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies {

checkstyle project(":checkstyle")
checkstyle "com.puppycrawl.tools:checkstyle:${checkstylePluginVersion}"
implementation "com.opencsv:opencsv:${openCsvVersion}"
implementation group: 'org.ballerinalang', name: 'ballerina-runtime', version: "${ballerinaLangVersion}"

}
Expand Down
59 changes: 59 additions & 0 deletions native/src/main/java/io/ballerinax/salesforce/CsvParserUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* 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.
*/

package io.ballerinax.salesforce;

import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvException;
import io.ballerina.runtime.api.creators.ErrorCreator;
import io.ballerina.runtime.api.creators.TypeCreator;
import io.ballerina.runtime.api.creators.ValueCreator;
import io.ballerina.runtime.api.types.ArrayType;
import io.ballerina.runtime.api.utils.StringUtils;
import io.ballerina.runtime.api.values.BArray;
import io.ballerina.runtime.api.values.BString;

import java.io.IOException;
import java.io.StringReader;
import java.util.List;

/**
* This class holds the utility methods involved with parsing csv content.
*
* @since 8.0.1
*/
public class CsvParserUtils {
public static Object parseCsvToStringArray(BString csvData) {
try (CSVReader reader = new CSVReader(new StringReader(csvData.getValue()))) {
List<String[]> records = reader.readAll();

// Convert each row in records to BArray
BArray[] bArrayData = new BArray[records.size()];
for (int i = 0; i < records.size(); i++) {
String[] row = records.get(i);
BArray bArrayRow = StringUtils.fromStringArray(row);
bArrayData[i] = bArrayRow;
}
BArray emptyBArray = StringUtils.fromStringArray(new String[0]);
ArrayType stringArrayType = TypeCreator.createArrayType(emptyBArray.getType());
return ValueCreator.createArrayValue(bArrayData, stringArrayType); // string[][]
} catch (IOException | CsvException e) {
return ErrorCreator.createError(StringUtils.fromString(e.getMessage()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ public static Object getRecord(Environment env, BObject client, BString path, BT
return invokeClientMethod(env, client, "processGetRecord", paramFeed);
}

public static Object getInvocableActions(Environment env, BObject client, BString subContext,
BTypedesc targetType) {
public static Object getInvocableActions(Environment env, BObject client, BString subContext,
BTypedesc targetType) {
Object[] paramFeed = {targetType, true, subContext, true};
return invokeClientMethod(env, client, "processGetInvocableActions", paramFeed);
}

public static Object invokeActions(Environment env, BObject client, BString subContext, BMap<BString, ?> payload,
BTypedesc targetType) {
BTypedesc targetType) {
Object[] paramFeed = {targetType, true, subContext, true, payload, true};
return invokeClientMethod(env, client, "processInvokeActions", paramFeed);
}
Expand All @@ -71,14 +71,14 @@ public static Object getRecordById(Environment env, BObject client, BString sobj
}

public static Object getNamedLayouts(Environment env, BObject client, BString sObject, BString name,
BTypedesc targetType) {
BTypedesc targetType) {
Object[] paramFeed = {targetType, true, sObject, true, name, true};
return invokeClientMethod(env, client, "processGetNamedLayouts", paramFeed);
}

public static Object apexRestExecute(Environment env, BObject client, BString urlPath,
BString methodType, BMap<BString, ?> payload,
BTypedesc targetType) {
public static Object apexRestExecute(Environment env, BObject client, BString urlPath,
BString methodType, BMap<BString, ?> payload,
BTypedesc targetType) {
Object[] paramFeed = {targetType, true, urlPath, true, methodType, true, payload, true};
return invokeClientMethod(env, client, "processApexExecute", paramFeed);
}
Expand Down
1 change: 1 addition & 0 deletions native/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@

module io.ballerinax.salesforce {
requires io.ballerina.runtime;
requires com.opencsv;
exports io.ballerinax.salesforce;
}

0 comments on commit 9786f34

Please sign in to comment.