Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataBind CSV Write Support and Code Maintenance #316

Merged
merged 17 commits into from
Jan 17, 2024
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ insert_final_newline = true
indent_style = space
indent_size = 4

[*.{feature, yml}]
[*.{feature,yml}]
indent_style = space
indent_size = 2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ public Map<V, V> aggregateByColumn(@NonNull K columnName, @NonNull K groupColumn

/**
* Returns a string representation of a {@link DataTable}. The output table
* is formatted to align columns and provide a separator line between the
* is formatted to align columns and provides a separator line between the
* header and data rows. The width of each column is determined by the
* length of the longest data value for that column.
*
Expand Down Expand Up @@ -489,4 +489,19 @@ public String toString() {
forEach(row -> table.add(row.values().toString()));
return table.toString();
}

/**
* Converts the {@link DataTable} to a CSV format.
* <p>
* This method uses the {@link TextTable} utility class to format the CSV
* output. The resulting CSV string represents the DataTable in a
* standardized format with aligned columns and a separator line between the
* header and data rows. The width of each column is determined by the
* length of the longest data value for that column.
*
* @return a string representing the DataTable in CSV format
*/
public String toCSV() {
return TextTable.of(this).printCSV();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -95,22 +93,42 @@ public String createFile(final Path filePath) {
* Writes the provided content to a file at the specified path using UTF-8
* encoding.
*
* @param fileContent The content to be written to the file.
* @param filePath The path of the file to which the content
* will be written.
* @param fileContent The content to be written to the file.
* @return The path of the file where the content was
* successfully written.
* @throws DataStreamException If an I/O error occurs while writing the
* content to the file.
*/
public Path writeToFile(final @NonNull String fileContent, final Path filePath) {
public Path writeToFile(final Path filePath, final @NonNull String fileContent) {
try {
return Files.write(filePath, fileContent.getBytes(UTF_8));
} catch (IOException e) {
throw new DataStreamException("Failed to write content to file: " + filePath.toAbsolutePath(), e);
}
}

/**
* Writes the provided content to a file at the specified path using UTF-8
* encoding.
*
* @param filePath The path of the file to which the content
* will be written.
* @param fileContent The content to be written to the file.
* @return The path of the file where the content was
* successfully written.
* @throws DataStreamException If an I/O error occurs while writing the
* content to the file.
*/
public Path writeToFile(final Path filePath, final @NonNull Iterable<? extends CharSequence> fileContent) {
try {
return Files.write(filePath, fileContent, UTF_8);
} catch (IOException e) {
throw new DataStreamException("Failed to write content to file: " + filePath.toAbsolutePath(), e);
}
}

/**
* Copies a file from the source path to the destination path.
*
Expand Down Expand Up @@ -246,11 +264,8 @@ public static OutputStream newOutputStream(Path filePath) {
* be parsed
*/
public URL toURL(String urlStr) {
try {
return new URL(urlStr);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid URL string: " + urlStr, e);
}
return tryURL(urlStr)
.orElseThrow(() -> new IllegalArgumentException("Invalid URL string: " + urlStr));
}

/**
Expand All @@ -264,27 +279,9 @@ public URL toURL(String urlStr) {
*/
public Optional<URL> tryURL(String urlStr) {
try {
return Optional.of(new URL(urlStr));
} catch (MalformedURLException e) {
return Optional.of(new URI(urlStr).toURL());
} catch (Exception e) {
return Optional.empty();
}
}

/**
* Returns a new URI object by parsing the given URI string.
*
* @param uriStr the URI string to be parsed into a URI
* object
* @return the URI object representing the parsed
* URI string
* @throws IllegalArgumentException if the URI string is invalid and cannot
* be parsed
*/
public URI toURI(String uriStr) {
try {
return new URI(uriStr);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid URI string: " + uriStr, e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ public <T> Stream<T> of(final Iterator<? extends T> iterator) {
.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false);
}

/**
* Converts an Iterable to a Stream.
*
* @param iterable The iterable to convert to a stream.
* @param <T> The type of elements in the iterable.
* @return A stream of the iterable.
*/
public static <T> Stream<T> of(final Iterable<T> iterable) {
return StreamSupport.stream(iterable.spliterator(), false);
}

/**
* Returns an OptionalInt that contains the index of the first element in
* the list that matches the given predicate, or an empty OptionalInt if no
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class TextTable<K, V> {
private final DataTable<K, V> table;
Expand Down Expand Up @@ -66,6 +67,27 @@ public String printTable() {
return separator + "\n" + header + "|\n" + separator + "\n" + rows + "\n" + separator + "\n";
}

public String printCSV() {
return Stream.concat(
Stream.of(getCSVRow(table.getColumns())),
table.stream().map(row -> getCSVRow(row.values())))
.collect(Collectors.joining("\n"));
}

private <T> String getCSVRow(Iterable<T> values) {
return Streams.of(values)
.map(Object::toString)
.map(this::escapeCsvValue)
.collect(Collectors.joining(","));
}

private String escapeCsvValue(String value) {
if (value.contains(",") || value.contains("\"") || value.contains("\n")) {
return "\"" + value.replace("\"", "\"\"") + "\"";
}
return value;
}

public String printHtmlTable() {
var htmlTable = new HtmlTable<K, V>();
return htmlTable.buildTable(table);
Expand All @@ -74,13 +96,11 @@ public String printHtmlTable() {
private static class HtmlTable<K, V> {

public String buildTable(DataTable<K, V> table) {
StringBuilder sb = new StringBuilder();
sb.append("<table>\n");
sb.append(buildHeaderRow(table.getFirst()));
sb.append(buildDataRows(table));
sb.append("</table>");

return sb.toString();
return "<table>\n" +
buildHeaderRow(table.getFirst()) +
buildDataRows(table) +
"</table>";
}

private String buildHeaderRow(Map<K, V> row) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package io.github.selcukes.collections;

import lombok.Getter;

import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
Expand All @@ -30,6 +32,8 @@
*/
public class Try<T> {
private final T result;

@Getter
private final Exception exception;

/**
Expand Down Expand Up @@ -168,16 +172,6 @@ public Optional<T> getResult() {
return Optional.ofNullable(result);
}

/**
* Returns the cause of the failure represented by this Try object.
*
* @return the cause of the failure represented by this Try object, or null
* if this Try object represents a success
*/
public Exception getException() {
return exception;
}

/**
* Applies the given function to the result of this Try, which produces a
* new Try. If this Try contains an exception, a new Try containing the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,11 @@ public boolean until(Callable<Boolean> conditionEvaluator) {
stopwatch += pollTimeout;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.error(e, () -> "Interrupted while waiting for condition");
return false;
} catch (Exception e) {
logger.error(e, () -> "Error while evaluating condition");
return false;
}
}
logger.error(() -> "Condition not met within the given time");
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ private ExecResults interactWithProcess(final Process process) {
// Wait for all the tasks to complete.
Await.until(1);
}

return new ExecResults(output.getContent(), error.getContent(), process.exitValue());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.github.selcukes.commons.helper;

import io.github.selcukes.collections.Resources;
import io.github.selcukes.commons.exception.ConfigurationException;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
Expand Down Expand Up @@ -358,7 +359,7 @@ public String downloadToUsersFolder(final String url) {
if (file.exists()) {
return file.getPath();
}
download(new URL(url), file);
download(Resources.toURL(url), file);
return file.getPath();
}

Expand All @@ -369,8 +370,8 @@ public String downloadToUsersFolder(final String url) {
* @return The content of the file.
*/
public String readContent(final String filePath) {
try {
return new String(loadResourceFromJar(filePath).readAllBytes(), StandardCharsets.UTF_8);
try (var inputStream = loadResourceFromJar(filePath)) {
return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
} catch (Exception e) {
throw new ConfigurationException(String.format("Cannot load [%s] from classpath", filePath));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,6 @@ private String encode(String value) {
private URI buildUri() {
var joiner = new StringJoiner("&");
queryParams.forEach((key, value) -> joiner.add(encode(key) + "=" + encode(value)));
return Resources.toURI(baseUri + endpoint + (baseUri.contains("?") ? "&" : "?") + joiner);
return URI.create(baseUri + endpoint + (baseUri.contains("?") ? "&" : "?") + joiner);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
* It takes the HTTP response and provides a number of methods to access the
* response body, headers, and status code
*/
@Getter
public class WebResponse {
@Getter
private final HttpResponse<String> httpResponse;

public WebResponse(final HttpResponse<String> httpResponse) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum Architecture {
X32(32),
X64(64);

@Getter
final int value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import org.openqa.selenium.os.ExternalProcess;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -89,15 +88,15 @@ public SeleniumService start(String mode, String... extraFlags) {
process = builder.start();

try {
var url = new URL(baseUrl + "/status");
var url = Resources.toURL(baseUrl + "/status");
new UrlChecker().waitUntilAvailable(10, SECONDS, url);
logger.info(() -> "Selenium Server is ready...");
} catch (UrlChecker.TimeoutException e) {
logger.error(() -> "Server failed to start: " + e.getMessage());
process.shutdown();
process = null;
throw new DriverConnectionException(e);
} catch (MalformedURLException e) {
} catch (Exception e) {
throw new DriverConnectionException(e);
}

Expand All @@ -123,7 +122,7 @@ public void stop() {
*/
@SneakyThrows
public URL getServiceUrl() {
return new URL(baseUrl);
return Resources.toURL(baseUrl);
}

/**
Expand All @@ -135,10 +134,10 @@ public URL getServiceUrl() {
@SneakyThrows
public String getServerJar() {
var seleniumServerJar = ConfigFactory.getConfig().getWeb().getServerJar();
var serverJarUrl = new URL(seleniumServerJar);
var reportsPath = ofNullable(ConfigFactory.getConfig().getReports())
var serverJarUrl = Resources.toURL(seleniumServerJar);
var reportPath = ofNullable(ConfigFactory.getConfig().getReports())
.map(reports -> reports.get("path")).orElse("target");
var serverJarPath = Resources.of(reportsPath + "/selenium-server.jar");
var serverJarPath = Resources.of(reportPath + "/selenium-server.jar");
FileHelper.download(serverJarUrl, serverJarPath.toFile());
return serverJarPath.toAbsolutePath().toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,14 @@ public Object selected(Select select, String optionLocator) {
return type.getRetriever().apply(select);
}

@Getter
@AllArgsConstructor
enum SelectionType {
LABEL(Select::selectByVisibleText, select -> select.getFirstSelectedOption().getText()),
VALUE(Select::selectByValue, select -> select.getFirstSelectedOption().getAttribute(ATTRIBUTE)),
INDEX((select, value) -> select.selectByIndex(parseInt(value)),
select -> select.getOptions().indexOf(select.getFirstSelectedOption()));
@Getter
private final BiConsumer<Select, String> selector;
@Getter
private final Function<Select, Object> retriever;

}
Expand Down
Loading
Loading