mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
Refactor
This commit is contained in:
parent
27843ae0fd
commit
55da767dab
186 changed files with 1541 additions and 1606 deletions
|
@ -27,10 +27,6 @@ import java.nio.file.Path;
|
||||||
*/
|
*/
|
||||||
public interface DataSource {
|
public interface DataSource {
|
||||||
|
|
||||||
void forwardTo(DataSource target);
|
|
||||||
|
|
||||||
void appendTo(DataSource target);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOT YET IMPLEMENTED!
|
* NOT YET IMPLEMENTED!
|
||||||
*
|
*
|
||||||
|
@ -126,7 +122,6 @@ public interface DataSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for {@link #create(DataSourceId, String, InputStream)} that creates an anonymous data source.
|
* Wrapper for {@link #create(DataSourceId, String, InputStream)} that creates an anonymous data source.
|
||||||
*/
|
*/
|
||||||
|
@ -168,6 +163,10 @@ public interface DataSource {
|
||||||
return DataSourceImpl.create(id, type, in);
|
return DataSourceImpl.create(id, type, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void forwardTo(DataSource target);
|
||||||
|
|
||||||
|
void appendTo(DataSource target);
|
||||||
|
|
||||||
public io.xpipe.core.source.DataSource<?> getInternalSource();
|
public io.xpipe.core.source.DataSource<?> getInternalSource();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -180,7 +179,6 @@ public interface DataSource {
|
||||||
*/
|
*/
|
||||||
DataSourceType getType();
|
DataSourceType getType();
|
||||||
|
|
||||||
|
|
||||||
DataSourceConfig getConfig();
|
DataSourceConfig getConfig();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,7 +12,9 @@ public class DataStores {
|
||||||
public static void addNamedStore(DataStore store, String name) {
|
public static void addNamedStore(DataStore store, String name) {
|
||||||
XPipeConnection.execute(con -> {
|
XPipeConnection.execute(con -> {
|
||||||
var req = StoreAddExchange.Request.builder()
|
var req = StoreAddExchange.Request.builder()
|
||||||
.storeInput(store).name(name).build();
|
.storeInput(store)
|
||||||
|
.name(name)
|
||||||
|
.build();
|
||||||
StoreAddExchange.Response res = con.performSimpleExchange(req);
|
StoreAddExchange.Response res = con.performSimpleExchange(req);
|
||||||
|
|
||||||
new QuietDialogHandler(res.getConfig(), con, Map.of()).handle();
|
new QuietDialogHandler(res.getConfig(), con, Map.of()).handle();
|
||||||
|
|
|
@ -8,6 +8,8 @@ import java.util.Optional;
|
||||||
|
|
||||||
public final class XPipeConnection extends BeaconConnection {
|
public final class XPipeConnection extends BeaconConnection {
|
||||||
|
|
||||||
|
private XPipeConnection() {}
|
||||||
|
|
||||||
public static XPipeConnection open() {
|
public static XPipeConnection open() {
|
||||||
var con = new XPipeConnection();
|
var con = new XPipeConnection();
|
||||||
con.constructSocket();
|
con.constructSocket();
|
||||||
|
@ -23,7 +25,9 @@ public final class XPipeConnection extends BeaconConnection {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogExchange.Response response = con.performSimpleExchange(DialogExchange.Request.builder().dialogKey(reference.getDialogId()).build());
|
DialogExchange.Response response = con.performSimpleExchange(DialogExchange.Request.builder()
|
||||||
|
.dialogKey(reference.getDialogId())
|
||||||
|
.build());
|
||||||
element = response.getElement();
|
element = response.getElement();
|
||||||
if (response.getElement() == null) {
|
if (response.getElement() == null) {
|
||||||
break;
|
break;
|
||||||
|
@ -58,40 +62,6 @@ public final class XPipeConnection extends BeaconConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private XPipeConnection() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void constructSocket() {
|
|
||||||
if (!BeaconServer.isRunning()) {
|
|
||||||
try {
|
|
||||||
start();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new BeaconException("Unable to start xpipe daemon", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
var r = waitForStartup(null);
|
|
||||||
if (r.isEmpty()) {
|
|
||||||
throw new BeaconException("Wait for xpipe daemon timed out");
|
|
||||||
} else {
|
|
||||||
beaconClient = r.get();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
beaconClient = new BeaconClient();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
throw new BeaconException("Unable to connect to running xpipe daemon", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void start() throws Exception {
|
|
||||||
if (BeaconServer.tryStart() == null) {
|
|
||||||
throw new UnsupportedOperationException("Unable to determine xpipe daemon launch command");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Optional<BeaconClient> waitForStartup(Process process) {
|
public static Optional<BeaconClient> waitForStartup(Process process) {
|
||||||
for (int i = 0; i < 160; i++) {
|
for (int i = 0; i < 160; i++) {
|
||||||
if (process != null && !process.isAlive()) {
|
if (process != null && !process.isAlive()) {
|
||||||
|
@ -125,6 +95,38 @@ public final class XPipeConnection extends BeaconConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void constructSocket() {
|
||||||
|
if (!BeaconServer.isRunning()) {
|
||||||
|
try {
|
||||||
|
start();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new BeaconException("Unable to start xpipe daemon", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var r = waitForStartup(null);
|
||||||
|
if (r.isEmpty()) {
|
||||||
|
throw new BeaconException("Wait for xpipe daemon timed out");
|
||||||
|
} else {
|
||||||
|
beaconClient = r.get();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
beaconClient = new BeaconClient();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new BeaconException("Unable to connect to running xpipe daemon", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void start() throws Exception {
|
||||||
|
if (BeaconServer.tryStart() == null) {
|
||||||
|
throw new UnsupportedOperationException("Unable to determine xpipe daemon launch command");
|
||||||
|
}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public static interface Handler {
|
public static interface Handler {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,9 @@ package io.xpipe.api.impl;
|
||||||
|
|
||||||
import io.xpipe.api.DataRaw;
|
import io.xpipe.api.DataRaw;
|
||||||
import io.xpipe.api.DataSourceConfig;
|
import io.xpipe.api.DataSourceConfig;
|
||||||
import io.xpipe.core.source.*;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
|
import io.xpipe.core.source.DataSourceInfo;
|
||||||
|
import io.xpipe.core.source.DataSourceType;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
@ -10,7 +12,11 @@ public class DataRawImpl extends DataSourceImpl implements DataRaw {
|
||||||
|
|
||||||
private final DataSourceInfo.Raw info;
|
private final DataSourceInfo.Raw info;
|
||||||
|
|
||||||
public DataRawImpl(DataSourceId sourceId, DataSourceConfig sourceConfig, DataSourceInfo.Raw info, io.xpipe.core.source.DataSource<?> internalSource) {
|
public DataRawImpl(
|
||||||
|
DataSourceId sourceId,
|
||||||
|
DataSourceConfig sourceConfig,
|
||||||
|
DataSourceInfo.Raw info,
|
||||||
|
io.xpipe.core.source.DataSource<?> internalSource) {
|
||||||
super(sourceId, sourceConfig, internalSource);
|
super(sourceId, sourceConfig, internalSource);
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,28 +13,15 @@ import java.io.InputStream;
|
||||||
|
|
||||||
public abstract class DataSourceImpl implements DataSource {
|
public abstract class DataSourceImpl implements DataSource {
|
||||||
|
|
||||||
@Override
|
private final DataSourceId sourceId;
|
||||||
public void forwardTo(DataSource target) {
|
private final DataSourceConfig config;
|
||||||
XPipeConnection.execute(con -> {
|
private final io.xpipe.core.source.DataSource<?> internalSource;
|
||||||
var req = ForwardExchange.Request.builder()
|
|
||||||
.source(DataSourceReference.id(sourceId))
|
|
||||||
.target(DataSourceReference.id(target.getId()))
|
|
||||||
.build();
|
|
||||||
ForwardExchange.Response res = con.performSimpleExchange(req);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void appendTo(DataSource target) {
|
|
||||||
XPipeConnection.execute(con -> {
|
|
||||||
var req = ForwardExchange.Request.builder()
|
|
||||||
.source(DataSourceReference.id(sourceId))
|
|
||||||
.target(DataSourceReference.id(target.getId()))
|
|
||||||
.append(true)
|
|
||||||
.build();
|
|
||||||
ForwardExchange.Response res = con.performSimpleExchange(req);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
public DataSourceImpl(
|
||||||
|
DataSourceId sourceId, DataSourceConfig config, io.xpipe.core.source.DataSource<?> internalSource) {
|
||||||
|
this.sourceId = sourceId;
|
||||||
|
this.config = config;
|
||||||
|
this.internalSource = internalSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataSource get(DataSourceReference ds) {
|
public static DataSource get(DataSourceReference ds) {
|
||||||
|
@ -59,17 +46,17 @@ public abstract class DataSourceImpl implements DataSource {
|
||||||
var info = res.getInfo().asRaw();
|
var info = res.getInfo().asRaw();
|
||||||
yield new DataRawImpl(res.getId(), config, info, res.getInternalSource());
|
yield new DataRawImpl(res.getId(), config, info, res.getInternalSource());
|
||||||
}
|
}
|
||||||
case COLLECTION -> throw new UnsupportedOperationException("Unimplemented case: " + res.getInfo().getType());
|
case COLLECTION -> throw new UnsupportedOperationException(
|
||||||
default -> throw new IllegalArgumentException("Unexpected value: " + res.getInfo().getType());
|
"Unimplemented case: " + res.getInfo().getType());
|
||||||
|
default -> throw new IllegalArgumentException(
|
||||||
|
"Unexpected value: " + res.getInfo().getType());
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DataSource create(DataSourceId id, io.xpipe.core.source.DataSource<?> source) {
|
public static DataSource create(DataSourceId id, io.xpipe.core.source.DataSource<?> source) {
|
||||||
var startReq = AddSourceExchange.Request.builder()
|
var startReq =
|
||||||
.source(source)
|
AddSourceExchange.Request.builder().source(source).target(id).build();
|
||||||
.target(id)
|
|
||||||
.build();
|
|
||||||
var returnedId = XPipeConnection.execute(con -> {
|
var returnedId = XPipeConnection.execute(con -> {
|
||||||
AddSourceExchange.Response r = con.performSimpleExchange(startReq);
|
AddSourceExchange.Response r = con.performSimpleExchange(startReq);
|
||||||
return r.getId();
|
return r.getId();
|
||||||
|
@ -108,9 +95,7 @@ public abstract class DataSourceImpl implements DataSource {
|
||||||
var configInstance = startRes.getConfig();
|
var configInstance = startRes.getConfig();
|
||||||
XPipeConnection.finishDialog(configInstance);
|
XPipeConnection.finishDialog(configInstance);
|
||||||
|
|
||||||
var ref = id != null ?
|
var ref = id != null ? DataSourceReference.id(id) : DataSourceReference.latest();
|
||||||
DataSourceReference.id(id) :
|
|
||||||
DataSourceReference.latest();
|
|
||||||
return get(ref);
|
return get(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,20 +122,31 @@ public abstract class DataSourceImpl implements DataSource {
|
||||||
var configInstance = startRes.getConfig();
|
var configInstance = startRes.getConfig();
|
||||||
XPipeConnection.finishDialog(configInstance);
|
XPipeConnection.finishDialog(configInstance);
|
||||||
|
|
||||||
var ref = id != null ?
|
var ref = id != null ? DataSourceReference.id(id) : DataSourceReference.latest();
|
||||||
DataSourceReference.id(id) :
|
|
||||||
DataSourceReference.latest();
|
|
||||||
return get(ref);
|
return get(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final DataSourceId sourceId;
|
@Override
|
||||||
private final DataSourceConfig config;
|
public void forwardTo(DataSource target) {
|
||||||
private final io.xpipe.core.source.DataSource<?> internalSource;
|
XPipeConnection.execute(con -> {
|
||||||
|
var req = ForwardExchange.Request.builder()
|
||||||
|
.source(DataSourceReference.id(sourceId))
|
||||||
|
.target(DataSourceReference.id(target.getId()))
|
||||||
|
.build();
|
||||||
|
ForwardExchange.Response res = con.performSimpleExchange(req);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public DataSourceImpl(DataSourceId sourceId, DataSourceConfig config, io.xpipe.core.source.DataSource<?> internalSource) {
|
@Override
|
||||||
this.sourceId = sourceId;
|
public void appendTo(DataSource target) {
|
||||||
this.config = config;
|
XPipeConnection.execute(con -> {
|
||||||
this.internalSource = internalSource;
|
var req = ForwardExchange.Request.builder()
|
||||||
|
.source(DataSourceReference.id(sourceId))
|
||||||
|
.target(DataSourceReference.id(target.getId()))
|
||||||
|
.append(true)
|
||||||
|
.build();
|
||||||
|
ForwardExchange.Response res = con.performSimpleExchange(req);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public io.xpipe.core.source.DataSource<?> getInternalSource() {
|
public io.xpipe.core.source.DataSource<?> getInternalSource() {
|
||||||
|
|
|
@ -3,13 +3,19 @@ package io.xpipe.api.impl;
|
||||||
import io.xpipe.api.DataSourceConfig;
|
import io.xpipe.api.DataSourceConfig;
|
||||||
import io.xpipe.api.DataStructure;
|
import io.xpipe.api.DataStructure;
|
||||||
import io.xpipe.core.data.node.DataStructureNode;
|
import io.xpipe.core.data.node.DataStructureNode;
|
||||||
import io.xpipe.core.source.*;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
|
import io.xpipe.core.source.DataSourceInfo;
|
||||||
|
import io.xpipe.core.source.DataSourceType;
|
||||||
|
|
||||||
public class DataStructureImpl extends DataSourceImpl implements DataStructure {
|
public class DataStructureImpl extends DataSourceImpl implements DataStructure {
|
||||||
|
|
||||||
private final DataSourceInfo.Structure info;
|
private final DataSourceInfo.Structure info;
|
||||||
|
|
||||||
public DataStructureImpl(DataSourceId sourceId, DataSourceConfig sourceConfig, DataSourceInfo.Structure info, io.xpipe.core.source.DataSource<?> internalSource) {
|
public DataStructureImpl(
|
||||||
|
DataSourceId sourceId,
|
||||||
|
DataSourceConfig sourceConfig,
|
||||||
|
DataSourceInfo.Structure info,
|
||||||
|
io.xpipe.core.source.DataSource<?> internalSource) {
|
||||||
super(sourceId, sourceConfig, internalSource);
|
super(sourceId, sourceConfig, internalSource);
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,11 @@ public class DataTableAccumulatorImpl implements DataTableAccumulator {
|
||||||
connection.close();
|
connection.close();
|
||||||
|
|
||||||
var req = ReadExchange.Request.builder()
|
var req = ReadExchange.Request.builder()
|
||||||
.target(id).store(res.getStore()).provider("xpbt").configureAll(false).build();
|
.target(id)
|
||||||
|
.store(res.getStore())
|
||||||
|
.provider("xpbt")
|
||||||
|
.configureAll(false)
|
||||||
|
.build();
|
||||||
ReadExchange.Response response = XPipeConnection.execute(con -> {
|
ReadExchange.Response response = XPipeConnection.execute(con -> {
|
||||||
return con.performSimpleExchange(req);
|
return con.performSimpleExchange(req);
|
||||||
});
|
});
|
||||||
|
@ -71,7 +75,9 @@ public class DataTableAccumulatorImpl implements DataTableAccumulator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void add(DataStructureNode row) {
|
public synchronized void add(DataStructureNode row) {
|
||||||
TupleNode toUse = type.matches(row) ? row.asTuple() : type.convert(row).orElseThrow().asTuple();
|
TupleNode toUse = type.matches(row)
|
||||||
|
? row.asTuple()
|
||||||
|
: type.convert(row).orElseThrow().asTuple();
|
||||||
connection.withOutputStream(out -> {
|
connection.withOutputStream(out -> {
|
||||||
writeDescriptor();
|
writeDescriptor();
|
||||||
TypedDataStreamWriter.writeStructure(out, toUse, writtenDescriptor);
|
TypedDataStreamWriter.writeStructure(out, toUse, writtenDescriptor);
|
||||||
|
|
|
@ -27,7 +27,11 @@ public class DataTableImpl extends DataSourceImpl implements DataTable {
|
||||||
|
|
||||||
private final DataSourceInfo.Table info;
|
private final DataSourceInfo.Table info;
|
||||||
|
|
||||||
DataTableImpl(DataSourceId id, DataSourceConfig sourceConfig, DataSourceInfo.Table info, io.xpipe.core.source.DataSource<?> internalSource) {
|
DataTableImpl(
|
||||||
|
DataSourceId id,
|
||||||
|
DataSourceConfig sourceConfig,
|
||||||
|
DataSourceInfo.Table info,
|
||||||
|
io.xpipe.core.source.DataSource<?> internalSource) {
|
||||||
super(id, sourceConfig, internalSource);
|
super(id, sourceConfig, internalSource);
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
@ -44,8 +48,8 @@ public class DataTableImpl extends DataSourceImpl implements DataTable {
|
||||||
|
|
||||||
public Stream<TupleNode> stream() {
|
public Stream<TupleNode> stream() {
|
||||||
var iterator = new TableIterator();
|
var iterator = new TableIterator();
|
||||||
return StreamSupport.stream(
|
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
|
||||||
Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false).onClose(iterator::finish);
|
.onClose(iterator::finish);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,15 +67,23 @@ 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()
|
||||||
.ref(DataSourceReference.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.of(info.getDataType()), nodes::add);
|
r.parseStructures(in, TypedDataStructureNodeReader.of(info.getDataType()), nodes::add);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return ArrayNode.of(nodes);
|
return ArrayNode.of(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<TupleNode> iterator() {
|
||||||
|
return new TableIterator();
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
private class TableIterator implements Iterator<TupleNode> {
|
private class TableIterator implements Iterator<TupleNode> {
|
||||||
|
|
||||||
private final BeaconConnection connection;
|
private final BeaconConnection connection;
|
||||||
|
@ -85,7 +97,9 @@ public class DataTableImpl extends DataSourceImpl implements DataTable {
|
||||||
|
|
||||||
connection = XPipeConnection.open();
|
connection = XPipeConnection.open();
|
||||||
var req = QueryTableDataExchange.Request.builder()
|
var req = QueryTableDataExchange.Request.builder()
|
||||||
.ref(DataSourceReference.id(getId())).maxRows(Integer.MAX_VALUE).build();
|
.ref(DataSourceReference.id(getId()))
|
||||||
|
.maxRows(Integer.MAX_VALUE)
|
||||||
|
.build();
|
||||||
connection.sendRequest(req);
|
connection.sendRequest(req);
|
||||||
connection.receiveResponse();
|
connection.receiveResponse();
|
||||||
connection.receiveBody();
|
connection.receiveBody();
|
||||||
|
@ -116,10 +130,5 @@ public class DataTableImpl extends DataSourceImpl implements DataTable {
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<TupleNode> iterator() {
|
|
||||||
return new TableIterator();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,11 @@ public class DataTextImpl extends DataSourceImpl implements DataText {
|
||||||
|
|
||||||
private final DataSourceInfo.Text info;
|
private final DataSourceInfo.Text info;
|
||||||
|
|
||||||
public DataTextImpl(DataSourceId sourceId, DataSourceConfig sourceConfig, DataSourceInfo.Text info, io.xpipe.core.source.DataSource<?> internalSource) {
|
public DataTextImpl(
|
||||||
|
DataSourceId sourceId,
|
||||||
|
DataSourceConfig sourceConfig,
|
||||||
|
DataSourceInfo.Text info,
|
||||||
|
io.xpipe.core.source.DataSource<?> internalSource) {
|
||||||
super(sourceId, sourceConfig, internalSource);
|
super(sourceId, sourceConfig, internalSource);
|
||||||
this.info = info;
|
this.info = info;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +74,9 @@ public class DataTextImpl extends DataSourceImpl implements DataText {
|
||||||
{
|
{
|
||||||
connection = XPipeConnection.open();
|
connection = XPipeConnection.open();
|
||||||
var req = QueryTextDataExchange.Request.builder()
|
var req = QueryTextDataExchange.Request.builder()
|
||||||
.ref(DataSourceReference.id(getId())).maxLines(-1).build();
|
.ref(DataSourceReference.id(getId()))
|
||||||
|
.maxLines(-1)
|
||||||
|
.build();
|
||||||
connection.sendRequest(req);
|
connection.sendRequest(req);
|
||||||
connection.receiveResponse();
|
connection.receiveResponse();
|
||||||
reader = new BufferedReader(new InputStreamReader(connection.receiveBody(), StandardCharsets.UTF_8));
|
reader = new BufferedReader(new InputStreamReader(connection.receiveBody(), StandardCharsets.UTF_8));
|
||||||
|
@ -98,8 +104,7 @@ public class DataTextImpl extends DataSourceImpl implements DataText {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return StreamSupport
|
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
|
||||||
.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
|
|
||||||
.onClose(iterator::close);
|
.onClose(iterator::close);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,6 +128,4 @@ public class DataTextImpl extends DataSourceImpl implements DataText {
|
||||||
});
|
});
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ import java.util.UUID;
|
||||||
public class QuietDialogHandler {
|
public class QuietDialogHandler {
|
||||||
|
|
||||||
private final UUID dialogKey;
|
private final UUID dialogKey;
|
||||||
private DialogElement element;
|
|
||||||
private final BeaconConnection connection;
|
private final BeaconConnection connection;
|
||||||
private final Map<String, String> overrides;
|
private final Map<String, String> overrides;
|
||||||
|
private DialogElement element;
|
||||||
|
|
||||||
public QuietDialogHandler(DialogReference ref, BeaconConnection connection, Map<String, String> overrides) {
|
public QuietDialogHandler(DialogReference ref, BeaconConnection connection, Map<String, String> overrides) {
|
||||||
this.dialogKey = ref.getDialogId();
|
this.dialogKey = ref.getDialogId();
|
||||||
|
@ -36,10 +36,13 @@ public class QuietDialogHandler {
|
||||||
response = handleQuery(q);
|
response = handleQuery(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogExchange.Response res = connection.performSimpleExchange(
|
DialogExchange.Response res = connection.performSimpleExchange(DialogExchange.Request.builder()
|
||||||
DialogExchange.Request.builder().dialogKey(dialogKey).value(response).build());
|
.dialogKey(dialogKey)
|
||||||
|
.value(response)
|
||||||
|
.build());
|
||||||
if (res.getElement() != null && element.equals(res.getElement())) {
|
if (res.getElement() != null && element.equals(res.getElement())) {
|
||||||
throw new ClientException("Invalid value for key " + res.getElement().toDisplayString());
|
throw new ClientException(
|
||||||
|
"Invalid value for key " + res.getElement().toDisplayString());
|
||||||
}
|
}
|
||||||
|
|
||||||
element = res.getElement();
|
element = res.getElement();
|
||||||
|
|
|
@ -6,8 +6,7 @@ import java.util.stream.Collectors;
|
||||||
public class TypeDescriptor {
|
public class TypeDescriptor {
|
||||||
|
|
||||||
public static String create(List<String> names) {
|
public static String create(List<String> names) {
|
||||||
return "[" + names.stream()
|
return "[" + names.stream().map(n -> n != null ? "\"" + n + "\"" : null).collect(Collectors.joining(","))
|
||||||
.map(n -> n != null ? "\"" + n + "\"" : null)
|
+ "]\n";
|
||||||
.collect(Collectors.joining(",")) + "]\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,11 @@ public class DataTableAccumulatorTest extends ApiTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
var type = TupleType.of(
|
var type = TupleType.of(List.of("col1", "col2"), List.of(ValueType.of(), ValueType.of()));
|
||||||
List.of("col1", "col2"),
|
|
||||||
List.of(ValueType.of(), ValueType.of()));
|
|
||||||
var acc = DataTableAccumulator.create(type);
|
var acc = DataTableAccumulator.create(type);
|
||||||
|
|
||||||
var val = type.convert(
|
var val = type.convert(TupleNode.of(List.of(ValueNode.of("val1"), ValueNode.of("val2"))))
|
||||||
TupleNode.of(List.of(ValueNode.of("val1"), ValueNode.of("val2")))).orElseThrow();
|
.orElseThrow();
|
||||||
acc.add(val);
|
acc.add(val);
|
||||||
var table = acc.finish(":test");
|
var table = acc.finish(":test");
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@ public class DataTableTest extends ApiTest {
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void setupStorage() throws Exception {
|
public static void setupStorage() throws Exception {
|
||||||
DataSource.create(DataSourceId.fromString(":usernames"), "csv", DataTableTest.class.getResource("username.csv"));
|
DataSource.create(
|
||||||
|
DataSourceId.fromString(":usernames"), "csv", DataTableTest.class.getResource("username.csv"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -23,32 +23,6 @@ import static io.xpipe.beacon.BeaconConfig.BODY_SEPARATOR;
|
||||||
|
|
||||||
public class BeaconClient implements AutoCloseable {
|
public class BeaconClient implements AutoCloseable {
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface FailableBiConsumer<T, U, E extends Throwable> {
|
|
||||||
|
|
||||||
void accept(T var1, U var2) throws E;
|
|
||||||
}
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface FailableConsumer<T, E extends Throwable> {
|
|
||||||
|
|
||||||
void accept(T var1) throws E;
|
|
||||||
}
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface FailableRunnable<E extends Throwable> {
|
|
||||||
|
|
||||||
void run() throws E;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Optional<BeaconClient> tryConnect() {
|
|
||||||
try {
|
|
||||||
return Optional.of(new BeaconClient());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Closeable closeable;
|
private final Closeable closeable;
|
||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
private final OutputStream out;
|
private final OutputStream out;
|
||||||
|
@ -66,6 +40,14 @@ public class BeaconClient implements AutoCloseable {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Optional<BeaconClient> tryConnect() {
|
||||||
|
try {
|
||||||
|
return Optional.of(new BeaconClient());
|
||||||
|
} catch (IOException ex) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void close() throws ConnectorException {
|
public void close() throws ConnectorException {
|
||||||
try {
|
try {
|
||||||
closeable.close();
|
closeable.close();
|
||||||
|
@ -104,12 +86,13 @@ public class BeaconClient implements AutoCloseable {
|
||||||
|
|
||||||
json.set("messageType", new TextNode(prov.get().getId()));
|
json.set("messageType", new TextNode(prov.get().getId()));
|
||||||
json.set("messagePhase", new TextNode("request"));
|
json.set("messagePhase", new TextNode("request"));
|
||||||
//json.set("id", new TextNode(UUID.randomUUID().toString()));
|
// json.set("id", new TextNode(UUID.randomUUID().toString()));
|
||||||
var msg = JsonNodeFactory.instance.objectNode();
|
var msg = JsonNodeFactory.instance.objectNode();
|
||||||
msg.set("xPipeMessage", json);
|
msg.set("xPipeMessage", json);
|
||||||
|
|
||||||
if (BeaconConfig.printMessages()) {
|
if (BeaconConfig.printMessages()) {
|
||||||
System.out.println("Sending request to server of type " + req.getClass().getName());
|
System.out.println(
|
||||||
|
"Sending request to server of type " + req.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
var writer = new StringWriter();
|
var writer = new StringWriter();
|
||||||
|
@ -198,13 +181,13 @@ public class BeaconClient implements AutoCloseable {
|
||||||
|
|
||||||
var type = content.required("messageType").textValue();
|
var type = content.required("messageType").textValue();
|
||||||
var phase = content.required("messagePhase").textValue();
|
var phase = content.required("messagePhase").textValue();
|
||||||
//var requestId = UUID.fromString(content.required("id").textValue());
|
// var requestId = UUID.fromString(content.required("id").textValue());
|
||||||
if (!phase.equals("response")) {
|
if (!phase.equals("response")) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
content.remove("messageType");
|
content.remove("messageType");
|
||||||
content.remove("messagePhase");
|
content.remove("messagePhase");
|
||||||
//content.remove("id");
|
// content.remove("id");
|
||||||
|
|
||||||
var prov = MessageExchanges.byId(type);
|
var prov = MessageExchanges.byId(type);
|
||||||
if (prov.isEmpty()) {
|
if (prov.isEmpty()) {
|
||||||
|
@ -226,4 +209,22 @@ public class BeaconClient implements AutoCloseable {
|
||||||
public OutputStream getRawOutputStream() {
|
public OutputStream getRawOutputStream() {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FailableBiConsumer<T, U, E extends Throwable> {
|
||||||
|
|
||||||
|
void accept(T var1, U var2) throws E;
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FailableConsumer<T, E extends Throwable> {
|
||||||
|
|
||||||
|
void accept(T var1) throws E;
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FailableRunnable<E extends Throwable> {
|
||||||
|
|
||||||
|
void run() throws E;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,14 @@ import java.nio.charset.StandardCharsets;
|
||||||
public class BeaconConfig {
|
public class BeaconConfig {
|
||||||
|
|
||||||
public static final byte[] BODY_SEPARATOR = "\n\n".getBytes(StandardCharsets.UTF_8);
|
public static final byte[] BODY_SEPARATOR = "\n\n".getBytes(StandardCharsets.UTF_8);
|
||||||
|
public static final String BEACON_PORT_PROP = "io.xpipe.beacon.port";
|
||||||
|
public static final int DEFAULT_PORT = System.getProperty("os.name").startsWith("Windows") ? 21721 : 21722;
|
||||||
private static final String PRINT_MESSAGES_PROPERTY = "io.xpipe.beacon.printMessages";
|
private static final String PRINT_MESSAGES_PROPERTY = "io.xpipe.beacon.printMessages";
|
||||||
|
private static final String LAUNCH_DAEMON_IN_DEBUG_PROP = "io.xpipe.beacon.launchDebugDaemon";
|
||||||
|
private static final String ATTACH_DEBUGGER_PROP = "io.xpipe.beacon.attachDebuggerToDaemon";
|
||||||
|
private static final String EXEC_DEBUG_PROP = "io.xpipe.beacon.printDaemonOutput";
|
||||||
|
private static final String EXEC_PROCESS_PROP = "io.xpipe.beacon.customDaemonCommand";
|
||||||
|
private static final String DAEMON_ARGUMENTS_PROP = "io.xpipe.beacon.daemonArgs";
|
||||||
|
|
||||||
public static boolean printMessages() {
|
public static boolean printMessages() {
|
||||||
if (System.getProperty(PRINT_MESSAGES_PROPERTY) != null) {
|
if (System.getProperty(PRINT_MESSAGES_PROPERTY) != null) {
|
||||||
|
@ -18,8 +24,6 @@ public class BeaconConfig {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String LAUNCH_DAEMON_IN_DEBUG_PROP = "io.xpipe.beacon.launchDebugDaemon";
|
|
||||||
|
|
||||||
public static boolean launchDaemonInDebugMode() {
|
public static boolean launchDaemonInDebugMode() {
|
||||||
if (System.getProperty(LAUNCH_DAEMON_IN_DEBUG_PROP) != null) {
|
if (System.getProperty(LAUNCH_DAEMON_IN_DEBUG_PROP) != null) {
|
||||||
return Boolean.parseBoolean(System.getProperty(LAUNCH_DAEMON_IN_DEBUG_PROP));
|
return Boolean.parseBoolean(System.getProperty(LAUNCH_DAEMON_IN_DEBUG_PROP));
|
||||||
|
@ -27,8 +31,6 @@ public class BeaconConfig {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String ATTACH_DEBUGGER_PROP = "io.xpipe.beacon.attachDebuggerToDaemon";
|
|
||||||
|
|
||||||
public static boolean attachDebuggerToDaemon() {
|
public static boolean attachDebuggerToDaemon() {
|
||||||
if (System.getProperty(ATTACH_DEBUGGER_PROP) != null) {
|
if (System.getProperty(ATTACH_DEBUGGER_PROP) != null) {
|
||||||
return Boolean.parseBoolean(System.getProperty(ATTACH_DEBUGGER_PROP));
|
return Boolean.parseBoolean(System.getProperty(ATTACH_DEBUGGER_PROP));
|
||||||
|
@ -36,10 +38,6 @@ public class BeaconConfig {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static final String EXEC_DEBUG_PROP = "io.xpipe.beacon.printDaemonOutput";
|
|
||||||
|
|
||||||
public static boolean printDaemonOutput() {
|
public static boolean printDaemonOutput() {
|
||||||
if (System.getProperty(EXEC_DEBUG_PROP) != null) {
|
if (System.getProperty(EXEC_DEBUG_PROP) != null) {
|
||||||
return Boolean.parseBoolean(System.getProperty(EXEC_DEBUG_PROP));
|
return Boolean.parseBoolean(System.getProperty(EXEC_DEBUG_PROP));
|
||||||
|
@ -47,11 +45,6 @@ public class BeaconConfig {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static final String BEACON_PORT_PROP = "io.xpipe.beacon.port";
|
|
||||||
public static final int DEFAULT_PORT = System.getProperty("os.name").startsWith("Windows") ? 21721 : 21722;
|
|
||||||
|
|
||||||
public static int getUsedPort() {
|
public static int getUsedPort() {
|
||||||
if (System.getProperty(BEACON_PORT_PROP) != null) {
|
if (System.getProperty(BEACON_PORT_PROP) != null) {
|
||||||
return Integer.parseInt(System.getProperty(BEACON_PORT_PROP));
|
return Integer.parseInt(System.getProperty(BEACON_PORT_PROP));
|
||||||
|
@ -60,10 +53,6 @@ public class BeaconConfig {
|
||||||
return DEFAULT_PORT;
|
return DEFAULT_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static final String EXEC_PROCESS_PROP = "io.xpipe.beacon.customDaemonCommand";
|
|
||||||
|
|
||||||
public static String getCustomDaemonCommand() {
|
public static String getCustomDaemonCommand() {
|
||||||
if (System.getProperty(EXEC_PROCESS_PROP) != null) {
|
if (System.getProperty(EXEC_PROCESS_PROP) != null) {
|
||||||
return System.getProperty(EXEC_PROCESS_PROP);
|
return System.getProperty(EXEC_PROCESS_PROP);
|
||||||
|
@ -72,8 +61,6 @@ public class BeaconConfig {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String DAEMON_ARGUMENTS_PROP = "io.xpipe.beacon.daemonArgs";
|
|
||||||
|
|
||||||
public static String getDaemonArguments() {
|
public static String getDaemonArguments() {
|
||||||
if (System.getProperty(DAEMON_ARGUMENTS_PROP) != null) {
|
if (System.getProperty(DAEMON_ARGUMENTS_PROP) != null) {
|
||||||
return System.getProperty(DAEMON_ARGUMENTS_PROP);
|
return System.getProperty(DAEMON_ARGUMENTS_PROP);
|
||||||
|
@ -82,5 +69,3 @@ public class BeaconConfig {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import java.io.OutputStream;
|
||||||
|
|
||||||
public abstract class BeaconConnection implements AutoCloseable {
|
public abstract class BeaconConnection implements AutoCloseable {
|
||||||
|
|
||||||
|
|
||||||
protected BeaconClient beaconClient;
|
protected BeaconClient beaconClient;
|
||||||
|
|
||||||
private InputStream bodyInput;
|
private InputStream bodyInput;
|
||||||
|
@ -74,9 +73,7 @@ public abstract class BeaconConnection implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public <REQ extends RequestMessage, RES extends ResponseMessage> void performInputExchange(
|
public <REQ extends RequestMessage, RES extends ResponseMessage> void performInputExchange(
|
||||||
REQ req,
|
REQ req, BeaconClient.FailableBiConsumer<RES, InputStream, Exception> responseConsumer) {
|
||||||
BeaconClient.FailableBiConsumer<RES, InputStream, Exception> responseConsumer
|
|
||||||
) {
|
|
||||||
checkClosed();
|
checkClosed();
|
||||||
|
|
||||||
performInputOutputExchange(req, null, responseConsumer);
|
performInputOutputExchange(req, null, responseConsumer);
|
||||||
|
@ -85,8 +82,7 @@ public abstract class BeaconConnection implements AutoCloseable {
|
||||||
public <REQ extends RequestMessage, RES extends ResponseMessage> void performInputOutputExchange(
|
public <REQ extends RequestMessage, RES extends ResponseMessage> void performInputOutputExchange(
|
||||||
REQ req,
|
REQ req,
|
||||||
BeaconClient.FailableConsumer<OutputStream, IOException> reqWriter,
|
BeaconClient.FailableConsumer<OutputStream, IOException> reqWriter,
|
||||||
BeaconClient.FailableBiConsumer<RES, InputStream, Exception> responseConsumer
|
BeaconClient.FailableBiConsumer<RES, InputStream, Exception> responseConsumer) {
|
||||||
) {
|
|
||||||
checkClosed();
|
checkClosed();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -105,9 +101,7 @@ public abstract class BeaconConnection implements AutoCloseable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <REQ extends RequestMessage> void sendRequest(
|
public <REQ extends RequestMessage> void sendRequest(REQ req) {
|
||||||
REQ req
|
|
||||||
) {
|
|
||||||
checkClosed();
|
checkClosed();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -150,9 +144,7 @@ public abstract class BeaconConnection implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public <REQ extends RequestMessage, RES extends ResponseMessage> RES performOutputExchange(
|
public <REQ extends RequestMessage, RES extends ResponseMessage> RES performOutputExchange(
|
||||||
REQ req,
|
REQ req, BeaconClient.FailableConsumer<OutputStream, Exception> reqWriter) {
|
||||||
BeaconClient.FailableConsumer<OutputStream, Exception> reqWriter
|
|
||||||
) {
|
|
||||||
checkClosed();
|
checkClosed();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -166,9 +158,7 @@ public abstract class BeaconConnection implements AutoCloseable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <REQ extends RequestMessage, RES extends ResponseMessage> RES performSimpleExchange(
|
public <REQ extends RequestMessage, RES extends ResponseMessage> RES performSimpleExchange(REQ req) {
|
||||||
REQ req
|
|
||||||
) {
|
|
||||||
checkClosed();
|
checkClosed();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -192,7 +182,6 @@ public abstract class BeaconConnection implements AutoCloseable {
|
||||||
return new BeaconException("A beacon connection error occurred", s.getCause());
|
return new BeaconException("A beacon connection error occurred", s.getCause());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return new BeaconException("An unexpected error occurred", exception);
|
return new BeaconException("An unexpected error occurred", exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@ package io.xpipe.beacon;
|
||||||
*/
|
*/
|
||||||
public class BeaconException extends RuntimeException {
|
public class BeaconException extends RuntimeException {
|
||||||
|
|
||||||
public BeaconException() {
|
public BeaconException() {}
|
||||||
}
|
|
||||||
|
|
||||||
public BeaconException(String message) {
|
public BeaconException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
|
|
|
@ -34,9 +34,8 @@ public class BeaconServer {
|
||||||
public static Process tryStartCustom() throws Exception {
|
public static Process tryStartCustom() throws Exception {
|
||||||
var custom = BeaconConfig.getCustomDaemonCommand();
|
var custom = BeaconConfig.getCustomDaemonCommand();
|
||||||
if (custom != null) {
|
if (custom != null) {
|
||||||
var command = custom + " " + (BeaconConfig.getDaemonArguments() != null ?
|
var command =
|
||||||
BeaconConfig.getDaemonArguments() :
|
custom + " " + (BeaconConfig.getDaemonArguments() != null ? BeaconConfig.getDaemonArguments() : "");
|
||||||
"");
|
|
||||||
Process process = Runtime.getRuntime().exec(command);
|
Process process = Runtime.getRuntime().exec(command);
|
||||||
printDaemonOutput(process, command);
|
printDaemonOutput(process, command);
|
||||||
return process;
|
return process;
|
||||||
|
@ -47,9 +46,8 @@ public class BeaconServer {
|
||||||
public static Process tryStart() throws Exception {
|
public static Process tryStart() throws Exception {
|
||||||
var daemonExecutable = getDaemonExecutable();
|
var daemonExecutable = getDaemonExecutable();
|
||||||
if (daemonExecutable.isPresent()) {
|
if (daemonExecutable.isPresent()) {
|
||||||
var command = "\"" + daemonExecutable.get() + "\" --external " + (BeaconConfig.getDaemonArguments() != null ?
|
var command = "\"" + daemonExecutable.get() + "\" --external "
|
||||||
BeaconConfig.getDaemonArguments() :
|
+ (BeaconConfig.getDaemonArguments() != null ? BeaconConfig.getDaemonArguments() : "");
|
||||||
"");
|
|
||||||
// Tell daemon that we launched from an external tool
|
// Tell daemon that we launched from an external tool
|
||||||
Process process = Runtime.getRuntime().exec(command);
|
Process process = Runtime.getRuntime().exec(command);
|
||||||
printDaemonOutput(process, command);
|
printDaemonOutput(process, command);
|
||||||
|
@ -65,35 +63,43 @@ public class BeaconServer {
|
||||||
System.out.println("Starting daemon: " + command);
|
System.out.println("Starting daemon: " + command);
|
||||||
}
|
}
|
||||||
|
|
||||||
new Thread(null, () -> {
|
new Thread(
|
||||||
try {
|
null,
|
||||||
InputStreamReader isr = new InputStreamReader(proc.getInputStream());
|
() -> {
|
||||||
BufferedReader br = new BufferedReader(isr);
|
try {
|
||||||
String line;
|
InputStreamReader isr = new InputStreamReader(proc.getInputStream());
|
||||||
while ((line = br.readLine()) != null) {
|
BufferedReader br = new BufferedReader(isr);
|
||||||
if (print) {
|
String line;
|
||||||
System.out.println("[xpiped] " + line);
|
while ((line = br.readLine()) != null) {
|
||||||
}
|
if (print) {
|
||||||
}
|
System.out.println("[xpiped] " + line);
|
||||||
} catch (Exception ioe) {
|
}
|
||||||
ioe.printStackTrace();
|
}
|
||||||
}
|
} catch (Exception ioe) {
|
||||||
}, "daemon sysout").start();
|
ioe.printStackTrace();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"daemon sysout")
|
||||||
|
.start();
|
||||||
|
|
||||||
new Thread(null, () -> {
|
new Thread(
|
||||||
try {
|
null,
|
||||||
InputStreamReader isr = new InputStreamReader(proc.getErrorStream());
|
() -> {
|
||||||
BufferedReader br = new BufferedReader(isr);
|
try {
|
||||||
String line;
|
InputStreamReader isr = new InputStreamReader(proc.getErrorStream());
|
||||||
while ((line = br.readLine()) != null) {
|
BufferedReader br = new BufferedReader(isr);
|
||||||
if (print) {
|
String line;
|
||||||
System.err.println("[xpiped] " + line);
|
while ((line = br.readLine()) != null) {
|
||||||
}
|
if (print) {
|
||||||
}
|
System.err.println("[xpiped] " + line);
|
||||||
} catch (Exception ioe) {
|
}
|
||||||
ioe.printStackTrace();
|
}
|
||||||
}
|
} catch (Exception ioe) {
|
||||||
}, "daemon syserr").start();
|
ioe.printStackTrace();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"daemon syserr")
|
||||||
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean tryStop(BeaconClient client) throws Exception {
|
public static boolean tryStop(BeaconClient client) throws Exception {
|
||||||
|
@ -111,7 +117,6 @@ public class BeaconServer {
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (base == null) {
|
if (base == null) {
|
||||||
if (System.getProperty("os.name").startsWith("Windows")) {
|
if (System.getProperty("os.name").startsWith("Windows")) {
|
||||||
base = Path.of(System.getenv("LOCALAPPDATA"), "X-Pipe");
|
base = Path.of(System.getenv("LOCALAPPDATA"), "X-Pipe");
|
||||||
|
|
|
@ -5,8 +5,7 @@ package io.xpipe.beacon;
|
||||||
*/
|
*/
|
||||||
public class ClientException extends Exception {
|
public class ClientException extends Exception {
|
||||||
|
|
||||||
public ClientException() {
|
public ClientException() {}
|
||||||
}
|
|
||||||
|
|
||||||
public ClientException(String message) {
|
public ClientException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
|
|
|
@ -5,8 +5,7 @@ package io.xpipe.beacon;
|
||||||
*/
|
*/
|
||||||
public class ConnectorException extends Exception {
|
public class ConnectorException extends Exception {
|
||||||
|
|
||||||
public ConnectorException() {
|
public ConnectorException() {}
|
||||||
}
|
|
||||||
|
|
||||||
public ConnectorException(String message) {
|
public ConnectorException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
public interface RequestMessage {
|
public interface RequestMessage {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
package io.xpipe.beacon;
|
package io.xpipe.beacon;
|
||||||
|
|
||||||
public interface ResponseMessage {
|
public interface ResponseMessage {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,8 +5,7 @@ package io.xpipe.beacon;
|
||||||
*/
|
*/
|
||||||
public class ServerException extends Exception {
|
public class ServerException extends Exception {
|
||||||
|
|
||||||
public ServerException() {
|
public ServerException() {}
|
||||||
}
|
|
||||||
|
|
||||||
public ServerException(String message) {
|
public ServerException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
|
|
|
@ -21,7 +21,9 @@ public class AddSourceExchange implements MessageExchange {
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {
|
||||||
DataSourceId target;
|
DataSourceId target;
|
||||||
@NonNull DataSource<?> source;
|
|
||||||
|
@NonNull
|
||||||
|
DataSource<?> source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
|
|
|
@ -31,6 +31,5 @@ public class ForwardExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ public class MessageExchanges {
|
||||||
private static void loadAll() {
|
private static void loadAll() {
|
||||||
if (ALL == null) {
|
if (ALL == null) {
|
||||||
ALL = ServiceLoader.load(MessageExchange.class).stream()
|
ALL = ServiceLoader.load(MessageExchange.class).stream()
|
||||||
.map(ServiceLoader.Provider::get).collect(Collectors.toSet());
|
.map(ServiceLoader.Provider::get)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,12 +27,16 @@ public class MessageExchanges {
|
||||||
|
|
||||||
public static <RQ extends RequestMessage> Optional<MessageExchange> byRequest(RQ req) {
|
public static <RQ extends RequestMessage> Optional<MessageExchange> byRequest(RQ req) {
|
||||||
loadAll();
|
loadAll();
|
||||||
return ALL.stream().filter(d -> d.getRequestClass().equals(req.getClass())).findAny();
|
return ALL.stream()
|
||||||
|
.filter(d -> d.getRequestClass().equals(req.getClass()))
|
||||||
|
.findAny();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <RP extends ResponseMessage> Optional<MessageExchange> byResponse(RP rep) {
|
public static <RP extends ResponseMessage> Optional<MessageExchange> byResponse(RP rep) {
|
||||||
loadAll();
|
loadAll();
|
||||||
return ALL.stream().filter(d -> d.getResponseClass().equals(rep.getClass())).findAny();
|
return ALL.stream()
|
||||||
|
.filter(d -> d.getResponseClass().equals(rep.getClass()))
|
||||||
|
.findAny();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<MessageExchange> getAll() {
|
public static Set<MessageExchange> getAll() {
|
||||||
|
|
|
@ -37,14 +37,18 @@ public class QueryDataSourceExchange implements MessageExchange {
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {
|
||||||
@NonNull
|
@NonNull
|
||||||
DataSourceId id;
|
DataSourceId id;
|
||||||
|
|
||||||
boolean disabled;
|
boolean disabled;
|
||||||
boolean hidden;
|
boolean hidden;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
DataSourceInfo info;
|
DataSourceInfo info;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
String storeDisplay;
|
String storeDisplay;
|
||||||
|
|
||||||
String provider;
|
String provider;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
Map<String, String> config;
|
Map<String, String> config;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,5 @@ public class ReadExecuteExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,7 @@ public class StopExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {}
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
|
|
|
@ -20,8 +20,7 @@ public class StoreStreamExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {}
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.api;
|
package io.xpipe.beacon.exchange.api;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
@ -29,6 +29,5 @@ public class QueryRawDataExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.api;
|
package io.xpipe.beacon.exchange.api;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
@ -32,6 +32,5 @@ public class QueryTableDataExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.api;
|
package io.xpipe.beacon.exchange.api;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
@ -30,6 +30,5 @@ public class QueryTextDataExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.core.dialog.DialogReference;
|
import io.xpipe.core.dialog.DialogReference;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.core.dialog.DialogElement;
|
import io.xpipe.core.dialog.DialogElement;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
@ -34,6 +34,7 @@ public class DialogExchange implements MessageExchange {
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {
|
||||||
@NonNull
|
@NonNull
|
||||||
UUID dialogKey;
|
UUID dialogKey;
|
||||||
|
|
||||||
String value;
|
String value;
|
||||||
boolean cancel;
|
boolean cancel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ public class EditStoreExchange implements MessageExchange {
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {
|
||||||
@NonNull DialogReference dialog;
|
@NonNull
|
||||||
|
DialogReference dialog;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,7 @@ public class InstanceExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.exchange.data.CollectionListEntry;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
|
import io.xpipe.beacon.exchange.data.CollectionListEntry;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
@ -20,9 +20,7 @@ public class ListCollectionsExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.exchange.data.EntryListEntry;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
|
import io.xpipe.beacon.exchange.data.EntryListEntry;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.exchange.data.StoreListEntry;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
|
import io.xpipe.beacon.exchange.data.StoreListEntry;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
@ -20,9 +20,7 @@ public class ListStoresExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
@ -26,7 +26,5 @@ public class ModeExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
@ -26,6 +26,5 @@ public class RemoveCollectionExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
@ -28,6 +28,5 @@ public class RemoveStoreExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
@ -21,6 +21,7 @@ public class RenameCollectionExchange implements MessageExchange {
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {
|
||||||
@NonNull
|
@NonNull
|
||||||
String collectionName;
|
String collectionName;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
String newName;
|
String newName;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +29,5 @@ public class RenameCollectionExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.core.source.DataSourceId;
|
import io.xpipe.core.source.DataSourceId;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
@ -32,6 +32,7 @@ public class RenameEntryExchange implements MessageExchange {
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {
|
||||||
@NonNull DataSourceId newId;
|
@NonNull
|
||||||
|
DataSourceId newId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
@ -21,6 +21,7 @@ public class RenameStoreExchange implements MessageExchange {
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {
|
||||||
@NonNull
|
@NonNull
|
||||||
String storeName;
|
String storeName;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
String newName;
|
String newName;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +29,5 @@ public class RenameStoreExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
@ -27,6 +27,5 @@ public class SelectExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.exchange.data.ProviderEntry;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
|
import io.xpipe.beacon.exchange.data.ProviderEntry;
|
||||||
import io.xpipe.core.source.DataSourceType;
|
import io.xpipe.core.source.DataSourceType;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
@ -23,13 +23,13 @@ public class SourceProviderListExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {}
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {
|
||||||
@NonNull Map<DataSourceType, List<ProviderEntry>> entries;
|
@NonNull
|
||||||
|
Map<DataSourceType, List<ProviderEntry>> entries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
@ -17,8 +17,7 @@ public class StatusExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {}
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.core.dialog.DialogReference;
|
import io.xpipe.core.dialog.DialogReference;
|
||||||
import io.xpipe.core.store.DataStore;
|
import io.xpipe.core.store.DataStore;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
|
|
|
@ -21,13 +21,13 @@ public class StoreProviderListExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {}
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {
|
||||||
@NonNull List<ProviderEntry> entries;
|
@NonNull
|
||||||
|
List<ProviderEntry> entries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
@ -17,9 +17,7 @@ public class VersionExchange implements MessageExchange {
|
||||||
@lombok.extern.jackson.Jacksonized
|
@lombok.extern.jackson.Jacksonized
|
||||||
@lombok.Builder
|
@lombok.Builder
|
||||||
@lombok.Value
|
@lombok.Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.xpipe.beacon.exchange.cli;
|
package io.xpipe.beacon.exchange.cli;
|
||||||
|
|
||||||
import io.xpipe.beacon.exchange.MessageExchange;
|
|
||||||
import io.xpipe.beacon.RequestMessage;
|
import io.xpipe.beacon.RequestMessage;
|
||||||
import io.xpipe.beacon.ResponseMessage;
|
import io.xpipe.beacon.ResponseMessage;
|
||||||
|
import io.xpipe.beacon.exchange.MessageExchange;
|
||||||
import io.xpipe.core.source.DataSourceReference;
|
import io.xpipe.core.source.DataSourceReference;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
@ -35,6 +35,5 @@ public class WriteExecuteExchange implements MessageExchange {
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
@Builder
|
@Builder
|
||||||
@Value
|
@Value
|
||||||
public static class Response implements ResponseMessage {
|
public static class Response implements ResponseMessage {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,10 @@ public class WritePreparationExchange implements MessageExchange {
|
||||||
@Value
|
@Value
|
||||||
public static class Request implements RequestMessage {
|
public static class Request implements RequestMessage {
|
||||||
String type;
|
String type;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
DataStore output;
|
DataStore output;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
DataSourceReference source;
|
DataSourceReference source;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import io.xpipe.beacon.exchange.*;
|
import io.xpipe.beacon.exchange.*;
|
||||||
import io.xpipe.beacon.exchange.api.*;
|
import io.xpipe.beacon.exchange.api.QueryRawDataExchange;
|
||||||
|
import io.xpipe.beacon.exchange.api.QueryTableDataExchange;
|
||||||
|
import io.xpipe.beacon.exchange.api.QueryTextDataExchange;
|
||||||
import io.xpipe.beacon.exchange.cli.*;
|
import io.xpipe.beacon.exchange.cli.*;
|
||||||
|
|
||||||
module io.xpipe.beacon {
|
module io.xpipe.beacon {
|
||||||
|
@ -21,6 +23,7 @@ module io.xpipe.beacon {
|
||||||
requires static lombok;
|
requires static lombok;
|
||||||
|
|
||||||
uses MessageExchange;
|
uses MessageExchange;
|
||||||
|
|
||||||
provides io.xpipe.beacon.exchange.MessageExchange with
|
provides io.xpipe.beacon.exchange.MessageExchange with
|
||||||
ForwardExchange,
|
ForwardExchange,
|
||||||
InstanceExchange,
|
InstanceExchange,
|
||||||
|
|
|
@ -13,7 +13,7 @@ compileJava {
|
||||||
options.compilerArgs << '-parameters'
|
options.compilerArgs << '-parameters'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies {
|
||||||
api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "2.13.0"
|
api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "2.13.0"
|
||||||
implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-parameter-names', version: "2.13.0"
|
implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-parameter-names', version: "2.13.0"
|
||||||
implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: "2.13.0"
|
implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: "2.13.0"
|
||||||
|
|
|
@ -4,7 +4,10 @@ import io.xpipe.core.store.FileStore;
|
||||||
import io.xpipe.core.store.StreamDataStore;
|
import io.xpipe.core.store.StreamDataStore;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.CharBuffer;
|
import java.nio.CharBuffer;
|
||||||
import java.nio.charset.*;
|
import java.nio.charset.*;
|
||||||
|
@ -15,8 +18,12 @@ import java.util.Map;
|
||||||
|
|
||||||
public abstract class Charsetter {
|
public abstract class Charsetter {
|
||||||
|
|
||||||
|
private static final int MAX_BYTES = 8192;
|
||||||
|
public static Charsetter INSTANCE;
|
||||||
private static CharsetterUniverse universe;
|
private static CharsetterUniverse universe;
|
||||||
|
|
||||||
|
protected Charsetter() {}
|
||||||
|
|
||||||
protected static void checkInit() {
|
protected static void checkInit() {
|
||||||
if (universe == null) {
|
if (universe == null) {
|
||||||
throw new IllegalStateException("Charsetter not initialized");
|
throw new IllegalStateException("Charsetter not initialized");
|
||||||
|
@ -27,30 +34,25 @@ public abstract class Charsetter {
|
||||||
universe = CharsetterUniverse.create(ctx);
|
universe = CharsetterUniverse.create(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Value
|
|
||||||
public static class Result {
|
|
||||||
StreamCharset charset;
|
|
||||||
NewLine newLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Charsetter() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Charsetter INSTANCE;
|
|
||||||
|
|
||||||
public static Charsetter get() {
|
public static Charsetter get() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
private static int count(byte[] outerArray, byte[] smallerArray) {
|
||||||
public interface FailableSupplier<R, E extends Throwable> {
|
int count = 0;
|
||||||
R get() throws E;
|
for (int i = 0; i < outerArray.length - smallerArray.length + 1; ++i) {
|
||||||
}
|
boolean found = true;
|
||||||
|
for (int j = 0; j < smallerArray.length; ++j) {
|
||||||
@FunctionalInterface
|
if (outerArray[i + j] != smallerArray[j]) {
|
||||||
public interface FailableConsumer<T, E extends Throwable> {
|
found = false;
|
||||||
|
break;
|
||||||
void accept(T var1) throws E;
|
}
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferedReader reader(StreamDataStore store, StreamCharset charset) throws Exception {
|
public BufferedReader reader(StreamDataStore store, StreamCharset charset) throws Exception {
|
||||||
|
@ -73,16 +75,15 @@ public abstract class Charsetter {
|
||||||
return new BufferedReader(new InputStreamReader(stream, charset.getCharset()));
|
return new BufferedReader(new InputStreamReader(stream, charset.getCharset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Result read(FailableSupplier<InputStream, Exception> in, FailableConsumer<InputStreamReader, Exception> con) throws Exception;
|
public abstract Result read(
|
||||||
|
FailableSupplier<InputStream, Exception> in, FailableConsumer<InputStreamReader, Exception> con)
|
||||||
private static final int MAX_BYTES = 8192;
|
throws Exception;
|
||||||
|
|
||||||
public Result detect(StreamDataStore store) throws Exception {
|
public Result detect(StreamDataStore store) throws Exception {
|
||||||
Result result = new Result(null, null);
|
Result result = new Result(null, null);
|
||||||
|
|
||||||
if (store.canOpen()) {
|
if (store.canOpen()) {
|
||||||
|
|
||||||
|
|
||||||
try (InputStream inputStream = store.openBufferedInput()) {
|
try (InputStream inputStream = store.openBufferedInput()) {
|
||||||
StreamCharset detected = null;
|
StreamCharset detected = null;
|
||||||
for (var charset : StreamCharset.COMMON) {
|
for (var charset : StreamCharset.COMMON) {
|
||||||
|
@ -135,25 +136,10 @@ public abstract class Charsetter {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return count.entrySet().stream().min(Comparator.comparingInt(Map.Entry::getValue))
|
return count.entrySet().stream()
|
||||||
.orElseThrow().getKey();
|
.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) {
|
public Charset inferCharset(byte[] content) {
|
||||||
|
@ -179,4 +165,21 @@ public abstract class Charsetter {
|
||||||
|
|
||||||
return StandardCharsets.UTF_8;
|
return StandardCharsets.UTF_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Value
|
||||||
|
public static class Result {
|
||||||
|
StreamCharset charset;
|
||||||
|
NewLine newLine;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,15 +11,13 @@ import java.util.Locale;
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class CharsetterContext {
|
public class CharsetterContext {
|
||||||
|
|
||||||
public static CharsetterContext empty() {
|
|
||||||
return new CharsetterContext(Charset.defaultCharset().name(), Locale.getDefault(), Locale.getDefault(), List.of());
|
|
||||||
}
|
|
||||||
|
|
||||||
String systemCharsetName;
|
String systemCharsetName;
|
||||||
|
|
||||||
Locale systemLocale;
|
Locale systemLocale;
|
||||||
|
|
||||||
Locale appLocale;
|
Locale appLocale;
|
||||||
|
|
||||||
List<String> observedCharsets;
|
List<String> observedCharsets;
|
||||||
|
|
||||||
|
public static CharsetterContext empty() {
|
||||||
|
return new CharsetterContext(
|
||||||
|
Charset.defaultCharset().name(), Locale.getDefault(), Locale.getDefault(), List.of());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,24 +5,11 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public enum NewLine {
|
public enum NewLine {
|
||||||
|
|
||||||
@JsonProperty("lf")
|
@JsonProperty("lf")
|
||||||
LF("\n", "lf"),
|
LF("\n", "lf"),
|
||||||
@JsonProperty("crlf")
|
@JsonProperty("crlf")
|
||||||
CRLF("\r\n", "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 newLine;
|
||||||
private final String id;
|
private final String id;
|
||||||
|
|
||||||
|
@ -31,6 +18,20 @@ public enum NewLine {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
public String getNewLine() {
|
public String getNewLine() {
|
||||||
return newLine;
|
return newLine;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,42 @@ import java.util.stream.Stream;
|
||||||
@Value
|
@Value
|
||||||
public class StreamCharset {
|
public class StreamCharset {
|
||||||
|
|
||||||
|
public static final StreamCharset UTF8 = new StreamCharset(StandardCharsets.UTF_8, null);
|
||||||
|
public static final StreamCharset UTF8_BOM =
|
||||||
|
new StreamCharset(StandardCharsets.UTF_8, new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
|
||||||
|
public static final StreamCharset UTF16 = new StreamCharset(StandardCharsets.UTF_16, null);
|
||||||
|
public static final StreamCharset UTF16_BOM =
|
||||||
|
new StreamCharset(StandardCharsets.UTF_16, new byte[] {(byte) 0xFE, (byte) 0xFF});
|
||||||
|
public static final StreamCharset UTF16_LE = new StreamCharset(StandardCharsets.UTF_16LE, null);
|
||||||
|
public static final StreamCharset UTF16_LE_BOM =
|
||||||
|
new StreamCharset(StandardCharsets.UTF_16LE, new byte[] {(byte) 0xFF, (byte) 0xFE});
|
||||||
|
public static final StreamCharset UTF32 = new StreamCharset(Charset.forName("utf-32"), null);
|
||||||
|
public static final StreamCharset UTF32_BOM =
|
||||||
|
new StreamCharset(Charset.forName("utf-32"), new byte[] {0x00, 0x00, (byte) 0xFE, (byte) 0xFF});
|
||||||
|
public static final List<StreamCharset> COMMON = List.of(
|
||||||
|
UTF8,
|
||||||
|
UTF8_BOM,
|
||||||
|
UTF16,
|
||||||
|
UTF16_BOM,
|
||||||
|
UTF16_LE,
|
||||||
|
UTF16_LE_BOM,
|
||||||
|
UTF32,
|
||||||
|
UTF32_BOM,
|
||||||
|
new StreamCharset(StandardCharsets.US_ASCII, null),
|
||||||
|
new StreamCharset(StandardCharsets.ISO_8859_1, null),
|
||||||
|
new StreamCharset(Charset.forName("Windows-1251"), null),
|
||||||
|
new StreamCharset(Charset.forName("Windows-1252"), null));
|
||||||
|
public static final List<StreamCharset> RARE = Charset.availableCharsets().values().stream()
|
||||||
|
.filter(charset -> COMMON.stream().noneMatch(c -> c.getCharset().equals(charset)))
|
||||||
|
.map(charset -> new StreamCharset(charset, null))
|
||||||
|
.toList();
|
||||||
|
Charset charset;
|
||||||
|
byte[] byteOrderMark;
|
||||||
|
|
||||||
public static StreamCharset get(Charset charset, boolean byteOrderMark) {
|
public static StreamCharset get(Charset charset, boolean byteOrderMark) {
|
||||||
return Stream.concat(COMMON.stream(), RARE.stream())
|
return Stream.concat(COMMON.stream(), RARE.stream())
|
||||||
.filter(streamCharset -> streamCharset.getCharset()
|
.filter(streamCharset ->
|
||||||
.equals(charset) && streamCharset.hasByteOrderMark() == byteOrderMark)
|
streamCharset.getCharset().equals(charset) && streamCharset.hasByteOrderMark() == byteOrderMark)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow();
|
.orElseThrow();
|
||||||
}
|
}
|
||||||
|
@ -24,66 +56,15 @@ public class StreamCharset {
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public static StreamCharset get(String s) {
|
public static StreamCharset get(String s) {
|
||||||
var byteOrderMark = s.endsWith("-bom");
|
var byteOrderMark = s.endsWith("-bom");
|
||||||
var charset = Charset.forName(s.substring(
|
var charset = Charset.forName(s.substring(0, s.length() - (byteOrderMark ? 4 : 0)));
|
||||||
0, s.length() - (byteOrderMark ?
|
|
||||||
4 :
|
|
||||||
0)));
|
|
||||||
return StreamCharset.get(charset, byteOrderMark);
|
return StreamCharset.get(charset, byteOrderMark);
|
||||||
}
|
}
|
||||||
|
|
||||||
Charset charset;
|
|
||||||
byte[] byteOrderMark;
|
|
||||||
|
|
||||||
@JsonValue
|
@JsonValue
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getCharset()
|
return getCharset().name().toLowerCase(Locale.ROOT) + (hasByteOrderMark() ? "-bom" : "");
|
||||||
.name().toLowerCase(Locale.ROOT) + (hasByteOrderMark() ?
|
|
||||||
"-bom" :
|
|
||||||
"");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final StreamCharset UTF8 = new StreamCharset(StandardCharsets.UTF_8, null);
|
|
||||||
public static final StreamCharset UTF8_BOM = new StreamCharset(StandardCharsets.UTF_8, new byte[]{
|
|
||||||
(byte) 0xEF,
|
|
||||||
(byte) 0xBB,
|
|
||||||
(byte) 0xBF
|
|
||||||
});
|
|
||||||
|
|
||||||
public static final StreamCharset UTF16 = new StreamCharset(StandardCharsets.UTF_16, null);
|
|
||||||
public static final StreamCharset UTF16_BOM = new StreamCharset(StandardCharsets.UTF_16, new byte[]{
|
|
||||||
(byte) 0xFE,
|
|
||||||
(byte) 0xFF
|
|
||||||
});
|
|
||||||
|
|
||||||
public static final StreamCharset UTF16_LE = new StreamCharset(StandardCharsets.UTF_16LE, null);
|
|
||||||
public static final StreamCharset UTF16_LE_BOM = new StreamCharset(StandardCharsets.UTF_16LE, new byte[]{
|
|
||||||
(byte) 0xFF,
|
|
||||||
(byte) 0xFE
|
|
||||||
});
|
|
||||||
|
|
||||||
public static final StreamCharset UTF32 = new StreamCharset(Charset.forName("utf-32"), null);
|
|
||||||
public static final StreamCharset UTF32_BOM = new StreamCharset(Charset.forName("utf-32"), new byte[]{
|
|
||||||
0x00,
|
|
||||||
0x00,
|
|
||||||
(byte) 0xFE,
|
|
||||||
(byte) 0xFF
|
|
||||||
});
|
|
||||||
|
|
||||||
public static final List<StreamCharset> COMMON = List.of(
|
|
||||||
UTF8, UTF8_BOM, UTF16, UTF16_BOM, UTF16_LE, UTF16_LE_BOM, UTF32, UTF32_BOM, new StreamCharset(StandardCharsets.US_ASCII, null),
|
|
||||||
new StreamCharset(StandardCharsets.ISO_8859_1, null),
|
|
||||||
new StreamCharset(Charset.forName("Windows-1251"), null), new StreamCharset(Charset.forName("Windows-1252"), null)
|
|
||||||
);
|
|
||||||
|
|
||||||
public static final List<StreamCharset> RARE = Charset.availableCharsets()
|
|
||||||
.values()
|
|
||||||
.stream()
|
|
||||||
.filter(charset -> COMMON.stream()
|
|
||||||
.noneMatch(c -> c.getCharset()
|
|
||||||
.equals(charset)))
|
|
||||||
.map(charset -> new StreamCharset(charset, null))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
public boolean hasByteOrderMark() {
|
public boolean hasByteOrderMark() {
|
||||||
return byteOrderMark != null;
|
return byteOrderMark != null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package io.xpipe.core.data.generic;
|
package io.xpipe.core.data.generic;
|
||||||
|
|
||||||
import io.xpipe.core.data.node.DataStructureNode;
|
|
||||||
import io.xpipe.core.data.node.ArrayNode;
|
import io.xpipe.core.data.node.ArrayNode;
|
||||||
|
import io.xpipe.core.data.node.DataStructureNode;
|
||||||
import io.xpipe.core.data.node.ValueNode;
|
import io.xpipe.core.data.node.ValueNode;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -16,8 +16,8 @@ public class GenericArrayReader implements GenericAbstractReader {
|
||||||
private int currentIndex = 0;
|
private int currentIndex = 0;
|
||||||
private GenericAbstractReader currentReader;
|
private GenericAbstractReader currentReader;
|
||||||
private DataStructureNode created;
|
private DataStructureNode created;
|
||||||
public GenericArrayReader() {
|
|
||||||
}
|
public GenericArrayReader() {}
|
||||||
|
|
||||||
public static GenericArrayReader newReader(int length) {
|
public static GenericArrayReader newReader(int length) {
|
||||||
var ar = new GenericArrayReader();
|
var ar = new GenericArrayReader();
|
||||||
|
|
|
@ -4,22 +4,15 @@ import java.util.Map;
|
||||||
|
|
||||||
public interface GenericDataStreamCallback {
|
public interface GenericDataStreamCallback {
|
||||||
|
|
||||||
default void onName(String name) {
|
default void onName(String name) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onArrayStart(int length) {
|
default void onArrayStart(int length) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onArrayEnd(Map<Integer, String> metaAttributes) {
|
default void onArrayEnd(Map<Integer, String> metaAttributes) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onTupleStart(int length) {
|
default void onTupleStart(int length) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onTupleEnd(Map<Integer, String> metaAttributes) {
|
default void onTupleEnd(Map<Integer, String> metaAttributes) {}
|
||||||
}
|
|
||||||
|
|
||||||
|
default void onValue(byte[] value, Map<Integer, String> metaAttributes) {}
|
||||||
default void onValue(byte[] value, Map<Integer, String> metaAttributes) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,6 @@ public class GenericDataStructureNodeReader implements GenericDataStreamCallback
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
node = ValueNode.of(value).tag(metaAttributes);
|
node = ValueNode.of(value).tag(metaAttributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ public class GenericTupleReader implements GenericAbstractReader {
|
||||||
private int currentIndex = 0;
|
private int currentIndex = 0;
|
||||||
private GenericAbstractReader currentReader;
|
private GenericAbstractReader currentReader;
|
||||||
private DataStructureNode created;
|
private DataStructureNode created;
|
||||||
public GenericTupleReader() {
|
|
||||||
}
|
public GenericTupleReader() {}
|
||||||
|
|
||||||
public static GenericTupleReader newReader(int length) {
|
public static GenericTupleReader newReader(int length) {
|
||||||
var tr = new GenericTupleReader();
|
var tr = new GenericTupleReader();
|
||||||
|
|
|
@ -8,6 +8,8 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class ArrayNode extends DataStructureNode {
|
public abstract class ArrayNode extends DataStructureNode {
|
||||||
|
|
||||||
|
protected ArrayNode() {}
|
||||||
|
|
||||||
public static ArrayNode empty() {
|
public static ArrayNode empty() {
|
||||||
return of(List.of());
|
return of(List.of());
|
||||||
}
|
}
|
||||||
|
@ -20,9 +22,6 @@ public abstract class ArrayNode extends DataStructureNode {
|
||||||
return new SimpleArrayNode(nodes);
|
return new SimpleArrayNode(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ArrayNode() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
|
@ -32,7 +31,8 @@ public abstract class ArrayNode extends DataStructureNode {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var toReturn = getNodes().equals(that.getNodes()) && Objects.equals(getMetaAttributes(), that.getMetaAttributes());
|
var toReturn =
|
||||||
|
getNodes().equals(that.getNodes()) && Objects.equals(getMetaAttributes(), that.getMetaAttributes());
|
||||||
|
|
||||||
// Useful for debugging
|
// Useful for debugging
|
||||||
if (toReturn == false) {
|
if (toReturn == false) {
|
||||||
|
@ -64,6 +64,7 @@ public abstract class ArrayNode extends DataStructureNode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final ArrayType determineDataType() {
|
public final ArrayType determineDataType() {
|
||||||
return ArrayType.ofSharedType(getNodes().stream().map(DataStructureNode::determineDataType).toList());
|
return ArrayType.ofSharedType(
|
||||||
|
getNodes().stream().map(DataStructureNode::determineDataType).toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,6 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getMetaAttribute(Integer key) {
|
public String getMetaAttribute(Integer key) {
|
||||||
if (metaAttributes == null) {
|
if (metaAttributes == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -104,9 +103,6 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
|
||||||
throw unsupported("get nodes");
|
throw unsupported("get nodes");
|
||||||
}
|
}
|
||||||
|
|
||||||
public record KeyValue(String key, DataStructureNode value) {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract String getName();
|
protected abstract String getName();
|
||||||
|
|
||||||
protected UnsupportedOperationException unsupported(String s) {
|
protected UnsupportedOperationException unsupported(String s) {
|
||||||
|
@ -125,12 +121,15 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String metaToString() {
|
public String metaToString() {
|
||||||
return "(" + (metaAttributes != null ?
|
return "("
|
||||||
metaAttributes.entrySet()
|
+ (metaAttributes != null
|
||||||
.stream()
|
? metaAttributes.entrySet().stream()
|
||||||
.map(e -> e.getValue() != null ? e.getKey() + ":" + e.getValue() : e.getKey().toString())
|
.map(e -> e.getValue() != null
|
||||||
.collect(Collectors.joining("|")) :
|
? e.getKey() + ":" + e.getValue()
|
||||||
"") + ")";
|
: e.getKey().toString())
|
||||||
|
.collect(Collectors.joining("|"))
|
||||||
|
: "")
|
||||||
|
+ ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract String toString(int indent);
|
public abstract String toString(int indent);
|
||||||
|
@ -146,11 +145,11 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
|
||||||
public boolean isValue() {
|
public boolean isValue() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataStructureNode set(int index, DataStructureNode node) {
|
public DataStructureNode set(int index, DataStructureNode node) {
|
||||||
throw unsupported("set at index");
|
throw unsupported("set at index");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final ValueNode asValue() {
|
public final ValueNode asValue() {
|
||||||
if (!isValue()) {
|
if (!isValue()) {
|
||||||
throw new UnsupportedOperationException(getName() + " is not a value node");
|
throw new UnsupportedOperationException(getName() + " is not a value node");
|
||||||
|
@ -235,4 +234,6 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
|
||||||
public Iterator<DataStructureNode> iterator() {
|
public Iterator<DataStructureNode> iterator() {
|
||||||
throw unsupported("iterator creation");
|
throw unsupported("iterator creation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record KeyValue(String key, DataStructureNode value) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,9 +152,7 @@ public class DataStructureNodePointer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataStructureNode tryMatch(DataStructureNode n) {
|
public DataStructureNode tryMatch(DataStructureNode n) {
|
||||||
var res = n.stream()
|
var res = n.stream().filter(selector).findAny();
|
||||||
.filter(selector)
|
|
||||||
.findAny();
|
|
||||||
return res.orElse(null);
|
return res.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +182,6 @@ public class DataStructureNodePointer {
|
||||||
return new Builder(new ArrayList<>(path));
|
return new Builder(new ArrayList<>(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Builder name(String name) {
|
public Builder name(String name) {
|
||||||
path.add(new NameElement(name));
|
path.add(new NameElement(name));
|
||||||
return this;
|
return this;
|
||||||
|
@ -219,7 +216,8 @@ public class DataStructureNodePointer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder pointerEvaluation(DataStructureNodePointer pointer, Function<DataStructureNode, String> converter) {
|
public Builder pointerEvaluation(
|
||||||
|
DataStructureNodePointer pointer, Function<DataStructureNode, String> converter) {
|
||||||
path.add(new FunctionElement((current) -> {
|
path.add(new FunctionElement((current) -> {
|
||||||
var res = pointer.get(current);
|
var res = pointer.get(current);
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
|
|
|
@ -84,7 +84,9 @@ public class LinkedTupleNode extends TupleNode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType determineDataType() {
|
public DataType determineDataType() {
|
||||||
return TupleType.of(getKeyNames(), getNodes().stream().map(DataStructureNode::determineDataType).toList());
|
return TupleType.of(
|
||||||
|
getKeyNames(),
|
||||||
|
getNodes().stream().map(DataStructureNode::determineDataType).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -142,7 +144,6 @@ public class LinkedTupleNode extends TupleNode {
|
||||||
return "LinkedTupleNode(" + size() + ")";
|
return "LinkedTupleNode(" + size() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return tupleNodes.stream().mapToInt(TupleNode::size).sum();
|
return tupleNodes.stream().mapToInt(TupleNode::size).sum();
|
||||||
|
@ -174,6 +175,7 @@ public class LinkedTupleNode extends TupleNode {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LinkedTupleNode(tupleNodes.stream().map(n -> n.isMutable() ? n : n.mutable()).toList());
|
return new LinkedTupleNode(
|
||||||
|
tupleNodes.stream().map(n -> n.isMutable() ? n : n.mutable()).toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,6 @@ import java.util.function.Consumer;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
|
||||||
|
|
||||||
public class SimpleArrayNode extends ArrayNode {
|
public class SimpleArrayNode extends ArrayNode {
|
||||||
|
|
||||||
List<DataStructureNode> nodes;
|
List<DataStructureNode> nodes;
|
||||||
|
@ -79,6 +77,4 @@ public class SimpleArrayNode extends ArrayNode {
|
||||||
nodes.remove(index);
|
nodes.remove(index);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,11 @@ public class SimpleValueNode extends ValueNode {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(int indent) {
|
public String toString(int indent) {
|
||||||
var string = getRawData().length == 0 && !hasMetaAttribute(IS_TEXT) ? "<null>" : new String(getRawData(), StandardCharsets.UTF_8);
|
var string = getRawData().length == 0 && !hasMetaAttribute(IS_TEXT)
|
||||||
return (hasMetaAttribute(IS_TEXT) ? "\"" : "") + string + (hasMetaAttribute(IS_TEXT) ? "\"" : "") + " " + metaToString();
|
? "<null>"
|
||||||
|
: new String(getRawData(), StandardCharsets.UTF_8);
|
||||||
|
return (hasMetaAttribute(IS_TEXT) ? "\"" : "") + string + (hasMetaAttribute(IS_TEXT) ? "\"" : "") + " "
|
||||||
|
+ metaToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -5,7 +5,6 @@ import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
public abstract class TupleNode extends DataStructureNode {
|
public abstract class TupleNode extends DataStructureNode {
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
|
@ -46,13 +45,15 @@ public abstract class TupleNode extends DataStructureNode {
|
||||||
public String toString(int indent) {
|
public String toString(int indent) {
|
||||||
var is = " ".repeat(indent);
|
var is = " ".repeat(indent);
|
||||||
var start = "{\n";
|
var start = "{\n";
|
||||||
var kvs = getKeyValuePairs().stream().map(kv -> {
|
var kvs = getKeyValuePairs().stream()
|
||||||
if (kv.key() == null) {
|
.map(kv -> {
|
||||||
return is + " " + kv.value().toString(indent + 1) + "\n";
|
if (kv.key() == null) {
|
||||||
} else {
|
return is + " " + kv.value().toString(indent + 1) + "\n";
|
||||||
return is + " " + kv.key() + "=" + kv.value().toString(indent + 1) + "\n";
|
} else {
|
||||||
}
|
return is + " " + kv.key() + "=" + kv.value().toString(indent + 1) + "\n";
|
||||||
}).collect(Collectors.joining());
|
}
|
||||||
|
})
|
||||||
|
.collect(Collectors.joining());
|
||||||
var end = is + "}";
|
var end = is + "}";
|
||||||
return start + kvs + end;
|
return start + kvs + end;
|
||||||
}
|
}
|
||||||
|
@ -65,8 +66,9 @@ public abstract class TupleNode extends DataStructureNode {
|
||||||
if (!(o instanceof TupleNode that)) {
|
if (!(o instanceof TupleNode that)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var toReturn = getKeyNames().equals(that.getKeyNames()) && getNodes().equals(that.getNodes()) &&
|
var toReturn = getKeyNames().equals(that.getKeyNames())
|
||||||
Objects.equals(getMetaAttributes(), that.getMetaAttributes());
|
&& getNodes().equals(that.getNodes())
|
||||||
|
&& Objects.equals(getMetaAttributes(), that.getMetaAttributes());
|
||||||
|
|
||||||
// Useful for debugging
|
// Useful for debugging
|
||||||
if (toReturn == false) {
|
if (toReturn == false) {
|
||||||
|
@ -98,11 +100,11 @@ public abstract class TupleNode extends DataStructureNode {
|
||||||
|
|
||||||
public TupleNode build() {
|
public TupleNode build() {
|
||||||
boolean hasKeys = entries.stream().anyMatch(kv -> kv.key() != null);
|
boolean hasKeys = entries.stream().anyMatch(kv -> kv.key() != null);
|
||||||
return hasKeys ? TupleNode.of(
|
return hasKeys
|
||||||
entries.stream().map(KeyValue::key).toList(),
|
? TupleNode.of(
|
||||||
entries.stream().map(KeyValue::value).toList()
|
entries.stream().map(KeyValue::key).toList(),
|
||||||
) :
|
entries.stream().map(KeyValue::value).toList())
|
||||||
TupleNode.of(entries.stream().map(KeyValue::value).toList());
|
: TupleNode.of(entries.stream().map(KeyValue::value).toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,32 +11,7 @@ import java.util.Objects;
|
||||||
|
|
||||||
public abstract class ValueNode extends DataStructureNode {
|
public abstract class ValueNode extends DataStructureNode {
|
||||||
|
|
||||||
|
protected ValueNode() {}
|
||||||
protected ValueNode() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(o instanceof ValueNode that)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var toReturn = Arrays.equals(getRawData(), that.getRawData()) && Objects.equals(getMetaAttributes(), that.getMetaAttributes());
|
|
||||||
|
|
||||||
// Useful for debugging
|
|
||||||
if (toReturn == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Arrays.hashCode(getRawData()) + Objects.hash(getMetaAttributes());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ValueNode nullValue() {
|
public static ValueNode nullValue() {
|
||||||
return new SimpleValueNode(new byte[0]).tag(IS_NULL).asValue();
|
return new SimpleValueNode(new byte[0]).tag(IS_NULL).asValue();
|
||||||
|
@ -79,6 +54,7 @@ public abstract class ValueNode extends DataStructureNode {
|
||||||
created.tag(IS_FLOATING_POINT);
|
created.tag(IS_FLOATING_POINT);
|
||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueNode ofBoolean(Boolean bool) {
|
public static ValueNode ofBoolean(Boolean bool) {
|
||||||
var created = of(bool);
|
var created = of(bool);
|
||||||
created.tag(IS_BOOLEAN);
|
created.tag(IS_BOOLEAN);
|
||||||
|
@ -93,6 +69,30 @@ public abstract class ValueNode extends DataStructureNode {
|
||||||
return of(o.toString().getBytes(StandardCharsets.UTF_8));
|
return of(o.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(o instanceof ValueNode that)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var toReturn = Arrays.equals(getRawData(), that.getRawData())
|
||||||
|
&& Objects.equals(getMetaAttributes(), that.getMetaAttributes());
|
||||||
|
|
||||||
|
// Useful for debugging
|
||||||
|
if (toReturn == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Arrays.hashCode(getRawData()) + Objects.hash(getMetaAttributes());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int asInt() {
|
public final int asInt() {
|
||||||
return Integer.parseInt(asString());
|
return Integer.parseInt(asString());
|
||||||
|
@ -114,5 +114,4 @@ public abstract class ValueNode extends DataStructureNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract byte[] getRawData();
|
public abstract byte[] getRawData();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,11 @@ package io.xpipe.core.data.type;
|
||||||
|
|
||||||
public interface DataTypeVisitor {
|
public interface DataTypeVisitor {
|
||||||
|
|
||||||
default void onValue(ValueType type) {
|
default void onValue(ValueType type) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onTuple(TupleType type) {
|
default void onTuple(TupleType type) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onArray(ArrayType type) {
|
default void onArray(ArrayType type) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onWildcard(WildcardType type) {
|
default void onWildcard(WildcardType type) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,9 +41,7 @@ public class DataTypeVisitors {
|
||||||
* Creates a visitor that allows for visiting possible recursive columns of table.
|
* Creates a visitor that allows for visiting possible recursive columns of table.
|
||||||
*/
|
*/
|
||||||
public static DataTypeVisitor table(
|
public static DataTypeVisitor table(
|
||||||
Consumer<String> newTuple,
|
Consumer<String> newTuple, Runnable endTuple, BiConsumer<String, DataStructureNodePointer> newValue) {
|
||||||
Runnable endTuple,
|
|
||||||
BiConsumer<String, DataStructureNodePointer> newValue) {
|
|
||||||
return new DataTypeVisitor() {
|
return new DataTypeVisitor() {
|
||||||
private final Stack<TupleType> tuples = new Stack<>();
|
private final Stack<TupleType> tuples = new Stack<>();
|
||||||
private final Stack<Integer> keyIndices = new Stack<>();
|
private final Stack<Integer> keyIndices = new Stack<>();
|
||||||
|
|
|
@ -17,6 +17,8 @@ import java.util.Optional;
|
||||||
@Value
|
@Value
|
||||||
public class WildcardType extends DataType {
|
public class WildcardType extends DataType {
|
||||||
|
|
||||||
|
private WildcardType() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
*/
|
*/
|
||||||
|
@ -24,8 +26,6 @@ public class WildcardType extends DataType {
|
||||||
return new WildcardType();
|
return new WildcardType();
|
||||||
}
|
}
|
||||||
|
|
||||||
private WildcardType() {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "wildcard";
|
return "wildcard";
|
||||||
|
|
|
@ -7,27 +7,19 @@ import java.util.Map;
|
||||||
|
|
||||||
public interface TypedDataStreamCallback {
|
public interface TypedDataStreamCallback {
|
||||||
|
|
||||||
default void onValue(byte[] data, Map<Integer, String> metaAttributes) {
|
default void onValue(byte[] data, Map<Integer, String> metaAttributes) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onGenericNode(DataStructureNode node) {
|
default void onGenericNode(DataStructureNode node) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onTupleBegin(TupleType type) {
|
default void onTupleBegin(TupleType type) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onTupleEnd(Map<Integer, String> metaAttributes) {
|
default void onTupleEnd(Map<Integer, String> metaAttributes) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onArrayBegin(int size) {
|
default void onArrayBegin(int size) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onArrayEnd(Map<Integer, String> metaAttributes) {
|
default void onArrayEnd(Map<Integer, String> metaAttributes) {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onNodeBegin() {
|
default void onNodeBegin() {}
|
||||||
}
|
|
||||||
|
|
||||||
default void onNodeEnd() {
|
default void onNodeEnd() {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package io.xpipe.core.data.typed;
|
package io.xpipe.core.data.typed;
|
||||||
|
|
||||||
import io.xpipe.core.data.node.DataStructureNode;
|
|
||||||
import io.xpipe.core.data.node.DataStructureNodeIO;
|
|
||||||
import io.xpipe.core.data.generic.GenericDataStreamParser;
|
import io.xpipe.core.data.generic.GenericDataStreamParser;
|
||||||
import io.xpipe.core.data.generic.GenericDataStructureNodeReader;
|
import io.xpipe.core.data.generic.GenericDataStructureNodeReader;
|
||||||
|
import io.xpipe.core.data.node.DataStructureNode;
|
||||||
|
import io.xpipe.core.data.node.DataStructureNodeIO;
|
||||||
import io.xpipe.core.data.type.ArrayType;
|
import io.xpipe.core.data.type.ArrayType;
|
||||||
import io.xpipe.core.data.type.DataType;
|
import io.xpipe.core.data.type.DataType;
|
||||||
import io.xpipe.core.data.type.TupleType;
|
import io.xpipe.core.data.type.TupleType;
|
||||||
|
@ -21,7 +21,7 @@ public class TypedDataStreamParser {
|
||||||
this.dataType = dataType;
|
this.dataType = dataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasNext(InputStream in) throws IOException {
|
private boolean hasNext(InputStream in) throws IOException {
|
||||||
var b = in.read();
|
var b = in.read();
|
||||||
if (b == -1) {
|
if (b == -1) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -34,7 +34,8 @@ public class TypedDataStreamParser {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parseStructures(InputStream in, TypedAbstractReader cb, Consumer<DataStructureNode> consumer) throws IOException {
|
public void parseStructures(InputStream in, TypedAbstractReader cb, Consumer<DataStructureNode> consumer)
|
||||||
|
throws IOException {
|
||||||
while (hasNext(in)) {
|
while (hasNext(in)) {
|
||||||
cb.onNodeBegin();
|
cb.onNodeBegin();
|
||||||
parse(in, cb, dataType);
|
parse(in, cb, dataType);
|
||||||
|
|
|
@ -12,20 +12,13 @@ import java.util.Stack;
|
||||||
|
|
||||||
public class TypedDataStructureNodeReader implements TypedAbstractReader {
|
public class TypedDataStructureNodeReader implements TypedAbstractReader {
|
||||||
|
|
||||||
public static TypedDataStructureNodeReader of(DataType type) {
|
|
||||||
return new TypedDataStructureNodeReader(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataStructureNode readNode;
|
|
||||||
|
|
||||||
private final Stack<List<DataStructureNode>> children;
|
private final Stack<List<DataStructureNode>> children;
|
||||||
private final Stack<DataStructureNode> nodes;
|
private final Stack<DataStructureNode> nodes;
|
||||||
private int arrayDepth;
|
|
||||||
|
|
||||||
private final List<DataType> flattened;
|
private final List<DataType> flattened;
|
||||||
|
private DataStructureNode readNode;
|
||||||
|
private int arrayDepth;
|
||||||
private DataType expectedType;
|
private DataType expectedType;
|
||||||
private int currentExpectedTypeIndex;
|
private int currentExpectedTypeIndex;
|
||||||
|
|
||||||
private TypedDataStructureNodeReader(DataType type) {
|
private TypedDataStructureNodeReader(DataType type) {
|
||||||
flattened = new ArrayList<>();
|
flattened = new ArrayList<>();
|
||||||
type.visit(DataTypeVisitors.flatten(flattened::add));
|
type.visit(DataTypeVisitors.flatten(flattened::add));
|
||||||
|
@ -34,6 +27,10 @@ public class TypedDataStructureNodeReader implements TypedAbstractReader {
|
||||||
expectedType = flattened.get(0);
|
expectedType = flattened.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TypedDataStructureNodeReader of(DataType type) {
|
||||||
|
return new TypedDataStructureNodeReader(type);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNodeBegin() {
|
public void onNodeBegin() {
|
||||||
if (nodes.size() != 0 || children.size() != 0) {
|
if (nodes.size() != 0 || children.size() != 0) {
|
||||||
|
@ -134,7 +131,8 @@ public class TypedDataStructureNodeReader implements TypedAbstractReader {
|
||||||
private void moveExpectedType(boolean force) {
|
private void moveExpectedType(boolean force) {
|
||||||
if (!isInArray() || force) {
|
if (!isInArray() || force) {
|
||||||
currentExpectedTypeIndex++;
|
currentExpectedTypeIndex++;
|
||||||
expectedType = currentExpectedTypeIndex == flattened.size() ? null : flattened.get(currentExpectedTypeIndex);
|
expectedType =
|
||||||
|
currentExpectedTypeIndex == flattened.size() ? null : flattened.get(currentExpectedTypeIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ public class BaseQueryElement extends DialogElement {
|
||||||
protected String value;
|
protected String value;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public BaseQueryElement(String description, boolean newLine, boolean required, boolean secret, boolean quiet, String value) {
|
public BaseQueryElement(
|
||||||
|
String description, boolean newLine, boolean required, boolean secret, boolean quiet, String value) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.newLine = newLine;
|
this.newLine = newLine;
|
||||||
this.required = required;
|
this.required = required;
|
||||||
|
|
|
@ -18,6 +18,18 @@ public class ChoiceElement extends DialogElement {
|
||||||
|
|
||||||
private int selected;
|
private int selected;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public ChoiceElement(String description, List<Choice> elements, boolean required, int selected) {
|
||||||
|
if (elements.stream().allMatch(Choice::isDisabled)) {
|
||||||
|
throw new IllegalArgumentException("All choices are disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.description = description;
|
||||||
|
this.elements = elements;
|
||||||
|
this.required = required;
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean requiresExplicitUserInput() {
|
public boolean requiresExplicitUserInput() {
|
||||||
return required && selected == -1;
|
return required && selected == -1;
|
||||||
|
@ -42,7 +54,8 @@ public class ChoiceElement extends DialogElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < elements.size(); i++) {
|
for (int i = 0; i < elements.size(); i++) {
|
||||||
if (elements.get(i).getCharacter() != null && elements.get(i).getCharacter().equals(c)) {
|
if (elements.get(i).getCharacter() != null
|
||||||
|
&& elements.get(i).getCharacter().equals(c)) {
|
||||||
selected = i;
|
selected = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -59,18 +72,6 @@ public class ChoiceElement extends DialogElement {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonCreator
|
|
||||||
public ChoiceElement(String description, List<Choice> elements, boolean required, int selected) {
|
|
||||||
if (elements.stream().allMatch(Choice::isDisabled)) {
|
|
||||||
throw new IllegalArgumentException("All choices are disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.description = description;
|
|
||||||
this.elements = elements;
|
|
||||||
this.required = required;
|
|
||||||
this.selected = selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Choice> getElements() {
|
public List<Choice> getElements() {
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ package io.xpipe.core.dialog;
|
||||||
|
|
||||||
import io.xpipe.core.util.SecretValue;
|
import io.xpipe.core.util.SecretValue;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -24,6 +26,10 @@ import java.util.function.Supplier;
|
||||||
*/
|
*/
|
||||||
public abstract class Dialog {
|
public abstract class Dialog {
|
||||||
|
|
||||||
|
private final List<Consumer<?>> completion = new ArrayList<>();
|
||||||
|
protected Object eval;
|
||||||
|
private Supplier<?> evaluation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty dialogue. This dialogue completes immediately and does not handle any questions or answers.
|
* Creates an empty dialogue. This dialogue completes immediately and does not handle any questions or answers.
|
||||||
*/
|
*/
|
||||||
|
@ -43,33 +49,6 @@ public abstract class Dialog {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Choice extends Dialog {
|
|
||||||
|
|
||||||
private final ChoiceElement element;
|
|
||||||
|
|
||||||
private Choice(String description, List<io.xpipe.core.dialog.Choice> elements, boolean required, int selected) {
|
|
||||||
this.element = new ChoiceElement(description, elements, required, selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DialogElement start() throws Exception {
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected DialogElement next(String answer) throws Exception {
|
|
||||||
if (element.apply(answer)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getSelected() {
|
|
||||||
return element.getSelected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a choice dialogue.
|
* Creates a choice dialogue.
|
||||||
*
|
*
|
||||||
|
@ -78,7 +57,8 @@ public abstract class Dialog {
|
||||||
* @param required signals whether a choice is required or can be left empty
|
* @param required signals whether a choice is required or can be left empty
|
||||||
* @param selected the selected element index
|
* @param selected the selected element index
|
||||||
*/
|
*/
|
||||||
public static Dialog.Choice choice(String description, List<io.xpipe.core.dialog.Choice> elements, boolean required, int selected) {
|
public static Dialog.Choice choice(
|
||||||
|
String description, List<io.xpipe.core.dialog.Choice> elements, boolean required, int selected) {
|
||||||
Dialog.Choice c = new Dialog.Choice(description, elements, required, selected);
|
Dialog.Choice c = new Dialog.Choice(description, elements, required, selected);
|
||||||
c.evaluateTo(c::getSelected);
|
c.evaluateTo(c::getSelected);
|
||||||
return c;
|
return c;
|
||||||
|
@ -94,8 +74,11 @@ public abstract class Dialog {
|
||||||
* @param vals the range of possible elements
|
* @param vals the range of possible elements
|
||||||
*/
|
*/
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public static <T> Dialog.Choice choice(String description, Function<T, String> toString, boolean required, T def, T... vals) {
|
public static <T> Dialog.Choice choice(
|
||||||
var elements = Arrays.stream(vals).map(v -> new io.xpipe.core.dialog.Choice(null, toString.apply(v))).toList();
|
String description, Function<T, String> toString, boolean required, T def, T... vals) {
|
||||||
|
var elements = Arrays.stream(vals)
|
||||||
|
.map(v -> new io.xpipe.core.dialog.Choice(null, toString.apply(v)))
|
||||||
|
.toList();
|
||||||
var index = Arrays.asList(vals).indexOf(def);
|
var index = Arrays.asList(vals).indexOf(def);
|
||||||
if (def != null && index == -1) {
|
if (def != null && index == -1) {
|
||||||
throw new IllegalArgumentException("Default value " + def.toString() + " is not in possible values");
|
throw new IllegalArgumentException("Default value " + def.toString() + " is not in possible values");
|
||||||
|
@ -111,38 +94,6 @@ public abstract class Dialog {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Query extends Dialog {
|
|
||||||
|
|
||||||
private final QueryElement element;
|
|
||||||
|
|
||||||
private <T> Query(String description, boolean newLine, boolean required, boolean quiet, T value, QueryConverter<T> converter, boolean hidden) {
|
|
||||||
this.element = new QueryElement(description, newLine, required, quiet, value, converter, hidden);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DialogElement start() throws Exception {
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected DialogElement next(String answer) throws Exception {
|
|
||||||
if (element.requiresExplicitUserInput() && (answer == null || answer.trim()
|
|
||||||
.length() == 0)) {
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element.apply(answer)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> T getConvertedValue() {
|
|
||||||
return element.getConvertedValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a simple query dialogue.
|
* Creates a simple query dialogue.
|
||||||
*
|
*
|
||||||
|
@ -155,7 +106,13 @@ public abstract class Dialog {
|
||||||
* @param value the default value
|
* @param value the default value
|
||||||
* @param converter the converter
|
* @param converter the converter
|
||||||
*/
|
*/
|
||||||
public static <T> Dialog.Query query(String description, boolean newLine, boolean required, boolean quiet, T value, QueryConverter<T> converter) {
|
public static <T> Dialog.Query query(
|
||||||
|
String description,
|
||||||
|
boolean newLine,
|
||||||
|
boolean required,
|
||||||
|
boolean quiet,
|
||||||
|
T value,
|
||||||
|
QueryConverter<T> converter) {
|
||||||
var q = new <T>Dialog.Query(description, newLine, required, quiet, value, converter, false);
|
var q = new <T>Dialog.Query(description, newLine, required, quiet, value, converter, false);
|
||||||
q.evaluateTo(q::getConvertedValue);
|
q.evaluateTo(q::getConvertedValue);
|
||||||
return q;
|
return q;
|
||||||
|
@ -201,8 +158,7 @@ public abstract class Dialog {
|
||||||
DialogElement currentElement = ds[current].receive(answer);
|
DialogElement currentElement = ds[current].receive(answer);
|
||||||
if (currentElement == null) {
|
if (currentElement == null) {
|
||||||
DialogElement next = null;
|
DialogElement next = null;
|
||||||
while (current < ds.length - 1 && (next = ds[++current].start()) == null) {
|
while (current < ds.length - 1 && (next = ds[++current].start()) == null) {}
|
||||||
}
|
|
||||||
;
|
;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
@ -218,7 +174,6 @@ public abstract class Dialog {
|
||||||
public static <T> Dialog repeatIf(Dialog d, Predicate<T> shouldRepeat) {
|
public static <T> Dialog repeatIf(Dialog d, Predicate<T> shouldRepeat) {
|
||||||
return new Dialog() {
|
return new Dialog() {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DialogElement start() throws Exception {
|
public DialogElement start() throws Exception {
|
||||||
eval = null;
|
eval = null;
|
||||||
|
@ -272,11 +227,6 @@ public abstract class Dialog {
|
||||||
return of(new BusyElement());
|
return of(new BusyElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface FailableSupplier<T> {
|
|
||||||
|
|
||||||
T get() throws Exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a dialogue that will only evaluate when needed.
|
* Creates a dialogue that will only evaluate when needed.
|
||||||
* This allows a dialogue to incorporate completion information about a previous dialogue.
|
* This allows a dialogue to incorporate completion information about a previous dialogue.
|
||||||
|
@ -305,7 +255,6 @@ public abstract class Dialog {
|
||||||
private static Dialog of(DialogElement e) {
|
private static Dialog of(DialogElement e) {
|
||||||
return new Dialog() {
|
return new Dialog() {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DialogElement start() throws Exception {
|
public DialogElement start() throws Exception {
|
||||||
eval = null;
|
eval = null;
|
||||||
|
@ -323,7 +272,6 @@ public abstract class Dialog {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a dialogue that will not be executed if the condition is true.
|
* Creates a dialogue that will not be executed if the condition is true.
|
||||||
*/
|
*/
|
||||||
|
@ -393,7 +341,12 @@ public abstract class Dialog {
|
||||||
* @param selected the index of the element that is selected by default
|
* @param selected the index of the element that is selected by default
|
||||||
* @param c the dialogue index mapping function
|
* @param c the dialogue index mapping function
|
||||||
*/
|
*/
|
||||||
public static Dialog fork(String description, List<io.xpipe.core.dialog.Choice> elements, boolean required, int selected, Function<Integer, Dialog> c) {
|
public static Dialog fork(
|
||||||
|
String description,
|
||||||
|
List<io.xpipe.core.dialog.Choice> elements,
|
||||||
|
boolean required,
|
||||||
|
int selected,
|
||||||
|
Function<Integer, Dialog> c) {
|
||||||
var choice = new ChoiceElement(description, elements, required, selected);
|
var choice = new ChoiceElement(description, elements, required, selected);
|
||||||
return new Dialog() {
|
return new Dialog() {
|
||||||
|
|
||||||
|
@ -427,13 +380,9 @@ public abstract class Dialog {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object eval;
|
|
||||||
private Supplier<?> evaluation;
|
|
||||||
private final List<Consumer<?>> completion = new ArrayList<>();
|
|
||||||
|
|
||||||
/* TODO: Implement automatic completion mechanism for start as well
|
/* TODO: Implement automatic completion mechanism for start as well
|
||||||
* In case start returns null, the completion is not automatically done.
|
* In case start returns null, the completion is not automatically done.
|
||||||
* */
|
* */
|
||||||
public abstract DialogElement start() throws Exception;
|
public abstract DialogElement start() throws Exception;
|
||||||
|
|
||||||
public Dialog evaluateTo(Dialog d) {
|
public Dialog evaluateTo(Dialog d) {
|
||||||
|
@ -493,4 +442,75 @@ public abstract class Dialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract DialogElement next(String answer) throws Exception;
|
protected abstract DialogElement next(String answer) throws Exception;
|
||||||
|
|
||||||
|
public static interface FailableSupplier<T> {
|
||||||
|
|
||||||
|
T get() throws Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Choice extends Dialog {
|
||||||
|
|
||||||
|
private final ChoiceElement element;
|
||||||
|
|
||||||
|
private Choice(String description, List<io.xpipe.core.dialog.Choice> elements, boolean required, int selected) {
|
||||||
|
this.element = new ChoiceElement(description, elements, required, selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DialogElement start() throws Exception {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DialogElement next(String answer) throws Exception {
|
||||||
|
if (element.apply(answer)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSelected() {
|
||||||
|
return element.getSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Query extends Dialog {
|
||||||
|
|
||||||
|
private final QueryElement element;
|
||||||
|
|
||||||
|
private <T> Query(
|
||||||
|
String description,
|
||||||
|
boolean newLine,
|
||||||
|
boolean required,
|
||||||
|
boolean quiet,
|
||||||
|
T value,
|
||||||
|
QueryConverter<T> converter,
|
||||||
|
boolean hidden) {
|
||||||
|
this.element = new QueryElement(description, newLine, required, quiet, value, converter, hidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DialogElement start() throws Exception {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DialogElement next(String answer) throws Exception {
|
||||||
|
if (element.requiresExplicitUserInput()
|
||||||
|
&& (answer == null || answer.trim().length() == 0)) {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.apply(answer)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T getConvertedValue() {
|
||||||
|
return element.getConvertedValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@ package io.xpipe.core.dialog;
|
||||||
*/
|
*/
|
||||||
public class DialogCancelException extends Exception {
|
public class DialogCancelException extends Exception {
|
||||||
|
|
||||||
public DialogCancelException() {
|
public DialogCancelException() {}
|
||||||
}
|
|
||||||
|
|
||||||
public DialogCancelException(String message) {
|
public DialogCancelException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
|
@ -20,7 +19,8 @@ public class DialogCancelException extends Exception {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DialogCancelException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
public DialogCancelException(
|
||||||
|
String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||||
super(message, cause, enableSuppression, writableStackTrace);
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ public abstract class QueryConverter<T> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public static final QueryConverter<StreamCharset> CHARSET = new QueryConverter<StreamCharset>() {
|
public static final QueryConverter<StreamCharset> CHARSET = new QueryConverter<StreamCharset>() {
|
||||||
@Override
|
@Override
|
||||||
protected StreamCharset fromString(String s) {
|
protected StreamCharset fromString(String s) {
|
||||||
|
@ -60,26 +59,27 @@ public abstract class QueryConverter<T> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final QueryConverter<Map.Entry<String, String>> HTTP_HEADER = new QueryConverter<Map.Entry<String, String>>() {
|
public static final QueryConverter<Map.Entry<String, String>> HTTP_HEADER =
|
||||||
@Override
|
new QueryConverter<Map.Entry<String, String>>() {
|
||||||
protected Map.Entry<String, String> fromString(String s) {
|
@Override
|
||||||
if (!s.contains(":")) {
|
protected Map.Entry<String, String> fromString(String s) {
|
||||||
throw new IllegalArgumentException("Missing colon");
|
if (!s.contains(":")) {
|
||||||
}
|
throw new IllegalArgumentException("Missing colon");
|
||||||
|
}
|
||||||
|
|
||||||
var split = s.split(":");
|
var split = s.split(":");
|
||||||
if (split.length != 2) {
|
if (split.length != 2) {
|
||||||
throw new IllegalArgumentException("Too many colons");
|
throw new IllegalArgumentException("Too many colons");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AbstractMap.SimpleEntry<>(split[0].trim(), split[1].trim());
|
return new AbstractMap.SimpleEntry<>(split[0].trim(), split[1].trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String toString(Map.Entry<String, String> value) {
|
protected String toString(Map.Entry<String, String> value) {
|
||||||
return value.getKey() + ": " + value.getValue();
|
return value.getKey() + ": " + value.getValue();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final QueryConverter<URI> URI = new QueryConverter<URI>() {
|
public static final QueryConverter<URI> URI = new QueryConverter<URI>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -141,9 +141,7 @@ public abstract class QueryConverter<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String toString(Boolean value) {
|
protected String toString(Boolean value) {
|
||||||
return value ?
|
return value ? "yes" : "no";
|
||||||
"yes" :
|
|
||||||
"no";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,14 @@ public class QueryElement extends BaseQueryElement {
|
||||||
|
|
||||||
private final QueryConverter<?> converter;
|
private final QueryConverter<?> converter;
|
||||||
|
|
||||||
public <T> QueryElement(String description, boolean newLine, boolean required, boolean quiet, T value, QueryConverter<T> converter, boolean hidden) {
|
public <T> QueryElement(
|
||||||
|
String description,
|
||||||
|
boolean newLine,
|
||||||
|
boolean required,
|
||||||
|
boolean quiet,
|
||||||
|
T value,
|
||||||
|
QueryConverter<T> converter,
|
||||||
|
boolean hidden) {
|
||||||
super(description, newLine, required, hidden, quiet, value != null ? converter.toString(value) : null);
|
super(description, newLine, required, hidden, quiet, value != null ? converter.toString(value) : null);
|
||||||
this.converter = converter;
|
this.converter = converter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,5 +50,3 @@ public abstract class BatchTableWriteConnection implements TableWriteConnection
|
||||||
|
|
||||||
protected abstract DataStructureNodeAcceptor<ArrayNode> writeBatchLinesAcceptor();
|
protected abstract DataStructureNodeAcceptor<ArrayNode> writeBatchLinesAcceptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ public class BinarySource extends RawDataSource<StreamDataStore> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RawReadConnection newReadConnection() {
|
protected RawReadConnection newReadConnection() {
|
||||||
return new RawReadConnection() {
|
return new RawReadConnection() {
|
||||||
|
|
|
@ -48,8 +48,7 @@ public class LimitTableReadConnection implements TableReadConnection {
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
var returned = lineAcceptor
|
var returned = lineAcceptor.accept(node);
|
||||||
.accept(node);
|
|
||||||
localCounter.getAndIncrement();
|
localCounter.getAndIncrement();
|
||||||
|
|
||||||
return returned;
|
return returned;
|
||||||
|
|
|
@ -9,14 +9,12 @@ import io.xpipe.core.source.TableWriteConnection;
|
||||||
|
|
||||||
public class PreservingTableWriteConnection extends PreservingWriteConnection implements TableWriteConnection {
|
public class PreservingTableWriteConnection extends PreservingWriteConnection implements TableWriteConnection {
|
||||||
|
|
||||||
public PreservingTableWriteConnection(DataSource<?> source, DataSourceConnection connection,
|
public PreservingTableWriteConnection(DataSource<?> source, DataSourceConnection connection, boolean append) {
|
||||||
boolean append
|
|
||||||
) {
|
|
||||||
super(DataSourceType.TABLE, source, append, connection);
|
super(DataSourceType.TABLE, source, append, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataStructureNodeAcceptor<TupleNode> writeLinesAcceptor() {
|
public DataStructureNodeAcceptor<TupleNode> writeLinesAcceptor() {
|
||||||
return ((TableWriteConnection)connection).writeLinesAcceptor();
|
return ((TableWriteConnection) connection).writeLinesAcceptor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,7 @@ import io.xpipe.core.source.TextWriteConnection;
|
||||||
|
|
||||||
public class PreservingTextWriteConnection extends PreservingWriteConnection implements TextWriteConnection {
|
public class PreservingTextWriteConnection extends PreservingWriteConnection implements TextWriteConnection {
|
||||||
|
|
||||||
public PreservingTextWriteConnection(
|
public PreservingTextWriteConnection(DataSource<?> source, DataSourceConnection connection, boolean append) {
|
||||||
DataSource<?> source, DataSourceConnection connection,
|
|
||||||
boolean append
|
|
||||||
) {
|
|
||||||
super(DataSourceType.TEXT, source, append, connection);
|
super(DataSourceType.TEXT, source, append, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,13 @@ import java.nio.file.Files;
|
||||||
|
|
||||||
public class PreservingWriteConnection implements DataSourceConnection {
|
public class PreservingWriteConnection implements DataSourceConnection {
|
||||||
|
|
||||||
|
protected final DataSourceConnection connection;
|
||||||
private final DataSourceType type;
|
private final DataSourceType type;
|
||||||
private final DataSource<?> source;
|
private final DataSource<?> source;
|
||||||
private final boolean append ;
|
private final boolean append;
|
||||||
protected final DataSourceConnection connection;
|
|
||||||
|
|
||||||
public PreservingWriteConnection(DataSourceType type, DataSource<?> source, boolean append, DataSourceConnection connection) {
|
public PreservingWriteConnection(
|
||||||
|
DataSourceType type, DataSource<?> source, boolean append, DataSourceConnection connection) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.append = append;
|
this.append = append;
|
||||||
|
@ -26,13 +27,13 @@ public class PreservingWriteConnection implements DataSourceConnection {
|
||||||
var nativeStore = FileStore.local(temp);
|
var nativeStore = FileStore.local(temp);
|
||||||
var nativeSource = DataSource.createInternalDataSource(type, nativeStore);
|
var nativeSource = DataSource.createInternalDataSource(type, nativeStore);
|
||||||
if (source.getStore().canOpen()) {
|
if (source.getStore().canOpen()) {
|
||||||
try (var in = source.openReadConnection(); var out = nativeSource.openWriteConnection()) {
|
try (var in = source.openReadConnection();
|
||||||
|
var out = nativeSource.openWriteConnection()) {
|
||||||
in.forward(out);
|
in.forward(out);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
connection.init();
|
connection.init();
|
||||||
if (source.getStore().canOpen()) {
|
if (source.getStore().canOpen()) {
|
||||||
|
|
||||||
|
@ -45,5 +46,4 @@ public class PreservingWriteConnection implements DataSourceConnection {
|
||||||
public void close() throws Exception {
|
public void close() throws Exception {
|
||||||
connection.close();
|
connection.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ public class TextReadConnection extends StreamReadConnection implements io.xpipe
|
||||||
return bufferedReader.lines();
|
return bufferedReader.lines();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws Exception {
|
public void close() throws Exception {
|
||||||
bufferedReader.close();
|
bufferedReader.close();
|
||||||
|
|
|
@ -14,7 +14,7 @@ import lombok.extern.jackson.Jacksonized;
|
||||||
@JsonTypeName("text")
|
@JsonTypeName("text")
|
||||||
@SuperBuilder
|
@SuperBuilder
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
public final class TextSource extends TextDataSource<StreamDataStore> implements Charsettable {
|
public final class TextSource extends TextDataSource<StreamDataStore> implements Charsettable {
|
||||||
|
|
||||||
private final StreamCharset charset;
|
private final StreamCharset charset;
|
||||||
private final NewLine newLine;
|
private final NewLine newLine;
|
||||||
|
|
|
@ -13,6 +13,6 @@ public class XpbsWriteConnection extends StreamWriteConnection implements Struct
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataStructureNode node) throws Exception {
|
public void write(DataStructureNode node) throws Exception {
|
||||||
GenericDataStreamWriter.writeStructure(outputStream,node);
|
GenericDataStreamWriter.writeStructure(outputStream, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,15 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
public class XpbtReadConnection implements TableReadConnection {
|
public class XpbtReadConnection implements TableReadConnection {
|
||||||
|
|
||||||
|
private final StreamDataStore store;
|
||||||
|
private TupleType dataType;
|
||||||
|
private InputStream inputStream;
|
||||||
|
private TypedDataStreamParser parser;
|
||||||
|
private boolean empty;
|
||||||
|
protected XpbtReadConnection(StreamDataStore store) {
|
||||||
|
this.store = store;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() throws Exception {
|
public void init() throws Exception {
|
||||||
this.inputStream = store.openBufferedInput();
|
this.inputStream = store.openBufferedInput();
|
||||||
|
@ -36,8 +45,8 @@ public class XpbtReadConnection implements TableReadConnection {
|
||||||
this.inputStream.skip(headerLength + 1);
|
this.inputStream.skip(headerLength + 1);
|
||||||
List<String> names = JacksonMapper.newMapper()
|
List<String> names = JacksonMapper.newMapper()
|
||||||
.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE)
|
.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE)
|
||||||
.readerFor(new TypeReference<List<String>>() {
|
.readerFor(new TypeReference<List<String>>() {})
|
||||||
}).readValue(header);
|
.readValue(header);
|
||||||
TupleType dataType = TupleType.tableType(names);
|
TupleType dataType = TupleType.tableType(names);
|
||||||
this.dataType = dataType;
|
this.dataType = dataType;
|
||||||
this.parser = new TypedDataStreamParser(dataType);
|
this.parser = new TypedDataStreamParser(dataType);
|
||||||
|
@ -48,16 +57,6 @@ public class XpbtReadConnection implements TableReadConnection {
|
||||||
inputStream.close();
|
inputStream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private TupleType dataType;
|
|
||||||
private final StreamDataStore store;
|
|
||||||
private InputStream inputStream;
|
|
||||||
private TypedDataStreamParser parser;
|
|
||||||
private boolean empty;
|
|
||||||
|
|
||||||
protected XpbtReadConnection(StreamDataStore store) {
|
|
||||||
this.store = store;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TupleType getDataType() {
|
public TupleType getDataType() {
|
||||||
return dataType;
|
return dataType;
|
||||||
|
|
|
@ -13,8 +13,6 @@ import lombok.extern.jackson.Jacksonized;
|
||||||
@Jacksonized
|
@Jacksonized
|
||||||
public class XpbtSource extends TableDataSource<StreamDataStore> {
|
public class XpbtSource extends TableDataSource<StreamDataStore> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TableWriteConnection newWriteConnection() {
|
protected TableWriteConnection newWriteConnection() {
|
||||||
return new XpbtWriteConnection(store);
|
return new XpbtWriteConnection(store);
|
||||||
|
|
|
@ -58,7 +58,8 @@ public class XpbtWriteConnection implements TableWriteConnection {
|
||||||
try (JsonGenerator g = f.createGenerator(writer)
|
try (JsonGenerator g = f.createGenerator(writer)
|
||||||
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
|
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
|
||||||
.setPrettyPrinter(new DefaultPrettyPrinter())) {
|
.setPrettyPrinter(new DefaultPrettyPrinter())) {
|
||||||
JacksonMapper.newMapper().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
|
JacksonMapper.newMapper()
|
||||||
|
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
|
||||||
.writeValue(g, tupleNode.getKeyNames());
|
.writeValue(g, tupleNode.getKeyNames());
|
||||||
writer.append("\n");
|
writer.append("\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ public interface CollectionReadConnection extends DataSourceReadConnection {
|
||||||
try (var tCon = (CollectionWriteConnection) con) {
|
try (var tCon = (CollectionWriteConnection) con) {
|
||||||
tCon.init();
|
tCon.init();
|
||||||
listEntries().forEach(s -> {
|
listEntries().forEach(s -> {
|
||||||
// try (var subCon = open(s)) {
|
// try (var subCon = open(s)) {
|
||||||
// ((CollectionWriteConnection) con).write(s, subCon);
|
// ((CollectionWriteConnection) con).write(s, subCon);
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,22 +22,23 @@ import java.util.Optional;
|
||||||
* This instance is only valid in combination with its associated data store instance.
|
* This instance is only valid in combination with its associated data store instance.
|
||||||
*/
|
*/
|
||||||
@SuperBuilder
|
@SuperBuilder
|
||||||
@JsonTypeInfo(
|
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||||
use = JsonTypeInfo.Id.NAME,
|
|
||||||
property = "type"
|
|
||||||
)
|
|
||||||
public abstract class DataSource<DS extends DataStore> extends JacksonizedValue {
|
public abstract class DataSource<DS extends DataStore> extends JacksonizedValue {
|
||||||
|
|
||||||
|
protected DS store;
|
||||||
|
|
||||||
public static DataSource<?> createInternalDataSource(DataSourceType t, DataStore store) {
|
public static DataSource<?> createInternalDataSource(DataSourceType t, DataStore store) {
|
||||||
try {
|
try {
|
||||||
return switch (t) {
|
return switch (t) {
|
||||||
case TABLE -> XpbtSource.builder().store(store.asNeeded()).build();
|
case TABLE -> XpbtSource.builder().store(store.asNeeded()).build();
|
||||||
case STRUCTURE -> null;
|
case STRUCTURE -> null;
|
||||||
case TEXT -> TextSource.builder().store(store.asNeeded()).newLine(NewLine.LF).charset(
|
case TEXT -> TextSource.builder()
|
||||||
StreamCharset.UTF8).build();
|
.store(store.asNeeded())
|
||||||
|
.newLine(NewLine.LF)
|
||||||
|
.charset(StreamCharset.UTF8)
|
||||||
|
.build();
|
||||||
case RAW -> null;
|
case RAW -> null;
|
||||||
//TODO
|
// TODO
|
||||||
case COLLECTION -> null;
|
case COLLECTION -> null;
|
||||||
};
|
};
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -45,9 +46,6 @@ public abstract class DataSource<DS extends DataStore> extends JacksonizedValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DS store;
|
|
||||||
|
|
||||||
|
|
||||||
public void test() throws Exception {
|
public void test() throws Exception {
|
||||||
store.validate();
|
store.validate();
|
||||||
}
|
}
|
||||||
|
@ -68,7 +66,6 @@ public abstract class DataSource<DS extends DataStore> extends JacksonizedValue
|
||||||
return WriteMode.values();
|
return WriteMode.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public DataFlow getFlow() {
|
public DataFlow getFlow() {
|
||||||
if (store == null) {
|
if (store == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -49,7 +49,8 @@ public class DataSourceId {
|
||||||
throw new IllegalArgumentException("Trimmed collection name is empty");
|
throw new IllegalArgumentException("Trimmed collection name is empty");
|
||||||
}
|
}
|
||||||
if (collectionName != null && collectionName.contains("" + SEPARATOR)) {
|
if (collectionName != null && collectionName.contains("" + SEPARATOR)) {
|
||||||
throw new IllegalArgumentException("Separator character " + SEPARATOR + " is not allowed in the collection name");
|
throw new IllegalArgumentException(
|
||||||
|
"Separator character " + SEPARATOR + " is not allowed in the collection name");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entryName == null) {
|
if (entryName == null) {
|
||||||
|
@ -59,7 +60,8 @@ public class DataSourceId {
|
||||||
throw new IllegalArgumentException("Trimmed entry name is empty");
|
throw new IllegalArgumentException("Trimmed entry name is empty");
|
||||||
}
|
}
|
||||||
if (entryName.contains("" + SEPARATOR)) {
|
if (entryName.contains("" + SEPARATOR)) {
|
||||||
throw new IllegalArgumentException("Separator character " + SEPARATOR + " is not allowed in the entry name");
|
throw new IllegalArgumentException(
|
||||||
|
"Separator character " + SEPARATOR + " is not allowed in the entry name");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DataSourceId(collectionName, entryName);
|
return new DataSourceId(collectionName, entryName);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue