mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
Add textual flag to value node, prepare for text data sources, and various other small fixes
This commit is contained in:
parent
c7c86b1bf8
commit
7dec1afdb4
43 changed files with 414 additions and 128 deletions
|
@ -59,7 +59,7 @@ public class DataTableImpl extends DataSourceImpl implements DataTable {
|
||||||
List<DataStructureNode> nodes = new ArrayList<>();
|
List<DataStructureNode> nodes = new ArrayList<>();
|
||||||
XPipeConnection.execute(con -> {
|
XPipeConnection.execute(con -> {
|
||||||
var req = QueryTableDataExchange.Request.builder()
|
var req = QueryTableDataExchange.Request.builder()
|
||||||
.id(getId()).maxRows(maxRows).build();
|
.ref(DataSourceReference.id(getId())).maxRows(maxRows).build();
|
||||||
con.performInputExchange(req, (QueryTableDataExchange.Response res, InputStream in) -> {
|
con.performInputExchange(req, (QueryTableDataExchange.Response res, InputStream in) -> {
|
||||||
var r = new TypedDataStreamParser(info.getDataType());
|
var r = new TypedDataStreamParser(info.getDataType());
|
||||||
r.parseStructures(in, TypedDataStructureNodeReader.immutable(info.getDataType()), nodes::add);
|
r.parseStructures(in, TypedDataStructureNodeReader.immutable(info.getDataType()), nodes::add);
|
||||||
|
@ -82,7 +82,7 @@ public class DataTableImpl extends DataSourceImpl implements DataTable {
|
||||||
|
|
||||||
connection = XPipeConnection.open();
|
connection = XPipeConnection.open();
|
||||||
var req = QueryTableDataExchange.Request.builder()
|
var req = QueryTableDataExchange.Request.builder()
|
||||||
.id(getId()).build();
|
.ref(DataSourceReference.id(getId())).build();
|
||||||
connection.sendRequest(req);
|
connection.sendRequest(req);
|
||||||
connection.receiveResponse();
|
connection.receiveResponse();
|
||||||
connection.receiveBody();
|
connection.receiveBody();
|
||||||
|
|
|
@ -138,6 +138,11 @@ public class BeaconClient implements AutoCloseable {
|
||||||
System.out.println("Sending request to server of type " + req.getClass().getName());
|
System.out.println("Sending request to server of type " + req.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BeaconConfig.debugEnabled()) {
|
||||||
|
System.out.println("Sending raw request:");
|
||||||
|
System.out.println(msg.toPrettyString());
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var mapper = JacksonHelper.newMapper().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
var mapper = JacksonHelper.newMapper().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||||
var gen = mapper.createGenerator(socket.getOutputStream());
|
var gen = mapper.createGenerator(socket.getOutputStream());
|
||||||
|
|
|
@ -43,7 +43,8 @@ public class ReadPreparationExchange implements MessageExchange<ReadPreparationE
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {
|
||||||
|
String determinedType;
|
||||||
|
|
||||||
DataSourceConfigInstance config;
|
DataSourceConfigInstance config;
|
||||||
StreamDataStore store;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package io.xpipe.beacon.exchange.api;
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.beacon.message.RequestMessage;
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
import io.xpipe.beacon.message.ResponseMessage;
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
@ -34,7 +34,7 @@ public class QueryTableDataExchange implements MessageExchange<QueryTableDataExc
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {
|
||||||
@NonNull
|
@NonNull
|
||||||
DataSourceId id;
|
DataSourceReference ref;
|
||||||
|
|
||||||
int maxRows;
|
int maxRows;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package io.xpipe.beacon.exchange.api;
|
||||||
|
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
|
import io.xpipe.beacon.message.RequestMessage;
|
||||||
|
import io.xpipe.beacon.message.ResponseMessage;
|
||||||
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.Value;
|
||||||
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
public class QueryTextDataExchange implements MessageExchange<QueryTextDataExchange.Request, QueryTextDataExchange.Response> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "queryTextData";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<QueryTextDataExchange.Request> getRequestClass() {
|
||||||
|
return QueryTextDataExchange.Request.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<QueryTextDataExchange.Response> getResponseClass() {
|
||||||
|
return QueryTextDataExchange.Response.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Jacksonized
|
||||||
|
@Builder
|
||||||
|
@Value
|
||||||
|
public static class Request implements RequestMessage {
|
||||||
|
@NonNull
|
||||||
|
DataSourceReference ref;
|
||||||
|
|
||||||
|
int maxLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Jacksonized
|
||||||
|
@Builder
|
||||||
|
@Value
|
||||||
|
public static class Response implements ResponseMessage {
|
||||||
|
}
|
||||||
|
}
|
14
core/src/main/java/io/xpipe/core/config/ConfigOption.java
Normal file
14
core/src/main/java/io/xpipe/core/config/ConfigOption.java
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package io.xpipe.core.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
@Value
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor(onConstructor_={@JsonCreator})
|
||||||
|
public class ConfigOption {
|
||||||
|
String name;
|
||||||
|
String key;
|
||||||
|
}
|
23
core/src/main/java/io/xpipe/core/config/ConfigOptionSet.java
Normal file
23
core/src/main/java/io/xpipe/core/config/ConfigOptionSet.java
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package io.xpipe.core.config;
|
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Singular;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Value
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor(onConstructor_={@JsonCreator})
|
||||||
|
public class ConfigOptionSet {
|
||||||
|
|
||||||
|
public static ConfigOptionSet empty() {
|
||||||
|
return new ConfigOptionSet(List.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singular
|
||||||
|
List<ConfigOption> options;
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package io.xpipe.core.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Value
|
||||||
|
@AllArgsConstructor(onConstructor_={@JsonCreator})
|
||||||
|
public class ConfigOptionSetInstance {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The available configuration options.
|
||||||
|
*/
|
||||||
|
ConfigOptionSet configOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current configuration options that are set.
|
||||||
|
*/
|
||||||
|
Map<String, String> currentValues;
|
||||||
|
|
||||||
|
public boolean isComplete() {
|
||||||
|
return currentValues.size() == configOptions.getOptions().size();
|
||||||
|
}
|
||||||
|
}
|
|
@ -127,9 +127,9 @@ public class GenericArrayReader implements GenericAbstractReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValue(byte[] value) {
|
public void onValue(byte[] value, boolean textual) {
|
||||||
if (currentReader != null) {
|
if (currentReader != null) {
|
||||||
currentReader.onValue(value);
|
currentReader.onValue(value, textual);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ public class GenericArrayReader implements GenericAbstractReader {
|
||||||
throw new IllegalStateException("Array is full but got another value");
|
throw new IllegalStateException("Array is full but got another value");
|
||||||
}
|
}
|
||||||
|
|
||||||
put(ValueNode.mutable(value));
|
put(ValueNode.mutable(value, textual));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,6 +17,6 @@ public interface GenericDataStreamCallback {
|
||||||
default void onTupleEnd() {
|
default void onTupleEnd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
default void onValue(byte[] value) {
|
default void onValue(byte[] value, boolean textual) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,9 @@ public class GenericDataStreamParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseValue(InputStream in, GenericDataStreamCallback cb) throws IOException {
|
private static void parseValue(InputStream in, GenericDataStreamCallback cb) throws IOException {
|
||||||
|
var textual = in.read() != 0;
|
||||||
var size = in.read();
|
var size = in.read();
|
||||||
var data = in.readNBytes(size);
|
var data = in.readNBytes(size);
|
||||||
cb.onValue(data);
|
cb.onValue(data, textual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ public class GenericDataStreamWriter {
|
||||||
|
|
||||||
private static void writeValue(OutputStream out, ValueNode value) throws IOException {
|
private static void writeValue(OutputStream out, ValueNode value) throws IOException {
|
||||||
out.write(DataStructureNodeIO.GENERIC_VALUE_ID);
|
out.write(DataStructureNodeIO.GENERIC_VALUE_ID);
|
||||||
|
out.write(value.isTextual() ? 1 : 0);
|
||||||
out.write(value.getRawData().length);
|
out.write(value.getRawData().length);
|
||||||
out.write(value.getRawData());
|
out.write(value.getRawData());
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,12 +78,12 @@ public class GenericDataStructureNodeReader implements GenericDataStreamCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValue(byte[] value) {
|
public void onValue(byte[] value, boolean textual) {
|
||||||
if (hasReader()) {
|
if (hasReader()) {
|
||||||
reader.onValue(value);
|
reader.onValue(value, textual);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = ValueNode.mutable(value);
|
node = ValueNode.mutable(value, textual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,9 +139,9 @@ public class GenericTupleReader implements GenericAbstractReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValue(byte[] value) {
|
public void onValue(byte[] value, boolean textual) {
|
||||||
if (currentReader != null) {
|
if (currentReader != null) {
|
||||||
currentReader.onValue(value);
|
currentReader.onValue(value, textual);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ public class GenericTupleReader implements GenericAbstractReader {
|
||||||
throw new IllegalStateException("Tuple is full but got another value");
|
throw new IllegalStateException("Tuple is full but got another value");
|
||||||
}
|
}
|
||||||
|
|
||||||
putNode(ValueNode.mutable(value));
|
putNode(ValueNode.mutable(value, textual));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -51,12 +51,20 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
|
||||||
throw unsupported("clear");
|
throw unsupported("clear");
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataStructureNode setRawData(byte[] data) {
|
public boolean isTextual() {
|
||||||
|
throw unsupported("textual check");
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataStructureNode setRaw(byte[] data) {
|
||||||
throw unsupported("set raw data");
|
throw unsupported("set raw data");
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataStructureNode setNull() {
|
public DataStructureNode set(Object newValue) {
|
||||||
throw unsupported("set null");
|
throw unsupported("set");
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataStructureNode set(Object newValue, boolean textual) {
|
||||||
|
throw unsupported("set");
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataStructureNode set(int index, DataStructureNode node) {
|
public DataStructureNode set(int index, DataStructureNode node) {
|
||||||
|
|
|
@ -3,14 +3,16 @@ package io.xpipe.core.data.node;
|
||||||
public class ImmutableValueNode extends ValueNode {
|
public class ImmutableValueNode extends ValueNode {
|
||||||
|
|
||||||
private final byte[] data;
|
private final byte[] data;
|
||||||
|
private final boolean textual;
|
||||||
|
|
||||||
ImmutableValueNode(byte[] data) {
|
ImmutableValueNode(byte[] data, boolean textual) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.textual = textual;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(int indent) {
|
public String toString(int indent) {
|
||||||
return new String(data) + "(I)";
|
return (textual ? "\"" : "") + new String(data) + (textual ? "\"" : "") + " (I)";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,11 +27,26 @@ public class ImmutableValueNode extends ValueNode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueNode mutableCopy() {
|
public ValueNode mutableCopy() {
|
||||||
return ValueNode.mutable(data);
|
return ValueNode.mutable(data, textual);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataStructureNode setRawData(byte[] data) {
|
public boolean isTextual() {
|
||||||
|
return textual;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataStructureNode setRaw(byte[] data) {
|
||||||
|
throw new UnsupportedOperationException("Value node is immutable");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataStructureNode set(Object newValue) {
|
||||||
|
throw new UnsupportedOperationException("Value node is immutable");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataStructureNode set(Object newValue, boolean textual) {
|
||||||
throw new UnsupportedOperationException("Value node is immutable");
|
throw new UnsupportedOperationException("Value node is immutable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,27 @@
|
||||||
package io.xpipe.core.data.node;
|
package io.xpipe.core.data.node;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
public class MutableValueNode extends ValueNode {
|
public class MutableValueNode extends ValueNode {
|
||||||
|
|
||||||
private byte[] data;
|
static final MutableValueNode NULL = new MutableValueNode(null, false);
|
||||||
|
|
||||||
MutableValueNode(byte[] data) {
|
private byte[] data;
|
||||||
|
private boolean textual;
|
||||||
|
|
||||||
|
MutableValueNode(byte[] data, boolean textual) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.textual = textual;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(int indent) {
|
public String toString(int indent) {
|
||||||
return new String(data) + "(M)";
|
return (textual ? "\"" : "") + new String(data) + (textual ? "\"" : "") + " (M)";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTextual() {
|
||||||
|
return textual;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -20,20 +31,49 @@ public class MutableValueNode extends ValueNode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueNode immutableView() {
|
public ValueNode immutableView() {
|
||||||
return new ImmutableValueNode(data);
|
return new ImmutableValueNode(data, textual);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueNode mutableCopy() {
|
public ValueNode mutableCopy() {
|
||||||
return new MutableValueNode(data);
|
return new MutableValueNode(data, textual);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataStructureNode setRawData(byte[] data) {
|
public DataStructureNode setRaw(byte[] data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataStructureNode set(Object newValue) {
|
||||||
|
if (newValue == null) {
|
||||||
|
this.data = null;
|
||||||
|
this.textual = false;
|
||||||
|
} else {
|
||||||
|
setRaw(newValue.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataStructureNode set(Object newValue, boolean textual) {
|
||||||
|
if (newValue == null && textual) {
|
||||||
|
throw new IllegalArgumentException("Can't set a textual null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newValue == null) {
|
||||||
|
this.data = null;
|
||||||
|
this.textual = false;
|
||||||
|
} else {
|
||||||
|
setRaw(newValue.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
this.textual = textual;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] getRawData() {
|
public byte[] getRawData() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,6 @@ import java.util.Arrays;
|
||||||
|
|
||||||
public abstract class ValueNode extends DataStructureNode {
|
public abstract class ValueNode extends DataStructureNode {
|
||||||
|
|
||||||
private static final byte[] NULL = new byte[]{0};
|
|
||||||
|
|
||||||
protected ValueNode() {
|
protected ValueNode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,40 +29,57 @@ public abstract class ValueNode extends DataStructureNode {
|
||||||
@Override
|
@Override
|
||||||
public abstract ValueNode mutableCopy();
|
public abstract ValueNode mutableCopy();
|
||||||
|
|
||||||
public static ValueNode immutable(byte[] data) {
|
public static ValueNode immutable(byte[] data, boolean textual) {
|
||||||
return new ImmutableValueNode(data);
|
return new ImmutableValueNode(data, textual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueNode immutable(Object o) {
|
public static ValueNode immutable(Object o, boolean textual) {
|
||||||
return immutable(o.toString().getBytes(StandardCharsets.UTF_8));
|
return immutable(o.toString().getBytes(StandardCharsets.UTF_8), textual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ValueNode immutableNull() {
|
||||||
|
return MutableValueNode.NULL.immutableView();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueNode mutableNull() {
|
public static ValueNode mutableNull() {
|
||||||
return mutable(NULL);
|
return MutableValueNode.NULL.mutableCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueNode nullValue() {
|
public static ValueNode mutable(byte[] data, boolean textual) {
|
||||||
return mutable(NULL);
|
return new MutableValueNode(data, textual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueNode mutable(byte[] data) {
|
public static ValueNode mutable(Object o, boolean textual) {
|
||||||
return new MutableValueNode(data);
|
return mutable(o.toString().getBytes(StandardCharsets.UTF_8), textual);
|
||||||
}
|
|
||||||
|
|
||||||
public static ValueNode mutable(Object o) {
|
|
||||||
return mutable(o.toString().getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueNode of(byte[] data) {
|
public static ValueNode of(byte[] data) {
|
||||||
return mutable(data);
|
return mutable(data, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueNode of(Object o) {
|
public static ValueNode of(Object o) {
|
||||||
return mutable(o);
|
return mutable(o, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ValueNode ofText(byte[] data) {
|
||||||
|
return mutable(data, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ValueNode ofText(Object o) {
|
||||||
|
return mutable(o, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract DataStructureNode setRawData(byte[] data);
|
public abstract boolean isTextual();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract DataStructureNode setRaw(byte[] data);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract DataStructureNode set(Object newValue);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract DataStructureNode set(Object newValue, boolean textual);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int asInt() {
|
public final int asInt() {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import io.xpipe.core.data.type.TupleType;
|
||||||
|
|
||||||
public interface TypedDataStreamCallback {
|
public interface TypedDataStreamCallback {
|
||||||
|
|
||||||
default void onValue(byte[] data) {
|
default void onValue(byte[] data, boolean textual) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default void onGenericNode(DataStructureNode node) {
|
default void onGenericNode(DataStructureNode node) {
|
||||||
|
|
|
@ -129,8 +129,9 @@ public class TypedDataStreamParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseValue(InputStream in, TypedDataStreamCallback cb) throws IOException {
|
private void parseValue(InputStream in, TypedDataStreamCallback cb) throws IOException {
|
||||||
|
var textual = in.read() != 0;
|
||||||
var size = in.read();
|
var size = in.read();
|
||||||
var data = in.readNBytes(size);
|
var data = in.readNBytes(size);
|
||||||
cb.onValue(data);
|
cb.onValue(data, textual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ public class TypedDataStreamWriter {
|
||||||
|
|
||||||
private static void writeValue(OutputStream out, ValueNode n) throws IOException {
|
private static void writeValue(OutputStream out, ValueNode n) throws IOException {
|
||||||
out.write(DataStructureNodeIO.TYPED_VALUE_ID);
|
out.write(DataStructureNodeIO.TYPED_VALUE_ID);
|
||||||
|
out.write(n.isTextual() ? 1 : 0);
|
||||||
out.write(n.getRawData().length);
|
out.write(n.getRawData().length);
|
||||||
out.write(n.getRawData());
|
out.write(n.getRawData());
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,12 +81,12 @@ public class TypedDataStructureNodeReader implements TypedAbstractReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValue(byte[] data) {
|
public void onValue(byte[] data, boolean textual) {
|
||||||
if (!expectedType.isValue()) {
|
if (!expectedType.isValue()) {
|
||||||
throw new IllegalStateException("Expected " + expectedType.getName() + " but got value");
|
throw new IllegalStateException("Expected " + expectedType.getName() + " but got value");
|
||||||
}
|
}
|
||||||
|
|
||||||
var val = makeImmutable ? ValueNode.immutable(data) : ValueNode.mutable(data);
|
var val = makeImmutable ? ValueNode.immutable(data, textual) : ValueNode.mutable(data, textual);
|
||||||
finishNode(val);
|
finishNode(val);
|
||||||
moveExpectedType(false);
|
moveExpectedType(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,16 +47,16 @@ public class TypedReusableDataStructureNodeReader implements TypedAbstractReader
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onValue(byte[] data) {
|
public void onValue(byte[] data, boolean textual) {
|
||||||
if (!initialized()) {
|
if (!initialized()) {
|
||||||
initialReader.onValue(data);
|
initialReader.onValue(data, textual);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInArray()) {
|
if (isInArray()) {
|
||||||
getCurrentParent().set(indices.peek(), ValueNode.mutable(data));
|
getCurrentParent().set(indices.peek(), ValueNode.mutable(data, textual));
|
||||||
} else {
|
} else {
|
||||||
getCurrent().setRawData(data);
|
getCurrent().setRaw(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!indices.isEmpty()) {
|
if (!indices.isEmpty()) {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package io.xpipe.core.source;
|
package io.xpipe.core.source;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import io.xpipe.core.config.ConfigOptionSet;
|
||||||
|
import io.xpipe.core.config.ConfigOptionSetInstance;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -12,13 +13,11 @@ import java.util.Map;
|
||||||
* This configuration can either be in progress or complete.
|
* This configuration can either be in progress or complete.
|
||||||
*/
|
*/
|
||||||
@Value
|
@Value
|
||||||
@Builder
|
@AllArgsConstructor(onConstructor_={@JsonCreator})
|
||||||
@Jacksonized
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class DataSourceConfigInstance {
|
public class DataSourceConfigInstance {
|
||||||
|
|
||||||
public static DataSourceConfigInstance xpbt() {
|
public static DataSourceConfigInstance xpbt() {
|
||||||
return new DataSourceConfigInstance("xpbt", DataSourceConfigOptions.empty(), Map.of());
|
return new DataSourceConfigInstance("xpbt", ConfigOptionSet.empty(), Map.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,7 +28,7 @@ public class DataSourceConfigInstance {
|
||||||
/**
|
/**
|
||||||
* The available configuration options.
|
* The available configuration options.
|
||||||
*/
|
*/
|
||||||
DataSourceConfigOptions configOptions;
|
ConfigOptionSet configOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current configuration options that are set.
|
* The current configuration options that are set.
|
||||||
|
@ -39,4 +38,10 @@ public class DataSourceConfigInstance {
|
||||||
public boolean isComplete() {
|
public boolean isComplete() {
|
||||||
return currentValues.size() == configOptions.getOptions().size();
|
return currentValues.size() == configOptions.getOptions().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DataSourceConfigInstance(String provider, ConfigOptionSetInstance cInstance) {
|
||||||
|
this.provider = provider;
|
||||||
|
this.configOptions = cInstance.getConfigOptions();
|
||||||
|
this.currentValues = cInstance.getCurrentValues();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
package io.xpipe.core.source;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Singular;
|
|
||||||
import lombok.Value;
|
|
||||||
import lombok.extern.jackson.Jacksonized;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Value
|
|
||||||
@Builder
|
|
||||||
@Jacksonized
|
|
||||||
public class DataSourceConfigOptions {
|
|
||||||
|
|
||||||
public static DataSourceConfigOptions empty() {
|
|
||||||
return new DataSourceConfigOptions(List.of());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Singular
|
|
||||||
List<Option> options;
|
|
||||||
|
|
||||||
@Value
|
|
||||||
@Builder
|
|
||||||
@Jacksonized
|
|
||||||
@AllArgsConstructor
|
|
||||||
public static class Option {
|
|
||||||
String name;
|
|
||||||
String key;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -31,4 +31,8 @@ public interface DataSourceDescriptor<DS extends DataStore> {
|
||||||
* Returns the general data source type.
|
* Returns the general data source type.
|
||||||
*/
|
*/
|
||||||
DataSourceType getType();
|
DataSourceType getType();
|
||||||
|
|
||||||
|
DataSourceReadConnection openReadConnection(DS store) throws Exception;
|
||||||
|
|
||||||
|
DataSourceConnection openWriteConnection(DS store) throws Exception;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,11 +67,14 @@ public abstract class DataSourceInfo {
|
||||||
@Value
|
@Value
|
||||||
@JsonTypeName("text")
|
@JsonTypeName("text")
|
||||||
public static class Text extends DataSourceInfo {
|
public static class Text extends DataSourceInfo {
|
||||||
Charset encoding;
|
Charset charset;
|
||||||
|
|
||||||
|
int lineCount;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public Text(Charset encoding) {
|
public Text(Charset charset, int lineCount) {
|
||||||
this.encoding = encoding;
|
this.charset = charset;
|
||||||
|
this.lineCount = lineCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package io.xpipe.core.source;
|
||||||
|
|
||||||
|
public interface DataSourceReadConnection extends DataSourceConnection {
|
||||||
|
|
||||||
|
void forward(DataSourceConnection con) throws Exception;
|
||||||
|
}
|
|
@ -2,10 +2,17 @@ package io.xpipe.core.source;
|
||||||
|
|
||||||
import io.xpipe.core.data.node.DataStructureNode;
|
import io.xpipe.core.data.node.DataStructureNode;
|
||||||
|
|
||||||
public interface StructureReadConnection extends DataSourceConnection {
|
public interface StructureReadConnection extends DataSourceReadConnection {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the complete contents.
|
* Reads the complete contents.
|
||||||
*/
|
*/
|
||||||
DataStructureNode read() throws Exception;
|
DataStructureNode read() throws Exception;
|
||||||
|
|
||||||
|
default void forward(DataSourceConnection con) throws Exception {
|
||||||
|
try (var tCon = (StructureWriteConnection) con) {
|
||||||
|
tCon.init();
|
||||||
|
tCon.write(read());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
/**
|
/**
|
||||||
* A connection for sequentially reading the data of a table data source.
|
* A connection for sequentially reading the data of a table data source.
|
||||||
*/
|
*/
|
||||||
public interface TableReadConnection extends DataSourceConnection {
|
public interface TableReadConnection extends DataSourceReadConnection {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the data type of the table data.
|
* Returns the data type of the table data.
|
||||||
|
@ -39,6 +39,10 @@ public interface TableReadConnection extends DataSourceConnection {
|
||||||
* Writes the rows to an OutputStream in the X-Pipe binary format.
|
* Writes the rows to an OutputStream in the X-Pipe binary format.
|
||||||
*/
|
*/
|
||||||
default void forwardRows(OutputStream out, int maxLines) throws Exception {
|
default void forwardRows(OutputStream out, int maxLines) throws Exception {
|
||||||
|
if (maxLines == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var dataType = getDataType();
|
var dataType = getDataType();
|
||||||
AtomicInteger rowCounter = new AtomicInteger();
|
AtomicInteger rowCounter = new AtomicInteger();
|
||||||
withRows(l -> {
|
withRows(l -> {
|
||||||
|
@ -47,4 +51,11 @@ public interface TableReadConnection extends DataSourceConnection {
|
||||||
return rowCounter.get() != maxLines;
|
return rowCounter.get() != maxLines;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void forward(DataSourceConnection con) throws Exception {
|
||||||
|
try (var tCon = (TableWriteConnection) con) {
|
||||||
|
tCon.init();
|
||||||
|
withRows(tCon.writeLinesAcceptor());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,28 @@ package io.xpipe.core.source;
|
||||||
|
|
||||||
import io.xpipe.core.store.DataStore;
|
import io.xpipe.core.store.DataStore;
|
||||||
|
|
||||||
public class TextDataSourceDescriptor<DS extends DataStore> implements DataSourceDescriptor<DS> {
|
public abstract class TextDataSourceDescriptor<DS extends DataStore> implements DataSourceDescriptor<DS> {
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataSourceInfo determineInfo(DS store) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataSourceType getType() {
|
public DataSourceType getType() {
|
||||||
return DataSourceType.TEXT;
|
return DataSourceType.TEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextReadConnection openReadConnection(DS store) throws Exception {
|
||||||
|
var con = newReadConnection(store);
|
||||||
|
con.init();
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextWriteConnection openWriteConnection(DS store) throws Exception {
|
||||||
|
var con = newWriteConnection(store);
|
||||||
|
con.init();
|
||||||
|
return con;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract TextWriteConnection newWriteConnection(DS store);
|
||||||
|
|
||||||
|
protected abstract TextReadConnection newReadConnection(DS store);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,29 @@
|
||||||
package io.xpipe.core.source;
|
package io.xpipe.core.source;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public interface TextReadConnection extends DataSourceConnection {
|
public interface TextReadConnection extends DataSourceReadConnection {
|
||||||
|
|
||||||
Charset getEncoding();
|
/**
|
||||||
|
* Reads the complete contents.
|
||||||
|
*/
|
||||||
|
String readAll() throws Exception;
|
||||||
|
|
||||||
|
List<String> readAllLines() throws Exception;
|
||||||
|
|
||||||
|
String readLine() throws Exception;
|
||||||
|
|
||||||
|
Stream<String> lines() throws Exception;
|
||||||
|
|
||||||
|
boolean isFinished() throws Exception;
|
||||||
|
|
||||||
|
default void forward(DataSourceConnection con) throws Exception {
|
||||||
|
try (var tCon = (TextWriteConnection) con) {
|
||||||
|
tCon.init();
|
||||||
|
for (var it = lines().iterator(); it.hasNext(); ) {
|
||||||
|
tCon.writeLine(it.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package io.xpipe.core.source;
|
package io.xpipe.core.source;
|
||||||
|
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
public interface TextWriteConnection extends DataSourceConnection {
|
public interface TextWriteConnection extends DataSourceConnection {
|
||||||
|
|
||||||
OutputStream getOutputStream();
|
void writeLine(String line) throws Exception;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package io.xpipe.core.store;
|
||||||
|
|
||||||
|
public interface FileDataStore extends StreamDataStore {
|
||||||
|
|
||||||
|
String getFileName();
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ import java.util.Optional;
|
||||||
|
|
||||||
@JsonTypeName("local")
|
@JsonTypeName("local")
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
public class LocalFileDataStore implements StreamDataStore {
|
public class LocalFileDataStore implements FileDataStore {
|
||||||
|
|
||||||
private final Path file;
|
private final Path file;
|
||||||
|
|
||||||
|
@ -57,4 +57,9 @@ public class LocalFileDataStore implements StreamDataStore {
|
||||||
public boolean exists() {
|
public boolean exists() {
|
||||||
return Files.exists(file);
|
return Files.exists(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFileName() {
|
||||||
|
return file.getFileName().toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,10 @@ public class CoreJacksonModule extends SimpleModule {
|
||||||
new NamedType(TupleType.class),
|
new NamedType(TupleType.class),
|
||||||
new NamedType(ArrayType.class),
|
new NamedType(ArrayType.class),
|
||||||
new NamedType(WildcardType.class),
|
new NamedType(WildcardType.class),
|
||||||
new NamedType(DataSourceInfo.Table.class)
|
new NamedType(DataSourceInfo.Table.class),
|
||||||
|
new NamedType(DataSourceInfo.Structure.class),
|
||||||
|
new NamedType(DataSourceInfo.Text.class),
|
||||||
|
new NamedType(DataSourceInfo.Raw.class)
|
||||||
);
|
);
|
||||||
|
|
||||||
addSerializer(Charset.class, new CharsetSerializer());
|
addSerializer(Charset.class, new CharsetSerializer());
|
||||||
|
|
|
@ -16,6 +16,8 @@ module io.xpipe.core {
|
||||||
opens io.xpipe.core.util;
|
opens io.xpipe.core.util;
|
||||||
opens io.xpipe.core.data.node;
|
opens io.xpipe.core.data.node;
|
||||||
opens io.xpipe.core.data.typed;
|
opens io.xpipe.core.data.typed;
|
||||||
|
exports io.xpipe.core.config;
|
||||||
|
opens io.xpipe.core.config;
|
||||||
|
|
||||||
requires com.fasterxml.jackson.core;
|
requires com.fasterxml.jackson.core;
|
||||||
requires com.fasterxml.jackson.databind;
|
requires com.fasterxml.jackson.databind;
|
||||||
|
|
|
@ -134,7 +134,7 @@ public class DataStructureTest {
|
||||||
readNode.clear();
|
readNode.clear();
|
||||||
Assertions.assertEquals(readNode.size(), 0);
|
Assertions.assertEquals(readNode.size(), 0);
|
||||||
} else {
|
} else {
|
||||||
readNode.setRawData("abc".getBytes(StandardCharsets.UTF_8));
|
readNode.setRaw("abc".getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (readNode.isTuple() || readNode.isArray()) {
|
if (readNode.isTuple() || readNode.isArray()) {
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class DataStructureTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DataStructureNode createTestData12() {
|
private static DataStructureNode createTestData12() {
|
||||||
var val = ValueNode.nullValue();
|
var val = ValueNode.of(null);
|
||||||
var flatArray = ArrayNode.of();
|
var flatArray = ArrayNode.of();
|
||||||
var flatTuple = TupleNode.builder().add("key1", val).build();
|
var flatTuple = TupleNode.builder().add("key1", val).build();
|
||||||
var nestedArray = ArrayNode.of(List.of(flatArray, flatTuple));
|
var nestedArray = ArrayNode.of(List.of(flatArray, flatTuple));
|
||||||
|
@ -101,7 +101,7 @@ public class DataStructureTests {
|
||||||
|
|
||||||
public static DataStructureNode createTestData32() {
|
public static DataStructureNode createTestData32() {
|
||||||
var val = ValueNode.of("value2".getBytes(StandardCharsets.UTF_8));
|
var val = ValueNode.of("value2".getBytes(StandardCharsets.UTF_8));
|
||||||
var flatTuple = TupleNode.builder().add("key1", ValueNode.nullValue()).add("key2", ValueNode.nullValue()).build();
|
var flatTuple = TupleNode.builder().add("key1", ValueNode.of(null)).add("key2", ValueNode.of(null)).build();
|
||||||
var flatArray = ArrayNode.of(List.of(val, flatTuple));
|
var flatArray = ArrayNode.of(List.of(val, flatTuple));
|
||||||
return flatArray;
|
return flatArray;
|
||||||
}
|
}
|
||||||
|
@ -112,13 +112,13 @@ public class DataStructureTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataStructureNode createTestData42() {
|
public static DataStructureNode createTestData42() {
|
||||||
var val = ValueNode.nullValue();
|
var val = ValueNode.of(null);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataStructureNode createTestData51() {
|
public static DataStructureNode createTestData51() {
|
||||||
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
|
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
|
||||||
var flatArray = ArrayNode.of(List.of(val, ValueNode.nullValue()));
|
var flatArray = ArrayNode.of(List.of(val, ValueNode.of(null)));
|
||||||
var array1 = ArrayNode.of(List.of(flatArray));
|
var array1 = ArrayNode.of(List.of(flatArray));
|
||||||
var array2 = ArrayNode.of(List.of(array1, array1));
|
var array2 = ArrayNode.of(List.of(array1, array1));
|
||||||
return array2;
|
return array2;
|
||||||
|
@ -143,7 +143,7 @@ public class DataStructureTests {
|
||||||
|
|
||||||
public static DataStructureNode createTestData61() {
|
public static DataStructureNode createTestData61() {
|
||||||
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
|
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
|
||||||
var array = ArrayNode.of(List.of(val, ValueNode.nullValue()));
|
var array = ArrayNode.of(List.of(val, ValueNode.of(null)));
|
||||||
var tuple = TupleNode.builder()
|
var tuple = TupleNode.builder()
|
||||||
.add(val).add("key2", array).build();
|
.add(val).add("key2", array).build();
|
||||||
return tuple;
|
return tuple;
|
||||||
|
@ -176,7 +176,7 @@ public class DataStructureTests {
|
||||||
|
|
||||||
public static DataStructureNode createTestData73() {
|
public static DataStructureNode createTestData73() {
|
||||||
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
|
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
|
||||||
var array = ArrayNode.of(List.of(val, ValueNode.nullValue()));
|
var array = ArrayNode.of(List.of(val, ValueNode.of(null)));
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
deps
2
deps
|
@ -1 +1 @@
|
||||||
Subproject commit cbac51bc63e727c0ff5038cace4e91daa168a556
|
Subproject commit 49a1ad06bc6872f72c1d20ea864d24f3df59b7c5
|
|
@ -1,11 +1,15 @@
|
||||||
package io.xpipe.extension;
|
package io.xpipe.extension;
|
||||||
|
|
||||||
import io.xpipe.core.source.*;
|
import io.xpipe.core.config.ConfigOption;
|
||||||
|
import io.xpipe.core.config.ConfigOptionSet;
|
||||||
|
import io.xpipe.core.source.DataSourceDescriptor;
|
||||||
|
import io.xpipe.core.source.DataSourceInfo;
|
||||||
|
import io.xpipe.core.source.DataSourceType;
|
||||||
import io.xpipe.core.store.DataStore;
|
import io.xpipe.core.store.DataStore;
|
||||||
import io.xpipe.core.store.StreamDataStore;
|
|
||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -15,8 +19,6 @@ public interface DataSourceProvider {
|
||||||
|
|
||||||
interface FileProvider {
|
interface FileProvider {
|
||||||
|
|
||||||
void write(StreamDataStore store, DataSourceDescriptor<StreamDataStore> desc, TableReadConnection con) throws Exception;
|
|
||||||
|
|
||||||
String getFileName();
|
String getFileName();
|
||||||
|
|
||||||
Map<Supplier<String>, String> getFileExtensions();
|
Map<Supplier<String>, String> getFileExtensions();
|
||||||
|
@ -35,6 +37,13 @@ public interface DataSourceProvider {
|
||||||
|
|
||||||
interface ConfigProvider {
|
interface ConfigProvider {
|
||||||
|
|
||||||
|
ConfigOption
|
||||||
|
CHARSET_OPTION = new ConfigOption("Charset", "charset");
|
||||||
|
Function<String, Charset>
|
||||||
|
CHARSET_CONVERTER = ConfigProvider.charsetConverter();
|
||||||
|
Function<Charset, String>
|
||||||
|
CHARSET_STRING = Charset::name;
|
||||||
|
|
||||||
static String booleanName(String name) {
|
static String booleanName(String name) {
|
||||||
return name + " (y/n)";
|
return name + " (y/n)";
|
||||||
}
|
}
|
||||||
|
@ -63,19 +72,25 @@ public interface DataSourceProvider {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
DataSourceConfigOptions getConfig();
|
static Function<String, Charset> charsetConverter() {
|
||||||
|
return Charset::forName;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigOptionSet getConfig();
|
||||||
|
|
||||||
DataSourceDescriptor<?> toDescriptor(Map<String, String> values);
|
DataSourceDescriptor<?> toDescriptor(Map<String, String> values);
|
||||||
|
|
||||||
Map<String, String> toConfigOptions(DataSourceDescriptor<?> desc);
|
Map<String, String> toConfigOptions(DataSourceDescriptor<?> desc);
|
||||||
|
|
||||||
Map<DataSourceConfigOptions.Option, Function<String, ?>> getConverters();
|
Map<ConfigOption, Function<String, ?>> getConverters();
|
||||||
|
|
||||||
List<String> getPossibleNames();
|
List<String> getPossibleNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
DataSourceType getType();
|
DataSourceType getType();
|
||||||
|
|
||||||
|
boolean prefersStore(DataStore store);
|
||||||
|
|
||||||
boolean supportsStore(DataStore store);
|
boolean supportsStore(DataStore store);
|
||||||
|
|
||||||
FileProvider getFileProvider();
|
FileProvider getFileProvider();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.xpipe.extension;
|
package io.xpipe.extension;
|
||||||
|
|
||||||
import io.xpipe.core.data.type.TupleType;
|
import io.xpipe.core.data.type.TupleType;
|
||||||
|
import io.xpipe.core.source.DataSourceType;
|
||||||
import io.xpipe.core.source.TableDataSourceDescriptor;
|
import io.xpipe.core.source.TableDataSourceDescriptor;
|
||||||
import io.xpipe.core.store.DataStore;
|
import io.xpipe.core.store.DataStore;
|
||||||
import io.xpipe.core.store.LocalFileDataStore;
|
import io.xpipe.core.store.LocalFileDataStore;
|
||||||
|
@ -22,6 +23,25 @@ public class DataSourceProviders {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DataSourceProvider getNativeProviderForType(DataSourceType t) {
|
||||||
|
switch (t) {
|
||||||
|
case TABLE -> {
|
||||||
|
return DataSourceProviders.byId("xpbt").orElseThrow();
|
||||||
|
}
|
||||||
|
case STRUCTURE -> {
|
||||||
|
return DataSourceProviders.byId("xpbs").orElseThrow();
|
||||||
|
}
|
||||||
|
case TEXT -> {
|
||||||
|
return DataSourceProviders.byId("xpbx").orElseThrow();
|
||||||
|
}
|
||||||
|
case RAW -> {
|
||||||
|
return DataSourceProviders.byId("xpbb").orElseThrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static TableDataSourceDescriptor<LocalFileDataStore> createLocalTableDescriptor(TupleType type) {
|
public static TableDataSourceDescriptor<LocalFileDataStore> createLocalTableDescriptor(TupleType type) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -36,7 +36,9 @@ public class CharChoiceComp extends Comp<CompStructure<HBox>> {
|
||||||
public CompStructure<HBox> createBase() {
|
public CompStructure<HBox> createBase() {
|
||||||
var charChoice = new CharComp(value);
|
var charChoice = new CharComp(value);
|
||||||
var rangeCopy = new DualLinkedHashBidiMap<>(range);
|
var rangeCopy = new DualLinkedHashBidiMap<>(range);
|
||||||
|
if (customName != null) {
|
||||||
rangeCopy.put(null, customName);
|
rangeCopy.put(null, customName);
|
||||||
|
}
|
||||||
var choice = new ChoiceComp<Character>(charChoiceValue, rangeCopy);
|
var choice = new ChoiceComp<Character>(charChoiceValue, rangeCopy);
|
||||||
var charChoiceR = charChoice.createRegion();
|
var charChoiceR = charChoice.createRegion();
|
||||||
var choiceR = choice.createRegion();
|
var choiceR = choice.createRegion();
|
||||||
|
|
Loading…
Reference in a new issue