mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-05-25 00:38:28 -04:00
Large refactor
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
package io.xpipe.core.charsetter;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public interface Charsettable {
|
||||
|
||||
Charset getCharset();
|
||||
}
|
||||
108
core/src/main/java/io/xpipe/core/charsetter/Charsetter.java
Normal file
108
core/src/main/java/io/xpipe/core/charsetter/Charsetter.java
Normal file
@@ -0,0 +1,108 @@
|
||||
package io.xpipe.core.charsetter;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.*;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class Charsetter {
|
||||
|
||||
private static CharsetterUniverse universe;
|
||||
|
||||
protected static void checkInit() {
|
||||
if (universe == null) {
|
||||
throw new IllegalStateException("Charsetter not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
public static void init(CharsetterContext ctx) {
|
||||
universe = CharsetterUniverse.create(ctx);
|
||||
}
|
||||
|
||||
@Value
|
||||
public static class Result {
|
||||
Charset charset;
|
||||
NewLine newLine;
|
||||
}
|
||||
|
||||
public static Charsetter INSTANCE;
|
||||
|
||||
public static Charsetter get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FailableSupplier<R, E extends Throwable> {
|
||||
R get() throws E;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FailableConsumer<T, E extends Throwable> {
|
||||
|
||||
void accept(T var1) throws E;
|
||||
}
|
||||
|
||||
public abstract Result read(FailableSupplier<InputStream, Exception> in, FailableConsumer<InputStreamReader, Exception> con) throws Exception;
|
||||
|
||||
public NewLine inferNewLine(byte[] content) {
|
||||
Map<NewLine, Integer> count = new HashMap<>();
|
||||
for (var nl : NewLine.values()) {
|
||||
var nlBytes = nl.getNewLine().getBytes(StandardCharsets.UTF_8);
|
||||
count.put(nl, count(content, nlBytes));
|
||||
}
|
||||
|
||||
if (count.values().stream().allMatch(v -> v == 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return count.entrySet().stream().min(Comparator.comparingInt(Map.Entry::getValue))
|
||||
.orElseThrow().getKey();
|
||||
}
|
||||
|
||||
private static int count(byte[] outerArray, byte[] smallerArray) {
|
||||
int count = 0;
|
||||
for(int i = 0; i < outerArray.length - smallerArray.length+1; ++i) {
|
||||
boolean found = true;
|
||||
for(int j = 0; j < smallerArray.length; ++j) {
|
||||
if (outerArray[i+j] != smallerArray[j]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public Charset inferCharset(byte[] content) {
|
||||
checkInit();
|
||||
|
||||
for (Charset c : universe.getCharsets()) {
|
||||
CharsetDecoder decoder = c.newDecoder();
|
||||
decoder.onMalformedInput(CodingErrorAction.REPORT);
|
||||
decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
|
||||
|
||||
ByteBuffer byteBuf = ByteBuffer.wrap(content);
|
||||
CharBuffer charBuf = CharBuffer.allocate(byteBuf.capacity() * 2);
|
||||
|
||||
CoderResult coderResult = decoder.decode(byteBuf, charBuf, false);
|
||||
if (coderResult != null) {
|
||||
if (coderResult.isError()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
return StandardCharsets.UTF_8;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package io.xpipe.core.charsetter;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@Value
|
||||
@AllArgsConstructor
|
||||
public class CharsetterContext {
|
||||
|
||||
public static CharsetterContext empty() {
|
||||
return new CharsetterContext(Charset.defaultCharset().name(), Locale.getDefault(), Locale.getDefault(), List.of());
|
||||
}
|
||||
|
||||
String systemCharsetName;
|
||||
|
||||
Locale systemLocale;
|
||||
|
||||
Locale appLocale;
|
||||
|
||||
List<String> observedCharsets;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package io.xpipe.core.charsetter;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Value
|
||||
@AllArgsConstructor
|
||||
public class CharsetterUniverse {
|
||||
|
||||
List<Charset> charsets;
|
||||
|
||||
public static CharsetterUniverse create(CharsetterContext ctx) {
|
||||
List<Charset> cs = new ArrayList<>();
|
||||
|
||||
cs.add(StandardCharsets.UTF_8);
|
||||
|
||||
var system = Charset.forName(ctx.getSystemCharsetName());
|
||||
cs.add(system);
|
||||
|
||||
// TODO: Locales
|
||||
|
||||
var observed = ctx.getObservedCharsets().stream().map(Charset::forName).toList();
|
||||
cs.addAll(observed);
|
||||
|
||||
return new CharsetterUniverse(cs);
|
||||
}
|
||||
}
|
||||
41
core/src/main/java/io/xpipe/core/charsetter/NewLine.java
Normal file
41
core/src/main/java/io/xpipe/core/charsetter/NewLine.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package io.xpipe.core.charsetter;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public enum NewLine {
|
||||
|
||||
@JsonProperty("lf")
|
||||
LF("\n", "lf"),
|
||||
@JsonProperty("crlf")
|
||||
CRLF("\r\n", "crlf");
|
||||
|
||||
public static NewLine platform() {
|
||||
return Arrays.stream(values())
|
||||
.filter(n -> n.getNewLine().equals(System.getProperty("line.separator")))
|
||||
.findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
public static NewLine id(String id) {
|
||||
return Arrays.stream(values())
|
||||
.filter(n -> n.getId().equalsIgnoreCase(id))
|
||||
.findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
private final String newLine;
|
||||
private final String id;
|
||||
|
||||
NewLine(String newLine, String id) {
|
||||
this.newLine = newLine;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getNewLine() {
|
||||
return newLine;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,13 @@ public class GenericDataStreamParser {
|
||||
}
|
||||
|
||||
private static void parseValue(InputStream in, GenericDataStreamCallback cb) throws IOException {
|
||||
var textual = in.read() != 0;
|
||||
var type = in.read();
|
||||
if (type == DataStructureNodeIO.VALUE_TYPE_NULL) {
|
||||
cb.onValue(null, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var textual = type == DataStructureNodeIO.VALUE_TYPE_TEXT;
|
||||
var size = in.read();
|
||||
var data = in.readNBytes(size);
|
||||
cb.onValue(data, textual);
|
||||
|
||||
@@ -51,10 +51,15 @@ public class GenericDataStreamWriter {
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeValue(OutputStream out, ValueNode value) throws IOException {
|
||||
private static void writeValue(OutputStream out, ValueNode n) throws IOException {
|
||||
out.write(DataStructureNodeIO.GENERIC_VALUE_ID);
|
||||
out.write(value.isTextual() ? 1 : 0);
|
||||
out.write(value.getRawData().length);
|
||||
out.write(value.getRawData());
|
||||
if (n.isNull()) {
|
||||
out.write(DataStructureNodeIO.VALUE_TYPE_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
out.write(n.isTextual() ? DataStructureNodeIO.VALUE_TYPE_TEXT : DataStructureNodeIO.VALUE_TYPE_BARE);
|
||||
out.write(n.getRawData().length);
|
||||
out.write(n.getRawData());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,4 +12,8 @@ public class DataStructureNodeIO {
|
||||
public static final int TYPED_TUPLE_ID = 6;
|
||||
public static final int TYPED_ARRAY_ID = 7;
|
||||
public static final int TYPED_VALUE_ID = 8;
|
||||
|
||||
public static final int VALUE_TYPE_BARE = 0;
|
||||
public static final int VALUE_TYPE_TEXT = 1;
|
||||
public static final int VALUE_TYPE_NULL = 2;
|
||||
}
|
||||
|
||||
@@ -21,9 +21,18 @@ public class MutableValueNode extends ValueNode {
|
||||
|
||||
@Override
|
||||
public String toString(int indent) {
|
||||
if (isNull()) {
|
||||
return "null (M)";
|
||||
}
|
||||
|
||||
return (textual ? "\"" : "") + new String(data) + (textual ? "\"" : "") + " (M)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNull() {
|
||||
return data == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTextual() {
|
||||
return textual;
|
||||
|
||||
@@ -129,7 +129,13 @@ public class TypedDataStreamParser {
|
||||
}
|
||||
|
||||
private void parseValue(InputStream in, TypedDataStreamCallback cb) throws IOException {
|
||||
var textual = in.read() != 0;
|
||||
var type = in.read();
|
||||
if (type == DataStructureNodeIO.VALUE_TYPE_NULL) {
|
||||
cb.onValue(null, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var textual = type == DataStructureNodeIO.VALUE_TYPE_TEXT;
|
||||
var size = in.read();
|
||||
var data = in.readNBytes(size);
|
||||
cb.onValue(data, textual);
|
||||
|
||||
@@ -32,7 +32,12 @@ public class TypedDataStreamWriter {
|
||||
|
||||
private static void writeValue(OutputStream out, ValueNode n) throws IOException {
|
||||
out.write(DataStructureNodeIO.TYPED_VALUE_ID);
|
||||
out.write(n.isTextual() ? 1 : 0);
|
||||
if (n.isNull()) {
|
||||
out.write(DataStructureNodeIO.VALUE_TYPE_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
out.write(n.isTextual() ? DataStructureNodeIO.VALUE_TYPE_TEXT : DataStructureNodeIO.VALUE_TYPE_BARE);
|
||||
out.write(n.getRawData().length);
|
||||
out.write(n.getRawData());
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package io.xpipe.core.dialog;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@AllArgsConstructor
|
||||
public class ConfigParameter {
|
||||
String key;
|
||||
|
||||
@JsonCreator
|
||||
public ConfigParameter(String key) {
|
||||
this.key = key;
|
||||
this.converter = null;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
QueryConverter<?> converter;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> QueryConverter<T> getConverter() {
|
||||
return (QueryConverter<T>) converter;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package io.xpipe.core.dialog;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Value
|
||||
@AllArgsConstructor(onConstructor_={@JsonCreator})
|
||||
public class ConfigParameterSetInstance {
|
||||
|
||||
/**
|
||||
* The available configuration parameters.
|
||||
*/
|
||||
List<ConfigParameter> configParameters;
|
||||
|
||||
/**
|
||||
* The current configuration options that are set.
|
||||
*/
|
||||
Map<String, String> currentValues;
|
||||
|
||||
public ConfigParameterSetInstance(Map<ConfigParameter, Object> map) {
|
||||
configParameters = map.keySet().stream().toList();
|
||||
currentValues = map.entrySet().stream().collect(Collectors.toMap(
|
||||
e -> e.getKey().getKey(),
|
||||
e -> e.getKey().getConverter().convertToString(e.getValue())));
|
||||
}
|
||||
|
||||
public <X, T extends Function<X,?>> ConfigParameterSetInstance(Map<ConfigParameter, T> map, Object v) {
|
||||
configParameters = map.keySet().stream().toList();
|
||||
currentValues = map.entrySet().stream().collect(Collectors.toMap(
|
||||
e -> e.getKey().getKey(),
|
||||
e -> e.getKey().getConverter().convertToString(apply(e.getValue(), v))));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <X, T extends Function<X,?>, V> Object apply(T func, Object v) {
|
||||
return func.apply((X) v);
|
||||
}
|
||||
|
||||
public void update(ConfigParameter p, String val) {
|
||||
currentValues.put(p.getKey(), val);
|
||||
}
|
||||
|
||||
public Map<ConfigParameter, Object> evaluate() {
|
||||
return configParameters.stream().collect(Collectors.toMap(
|
||||
p -> p,
|
||||
p -> p.getConverter().convertFromString(currentValues.get(p.getKey()))));
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package io.xpipe.core.source;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import io.xpipe.core.dialog.ConfigParameter;
|
||||
import io.xpipe.core.dialog.ConfigParameterSetInstance;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Represents the current configuration of a data source.
|
||||
* This configuration can either be in progress or complete.
|
||||
*/
|
||||
@Value
|
||||
@AllArgsConstructor(onConstructor_={@JsonCreator})
|
||||
public class DataSourceConfigInstance {
|
||||
|
||||
public static DataSourceConfigInstance xpbt() {
|
||||
return new DataSourceConfigInstance("xpbt", new ConfigParameterSetInstance(Map.of()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The data source provider id.
|
||||
*/
|
||||
String provider;
|
||||
|
||||
/**
|
||||
* The available configuration parameters.
|
||||
*/
|
||||
ConfigParameterSetInstance configInstance;
|
||||
|
||||
public DataSourceConfigInstance(String provider, Map<ConfigParameter, Object> map) {
|
||||
this.provider = provider;
|
||||
this.configInstance = new ConfigParameterSetInstance(map);
|
||||
}
|
||||
|
||||
public <X, T extends Function<X,?>> DataSourceConfigInstance(String provider, Map<ConfigParameter, T> map, Object val) {
|
||||
this.provider = provider;
|
||||
this.configInstance = new ConfigParameterSetInstance(map, val);
|
||||
}
|
||||
|
||||
public Map<ConfigParameter, Object> evaluate() {
|
||||
return configInstance.evaluate();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ module io.xpipe.core {
|
||||
exports io.xpipe.core.data.node;
|
||||
exports io.xpipe.core.data.typed;
|
||||
exports io.xpipe.core.dialog;
|
||||
exports io.xpipe.core.connection;
|
||||
|
||||
opens io.xpipe.core.store;
|
||||
opens io.xpipe.core.source;
|
||||
@@ -19,6 +18,7 @@ module io.xpipe.core {
|
||||
opens io.xpipe.core.data.node;
|
||||
opens io.xpipe.core.data.typed;
|
||||
opens io.xpipe.core.dialog;
|
||||
exports io.xpipe.core.charsetter;
|
||||
|
||||
requires com.fasterxml.jackson.core;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
|
||||
Reference in New Issue
Block a user