mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-21 23:20:23 +00:00
Large refactor
This commit is contained in:
parent
9440037f03
commit
3cc527dfa3
76 changed files with 359 additions and 387 deletions
13
README.md
13
README.md
|
@ -1,5 +1,6 @@
|
|||
## X-Pipe Java
|
||||
|
||||
The fundamental components of the [X-Pipe project]().
|
||||
This repository contains the following four modules:
|
||||
|
||||
- Core - Shared core classes of the Java API and the X-Pipe daemon implementation
|
||||
|
@ -8,6 +9,18 @@ This repository contains the following four modules:
|
|||
and the client applications, for example the various programming language APIs and the CLI
|
||||
- Extension - An API to create all different kinds of extensions for the X-Pipe platform
|
||||
|
||||
## Installation / Usage
|
||||
|
||||
The *core* and *extension* libraries are used in X-Pipe extension development.
|
||||
For setup instructions, see the [X-Pipe extension development]() section.
|
||||
|
||||
The *beacon* library handles all communication and serves as a
|
||||
reference when implementing an API or program that communicates with the X-Pipe daemon.
|
||||
|
||||
The *api* library serves as a reference implementation for other potential X-Pipe APIs
|
||||
and is also used to enable your Java program to communicate with X-Pipe.
|
||||
For setup instructions, see the [X-Pipe Java API Usage]() section.
|
||||
|
||||
## Development
|
||||
|
||||
All X-Pipe components target [JDK 17](https://openjdk.java.net/projects/jdk/17/) and make full use of the Java Module System (JPMS).
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.xpipe/api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.xpipe/api)
|
||||
[![javadoc](https://javadoc.io/badge2/io.xpipe/api/javadoc.svg)](https://javadoc.io/doc/io.xpipe/api)
|
||||
[![Build Status](https://github.com/xpipe-io/xpipe_java/actions/workflows/api-build.yml/badge.svg)](https://github.com/xpipe-io/xpipe_java/actions/workflows/api-build.yml)
|
||||
|
||||
## X-Pipe Java API
|
||||
|
||||
The X-Pipe API for Java allows you to use most of the X-Pipe functionality from Java applications:
|
||||
|
||||
- Create data stores and data sources
|
||||
- Query and work with the contents of data sources
|
||||
- Write and append to data sources
|
||||
|
||||
## Setup
|
||||
|
||||
Either install the [dependency](https://maven-badges.herokuapp.com/maven-central/io.xpipe/api) from Maven Central
|
||||
using your favourite build tool or alternatively download the `xpipe-api.jar`, `xpipe-core.jar`, and `xpipe-beacon.jar`
|
||||
from the [releases page](https://github.com/xpipe-io/xpipe_java/releases/latest) and add them to the classpath.
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ public interface DataSource {
|
|||
DataSourceType getType();
|
||||
|
||||
|
||||
DataSourceConfigInstance getConfig();
|
||||
DataSourceConfig getConfig();
|
||||
|
||||
/**
|
||||
* Attempts to cast this object to a {@link DataTable}.
|
||||
|
|
32
api/src/main/java/io/xpipe/api/DataSourceConfig.java
Normal file
32
api/src/main/java/io/xpipe/api/DataSourceConfig.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package io.xpipe.api;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents the current configuration of a data source.
|
||||
*/
|
||||
public final class DataSourceConfig {
|
||||
|
||||
/**
|
||||
* The data source provider id.
|
||||
*/
|
||||
private final String provider;
|
||||
|
||||
/**
|
||||
* The set configuration parameters.
|
||||
*/
|
||||
private final Map<String, String> configInstance;
|
||||
|
||||
public DataSourceConfig(String provider, Map<String, String> configInstance) {
|
||||
this.provider = provider;
|
||||
this.configInstance = configInstance;
|
||||
}
|
||||
|
||||
public String getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
public Map<String, String> getConfigInstance() {
|
||||
return configInstance;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.api.impl;
|
||||
|
||||
import io.xpipe.api.DataRaw;
|
||||
import io.xpipe.api.DataSourceConfig;
|
||||
import io.xpipe.core.source.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
@ -9,7 +10,7 @@ public class DataRawImpl extends DataSourceImpl implements DataRaw {
|
|||
|
||||
private final DataSourceInfo.Raw info;
|
||||
|
||||
public DataRawImpl(DataSourceId sourceId, DataSourceConfigInstance sourceConfig, DataSourceInfo.Raw info) {
|
||||
public DataRawImpl(DataSourceId sourceId, DataSourceConfig sourceConfig, DataSourceInfo.Raw info) {
|
||||
super(sourceId, sourceConfig);
|
||||
this.info = info;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package io.xpipe.api.impl;
|
||||
|
||||
import io.xpipe.api.DataSource;
|
||||
import io.xpipe.api.DataSourceConfig;
|
||||
import io.xpipe.api.connector.XPipeConnection;
|
||||
import io.xpipe.beacon.exchange.StoreStreamExchange;
|
||||
import io.xpipe.beacon.exchange.QueryDataSourceExchange;
|
||||
import io.xpipe.beacon.exchange.ReadExecuteExchange;
|
||||
import io.xpipe.beacon.exchange.ReadPreparationExchange;
|
||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
||||
import io.xpipe.beacon.exchange.StoreStreamExchange;
|
||||
import io.xpipe.core.source.DataSourceId;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
|
||||
|
@ -19,22 +18,23 @@ public abstract class DataSourceImpl implements DataSource {
|
|||
return XPipeConnection.execute(con -> {
|
||||
var req = QueryDataSourceExchange.Request.builder().ref(ds).build();
|
||||
QueryDataSourceExchange.Response res = con.performSimpleExchange(req);
|
||||
var config = new DataSourceConfig(res.getProvider(), res.getConfig());
|
||||
switch (res.getInfo().getType()) {
|
||||
case TABLE -> {
|
||||
var data = res.getInfo().asTable();
|
||||
return new DataTableImpl(res.getId(), res.getConfig(), data);
|
||||
return new DataTableImpl(res.getId(), config, data);
|
||||
}
|
||||
case STRUCTURE -> {
|
||||
var info = res.getInfo().asStructure();
|
||||
return new DataStructureImpl(res.getId(), res.getConfig(), info);
|
||||
return new DataStructureImpl(res.getId(), config, info);
|
||||
}
|
||||
case TEXT -> {
|
||||
var info = res.getInfo().asText();
|
||||
return new DataTextImpl(res.getId(), res.getConfig(), info);
|
||||
return new DataTextImpl(res.getId(), config, info);
|
||||
}
|
||||
case RAW -> {
|
||||
var info = res.getInfo().asRaw();
|
||||
return new DataRawImpl(res.getId(), res.getConfig(), info);
|
||||
return new DataRawImpl(res.getId(), config, info);
|
||||
}
|
||||
}
|
||||
throw new AssertionError();
|
||||
|
@ -60,20 +60,21 @@ public abstract class DataSourceImpl implements DataSource {
|
|||
});
|
||||
|
||||
var configInstance = startRes.getConfig();
|
||||
configInstance.getConfigInstance().getCurrentValues().putAll(config);
|
||||
var endReq = ReadExecuteExchange.Request.builder()
|
||||
.target(id).dataStore(store).config(configInstance).build();
|
||||
XPipeConnection.execute(con -> {
|
||||
con.performSimpleExchange(endReq);
|
||||
});
|
||||
//TODO
|
||||
// configInstance.getConfigInstance().getCurrentValues().putAll(config);
|
||||
// var endReq = ReadExecuteExchange.Request.builder()
|
||||
// .target(id).dataStore(store).config(configInstance).build();
|
||||
// XPipeConnection.execute(con -> {
|
||||
// con.performSimpleExchange(endReq);
|
||||
// });
|
||||
var ref = id != null ? DataSourceReference.id(id) : DataSourceReference.latest();
|
||||
return get(ref);
|
||||
}
|
||||
|
||||
private final DataSourceId sourceId;
|
||||
private final DataSourceConfigInstance config;
|
||||
private final DataSourceConfig config;
|
||||
|
||||
public DataSourceImpl(DataSourceId sourceId, DataSourceConfigInstance config) {
|
||||
public DataSourceImpl(DataSourceId sourceId, DataSourceConfig config) {
|
||||
this.sourceId = sourceId;
|
||||
this.config = config;
|
||||
}
|
||||
|
@ -84,7 +85,7 @@ public abstract class DataSourceImpl implements DataSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DataSourceConfigInstance getConfig() {
|
||||
public DataSourceConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.xpipe.api.impl;
|
||||
|
||||
import io.xpipe.api.DataSourceConfig;
|
||||
import io.xpipe.api.DataStructure;
|
||||
import io.xpipe.core.data.node.DataStructureNode;
|
||||
import io.xpipe.core.source.*;
|
||||
|
@ -8,7 +9,7 @@ public class DataStructureImpl extends DataSourceImpl implements DataStructure {
|
|||
|
||||
private final DataSourceInfo.Structure info;
|
||||
|
||||
public DataStructureImpl(DataSourceId sourceId, DataSourceConfigInstance sourceConfig, DataSourceInfo.Structure info) {
|
||||
public DataStructureImpl(DataSourceId sourceId, DataSourceConfig sourceConfig, DataSourceInfo.Structure info) {
|
||||
super(sourceId, sourceConfig);
|
||||
this.info = info;
|
||||
}
|
||||
|
|
|
@ -5,14 +5,13 @@ import io.xpipe.api.DataTable;
|
|||
import io.xpipe.api.DataTableAccumulator;
|
||||
import io.xpipe.api.connector.XPipeConnection;
|
||||
import io.xpipe.api.util.TypeDescriptor;
|
||||
import io.xpipe.beacon.exchange.StoreStreamExchange;
|
||||
import io.xpipe.beacon.exchange.ReadExecuteExchange;
|
||||
import io.xpipe.beacon.exchange.StoreStreamExchange;
|
||||
import io.xpipe.core.data.node.DataStructureNode;
|
||||
import io.xpipe.core.data.node.DataStructureNodeAcceptor;
|
||||
import io.xpipe.core.data.node.TupleNode;
|
||||
import io.xpipe.core.data.type.TupleType;
|
||||
import io.xpipe.core.data.typed.TypedDataStreamWriter;
|
||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
||||
import io.xpipe.core.source.DataSourceId;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
|
||||
|
@ -40,7 +39,7 @@ public class DataTableAccumulatorImpl implements DataTableAccumulator {
|
|||
connection.close();
|
||||
|
||||
var req = ReadExecuteExchange.Request.builder()
|
||||
.target(id).dataStore(res.getStore()).config(DataSourceConfigInstance.xpbt()).build();
|
||||
.target(id).dataStore(res.getStore()).build();
|
||||
XPipeConnection.execute(con -> {
|
||||
con.performSimpleExchange(req);
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.xpipe.api.impl;
|
||||
|
||||
import io.xpipe.api.DataSourceConfig;
|
||||
import io.xpipe.api.DataTable;
|
||||
import io.xpipe.api.connector.XPipeConnection;
|
||||
import io.xpipe.beacon.BeaconConnection;
|
||||
|
@ -24,7 +25,7 @@ public class DataTableImpl extends DataSourceImpl implements DataTable {
|
|||
|
||||
private final DataSourceInfo.Table info;
|
||||
|
||||
DataTableImpl(DataSourceId id, DataSourceConfigInstance sourceConfig, DataSourceInfo.Table info) {
|
||||
DataTableImpl(DataSourceId id, DataSourceConfig sourceConfig, DataSourceInfo.Table info) {
|
||||
super(id, sourceConfig);
|
||||
this.info = info;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.xpipe.api.impl;
|
||||
|
||||
import io.xpipe.api.DataSourceConfig;
|
||||
import io.xpipe.api.DataText;
|
||||
import io.xpipe.core.source.*;
|
||||
|
||||
|
@ -10,7 +11,7 @@ public class DataTextImpl extends DataSourceImpl implements DataText {
|
|||
|
||||
private final DataSourceInfo.Text info;
|
||||
|
||||
public DataTextImpl(DataSourceId sourceId, DataSourceConfigInstance sourceConfig, DataSourceInfo.Text info) {
|
||||
public DataTextImpl(DataSourceId sourceId, DataSourceConfig sourceConfig, DataSourceInfo.Text info) {
|
||||
super(sourceId, sourceConfig);
|
||||
this.info = info;
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
The X-Pipe beacon component is responsible for handling all communications between the X-Pipe daemon
|
||||
and the various programming language APIs and the CLI. It provides an API that supports all kinds
|
||||
of different operations.
|
||||
The underlying inter-process communication is realized through TCP sockets on port `21721`.
|
||||
The underlying inter-process communication is realized through TCP sockets on default port `21721`.
|
||||
|
||||
The data structures and exchange protocols are specified in the `io.xpipe.beacon.exchange` package.
|
||||
Every exchange is initiated from the outside by sending a request message to the daemon.
|
||||
Every exchange is initiated from the outside by sending a request message to the X-Pipe daemon.
|
||||
The daemon then always sends a response message.
|
||||
|
||||
The header information of a message is formatted in the json format.
|
||||
|
@ -23,7 +23,7 @@ Each segment is preceded by four bytes that specify the length of the next segme
|
|||
In case the next segment has a length of less than `65536` bytes, we know that the end of the body has been reached.
|
||||
This way the socket communication can handle payloads of unknown length.
|
||||
|
||||
### Configuration
|
||||
## Configuration
|
||||
|
||||
The default port used by the beacon implementation of the X-Pipe daemon and APIs is `21721`.
|
||||
It can be changed by passing the property `io.xpipe.beacon.port=<port>` to both the daemon and APIs.
|
||||
|
@ -32,6 +32,7 @@ The beacon API also supports launching the daemon automatically in case it is no
|
|||
By default, it launches the daemon of the local X-Pipe installation.
|
||||
It is possible to pass a custom launch command with the property `io.xpipe.beacon.exec=<cmd>`.
|
||||
This allows for a custom launch behaviour in a testing/development environment.
|
||||
Note that the `<cmd>` value has to be a single property string, which can be prone to formatting errors
|
||||
|
||||
By passing the property `io.xpipe.beacon.debugOutput=true`, it is possible to print debug information
|
||||
about the underlying communications.
|
||||
|
|
|
@ -8,8 +8,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
|
|||
import com.fasterxml.jackson.databind.node.TextNode;
|
||||
import io.xpipe.beacon.exchange.MessageExchanges;
|
||||
import io.xpipe.beacon.exchange.data.ClientErrorMessage;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.exchange.data.ServerErrorMessage;
|
||||
import io.xpipe.core.util.JacksonHelper;
|
||||
|
||||
|
@ -32,12 +30,6 @@ public class BeaconClient implements AutoCloseable {
|
|||
void accept(T var1, U var2) throws E;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FailableBiPredicate<T, U, E extends Throwable> {
|
||||
|
||||
boolean test(T var1, U var2) throws E;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FailableConsumer<T, E extends Throwable> {
|
||||
|
||||
|
@ -76,30 +68,6 @@ public class BeaconClient implements AutoCloseable {
|
|||
}
|
||||
}
|
||||
|
||||
public <REQ extends RequestMessage, RES extends ResponseMessage> void exchange(
|
||||
REQ req,
|
||||
FailableConsumer<OutputStream, IOException> reqWriter,
|
||||
FailableBiConsumer<RES, InputStream, IOException> resReader)
|
||||
throws ConnectorException, ClientException, ServerException {
|
||||
try {
|
||||
sendRequest(req);
|
||||
if (reqWriter != null) {
|
||||
out.write(BODY_SEPARATOR);
|
||||
reqWriter.accept(out);
|
||||
}
|
||||
|
||||
var res = this.<RES>receiveResponse();
|
||||
var sep = in.readNBytes(BODY_SEPARATOR.length);
|
||||
if (sep.length != 0 && !Arrays.equals(BODY_SEPARATOR, sep)) {
|
||||
throw new ConnectorException("Invalid body separator");
|
||||
}
|
||||
|
||||
resReader.accept(res, in);
|
||||
} catch (IOException ex) {
|
||||
throw new ConnectorException("Couldn't communicate with socket", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream receiveBody() throws ConnectorException {
|
||||
try {
|
||||
var sep = in.readNBytes(BODY_SEPARATOR.length);
|
||||
|
@ -238,16 +206,4 @@ public class BeaconClient implements AutoCloseable {
|
|||
throw new ConnectorException("Couldn't parse response", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return in;
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
return out;
|
||||
}
|
||||
|
||||
public Socket getSocket() {
|
||||
return socket;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package io.xpipe.beacon;
|
||||
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
|
|
@ -13,7 +13,7 @@ import java.nio.file.Path;
|
|||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Contains basic functionality to start, communicate, and stop a beacon server.
|
||||
* Contains basic functionality to start, communicate, and stop a remote beacon server.
|
||||
*/
|
||||
@UtilityClass
|
||||
public class BeaconServer {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package io.xpipe.beacon.message;
|
||||
package io.xpipe.beacon;
|
||||
|
||||
public interface RequestMessage {
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package io.xpipe.beacon;
|
||||
|
||||
public interface ResponseMessage {
|
||||
|
||||
}
|
|
@ -1,11 +1,8 @@
|
|||
package io.xpipe.beacon;
|
||||
|
||||
import lombok.experimental.StandardException;
|
||||
|
||||
/**
|
||||
* Indicates that an internal server error occurred.
|
||||
*/
|
||||
@StandardException
|
||||
public class ServerException extends Exception {
|
||||
|
||||
public ServerException() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.beacon.exchange;
|
||||
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.dialog.DialogReference;
|
||||
import io.xpipe.core.source.DataSourceId;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.beacon.exchange;
|
||||
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
|
@ -15,26 +15,23 @@ public class MessageExchanges {
|
|||
private static void loadAll() {
|
||||
if (ALL == null) {
|
||||
ALL = ServiceLoader.load(MessageExchange.class).stream()
|
||||
.map(s -> (MessageExchange) s.get()).collect(Collectors.toSet());
|
||||
.map(ServiceLoader.Provider::get).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange> byId(String name) {
|
||||
public static Optional<MessageExchange> byId(String name) {
|
||||
loadAll();
|
||||
var r = ALL.stream().filter(d -> d.getId().equals(name)).findAny();
|
||||
return Optional.ofNullable((MessageExchange) r.orElse(null));
|
||||
return ALL.stream().filter(d -> d.getId().equals(name)).findAny();
|
||||
}
|
||||
|
||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange> byRequest(RQ req) {
|
||||
public static <RQ extends RequestMessage> Optional<MessageExchange> byRequest(RQ req) {
|
||||
loadAll();
|
||||
var r = ALL.stream().filter(d -> d.getRequestClass().equals(req.getClass())).findAny();
|
||||
return r;
|
||||
return ALL.stream().filter(d -> d.getRequestClass().equals(req.getClass())).findAny();
|
||||
}
|
||||
|
||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange> byResponse(RP rep) {
|
||||
public static <RP extends ResponseMessage> Optional<MessageExchange> byResponse(RP rep) {
|
||||
loadAll();
|
||||
var r = ALL.stream().filter(d -> d.getResponseClass().equals(rep.getClass())).findAny();
|
||||
return r;
|
||||
return ALL.stream().filter(d -> d.getResponseClass().equals(rep.getClass())).findAny();
|
||||
}
|
||||
|
||||
public static Set<MessageExchange> getAll() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.beacon.exchange;
|
||||
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceId;
|
||||
import io.xpipe.core.source.DataSourceInfo;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package io.xpipe.beacon.exchange;
|
||||
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceId;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import lombok.Builder;
|
||||
|
@ -26,8 +25,6 @@ public class ReadExecuteExchange implements MessageExchange {
|
|||
public static class Request implements RequestMessage {
|
||||
@NonNull
|
||||
DataStore dataStore;
|
||||
@NonNull
|
||||
DataSourceConfigInstance config;
|
||||
|
||||
DataSourceId target;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.beacon.exchange;
|
||||
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.dialog.DialogReference;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import lombok.Builder;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.beacon.exchange;
|
||||
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.beacon.exchange;
|
||||
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.store.FileStore;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.api;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.api;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.api;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.dialog.DialogReference;
|
||||
import io.xpipe.core.source.DataSourceId;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.dialog.DialogElement;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -2,8 +2,8 @@ package io.xpipe.beacon.exchange.cli;
|
|||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.exchange.data.CollectionListEntry;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
|
|
@ -2,8 +2,8 @@ package io.xpipe.beacon.exchange.cli;
|
|||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.exchange.data.EntryListEntry;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
|
|
@ -2,8 +2,8 @@ package io.xpipe.beacon.exchange.cli;
|
|||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.exchange.data.StoreListEntry;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -2,8 +2,8 @@ package io.xpipe.beacon.exchange.cli;
|
|||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.exchange.data.ProviderEntry;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceType;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceId;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
import lombok.Builder;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceId;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
import lombok.Builder;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.dialog.DialogReference;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import lombok.Builder;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceConfigInstance;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
|
@ -26,9 +25,6 @@ public class WriteExecuteExchange implements MessageExchange {
|
|||
public static class Request implements RequestMessage {
|
||||
@NonNull
|
||||
DataSourceReference ref;
|
||||
|
||||
@NonNull
|
||||
DataSourceConfigInstance config;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package io.xpipe.beacon.exchange.cli;
|
||||
|
||||
import io.xpipe.beacon.exchange.MessageExchange;
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.RequestMessage;
|
||||
import io.xpipe.beacon.ResponseMessage;
|
||||
import io.xpipe.core.dialog.DialogReference;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
import io.xpipe.core.store.StreamDataStore;
|
||||
|
|
|
@ -6,6 +6,7 @@ import lombok.Builder;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
@Value
|
||||
@Builder
|
||||
@Jacksonized
|
||||
|
|
|
@ -8,6 +8,7 @@ import lombok.extern.jackson.Jacksonized;
|
|||
|
||||
import java.util.UUID;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord")
|
||||
@Value
|
||||
@Builder
|
||||
@Jacksonized
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
package io.xpipe.beacon.message;
|
||||
|
||||
import io.xpipe.beacon.BeaconHandler;
|
||||
|
||||
public interface ResponseMessage {
|
||||
|
||||
default void postSend(BeaconHandler handler) throws Exception {
|
||||
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ import io.xpipe.beacon.exchange.cli.*;
|
|||
module io.xpipe.beacon {
|
||||
exports io.xpipe.beacon;
|
||||
exports io.xpipe.beacon.exchange;
|
||||
exports io.xpipe.beacon.message;
|
||||
exports io.xpipe.beacon.exchange.api;
|
||||
exports io.xpipe.beacon.exchange.data;
|
||||
exports io.xpipe.beacon.exchange.cli;
|
||||
|
@ -13,7 +12,6 @@ module io.xpipe.beacon {
|
|||
opens io.xpipe.beacon;
|
||||
opens io.xpipe.beacon.exchange;
|
||||
opens io.xpipe.beacon.exchange.api;
|
||||
opens io.xpipe.beacon.message;
|
||||
opens io.xpipe.beacon.exchange.data;
|
||||
opens io.xpipe.beacon.exchange.cli;
|
||||
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
plugins {
|
||||
id 'java'
|
||||
id "org.moditect.gradleplugin" version "1.0.0-rc3"
|
||||
}
|
||||
|
||||
apply from: "$rootDir/deps/java.gradle"
|
||||
apply from: "$rootDir/deps/commons.gradle"
|
||||
apply from: "$rootDir/deps/junit.gradle"
|
||||
apply from: "$rootDir/deps/lombok.gradle"
|
||||
apply from: "$rootDir/deps/jackson.gradle"
|
||||
|
||||
|
||||
configurations {
|
||||
compileOnly.extendsFrom(dep)
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
module io.xpipe.charsetter {
|
||||
exports io.xpipe.charsetter;
|
||||
|
||||
requires org.apache.commons.io;
|
||||
requires org.apache.commons.lang3;
|
||||
requires static lombok;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
}
|
|
@ -2,19 +2,20 @@
|
|||
[![javadoc](https://javadoc.io/badge2/io.xpipe/core/javadoc.svg)](https://javadoc.io/doc/io.xpipe/core)
|
||||
[![Build Status](https://github.com/xpipe-io/xpipe_java/actions/workflows/core-build.yml/badge.svg)](https://github.com/xpipe-io/xpipe_java/actions/workflows/core-build.yml)
|
||||
|
||||
|
||||
## X-Pipe Core
|
||||
|
||||
The X-Pipe core component contains all the shared core classes used by the API, beacon, and daemon.
|
||||
The X-Pipe core module contains all the shared core classes used by the API, beacon, and daemon implementation.
|
||||
|
||||
The main part can be found in the [data package]().
|
||||
The main component is the [data package](src/main/java/io/xpipe/core/data).
|
||||
It contains all definitions of the internal X-Pipe data model and all IO functionality for these data structures.
|
||||
|
||||
The [source package]() contains the basic data source model classes.
|
||||
These have to be used by every custom data source implementation.
|
||||
The [source package](src/main/java/io/xpipe/core/source) contains the basic data source classes,
|
||||
which are used by every data source implementation.
|
||||
|
||||
The [store package]() contains the basic data store model classes.
|
||||
These have to be used by every custom data store implementation.
|
||||
The [store package](src/main/java/io/xpipe/core/store) contains the basic data store classes,
|
||||
which are used by every data store implementation.
|
||||
|
||||
Every class is expected to be potentially used in the context of files and message exchanges.
|
||||
As a result, all data structures exchanged must be serializable/deserializable with jackson.
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ apply from: "$rootDir/deps/publish-base.gradle"
|
|||
|
||||
configurations {
|
||||
compileOnly.extendsFrom(dep)
|
||||
testImplementation.extendsFrom(dep)
|
||||
}
|
||||
|
||||
version = file('../version').text
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package io.xpipe.charsetter;
|
||||
package io.xpipe.core.charsetter;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
|
@ -1,10 +1,6 @@
|
|||
package io.xpipe.charsetter;
|
||||
package io.xpipe.core.charsetter;
|
||||
|
||||
import lombok.Value;
|
||||
import org.apache.commons.io.ByteOrderMark;
|
||||
import org.apache.commons.io.input.BOMInputStream;
|
||||
import org.apache.commons.lang3.function.FailableConsumer;
|
||||
import org.apache.commons.lang3.function.FailableSupplier;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
@ -15,52 +11,46 @@ import java.util.Comparator;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Charsetter {
|
||||
public abstract class Charsetter {
|
||||
|
||||
private static CharsetterUniverse universe;
|
||||
private static final int MAX_BYTES = 8192;
|
||||
|
||||
public static void init(CharsetterContext ctx) {
|
||||
universe = CharsetterUniverse.create(ctx);
|
||||
}
|
||||
|
||||
private static void checkInit() {
|
||||
protected static void checkInit() {
|
||||
if (universe == null) {
|
||||
throw new IllegalStateException("Charsetter not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
public static void init(CharsetterContext ctx) {
|
||||
universe = CharsetterUniverse.create(ctx);
|
||||
}
|
||||
|
||||
@Value
|
||||
public static class Result {
|
||||
Charset charset;
|
||||
NewLine newLine;
|
||||
}
|
||||
|
||||
public static Result read(FailableSupplier<InputStream, Exception> in, FailableConsumer<InputStreamReader, Exception> con) throws Exception {
|
||||
checkInit();
|
||||
public static Charsetter INSTANCE;
|
||||
|
||||
try (var is = in.get();
|
||||
var bin = new BOMInputStream(is)) {
|
||||
ByteOrderMark bom = bin.getBOM();
|
||||
String charsetName = bom == null ? null : bom.getCharsetName();
|
||||
var charset = charsetName != null ? Charset.forName(charsetName) : null;
|
||||
|
||||
bin.mark(MAX_BYTES);
|
||||
var bytes = bin.readNBytes(MAX_BYTES);
|
||||
bin.reset();
|
||||
if (charset == null) {
|
||||
charset = inferCharset(bytes);
|
||||
}
|
||||
var nl = inferNewLine(bytes);
|
||||
|
||||
if (con != null) {
|
||||
con.accept(new InputStreamReader(bin, charset));
|
||||
}
|
||||
return new Result(charset, nl);
|
||||
}
|
||||
public static Charsetter get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static NewLine inferNewLine(byte[] content) {
|
||||
@FunctionalInterface
|
||||
public interface FailableSupplier<R, E extends Throwable> {
|
||||
R get() throws E;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FailableConsumer<T, E extends Throwable> {
|
||||
|
||||
void accept(T var1) throws E;
|
||||
}
|
||||
|
||||
public abstract Result read(FailableSupplier<InputStream, Exception> in, FailableConsumer<InputStreamReader, Exception> con) throws Exception;
|
||||
|
||||
public NewLine inferNewLine(byte[] content) {
|
||||
Map<NewLine, Integer> count = new HashMap<>();
|
||||
for (var nl : NewLine.values()) {
|
||||
var nlBytes = nl.getNewLine().getBytes(StandardCharsets.UTF_8);
|
||||
|
@ -75,7 +65,7 @@ public class Charsetter {
|
|||
.orElseThrow().getKey();
|
||||
}
|
||||
|
||||
public static int count(byte[] outerArray, byte[] smallerArray) {
|
||||
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;
|
||||
|
@ -92,7 +82,7 @@ public class Charsetter {
|
|||
return count;
|
||||
}
|
||||
|
||||
public static Charset inferCharset(byte[] content) {
|
||||
public Charset inferCharset(byte[] content) {
|
||||
checkInit();
|
||||
|
||||
for (Charset c : universe.getCharsets()) {
|
|
@ -1,4 +1,4 @@
|
|||
package io.xpipe.charsetter;
|
||||
package io.xpipe.core.charsetter;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
|
@ -1,4 +1,4 @@
|
|||
package io.xpipe.charsetter;
|
||||
package io.xpipe.core.charsetter;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
|
@ -1,4 +1,4 @@
|
|||
package io.xpipe.charsetter;
|
||||
package io.xpipe.core.charsetter;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
|
@ -79,7 +79,13 @@ public class GenericDataStreamParser {
|
|||
}
|
||||
|
||||
private static void parseValue(InputStream in, GenericDataStreamCallback cb) throws IOException {
|
||||
var textual = in.read() != 0;
|
||||
var type = in.read();
|
||||
if (type == DataStructureNodeIO.VALUE_TYPE_NULL) {
|
||||
cb.onValue(null, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var textual = type == DataStructureNodeIO.VALUE_TYPE_TEXT;
|
||||
var size = in.read();
|
||||
var data = in.readNBytes(size);
|
||||
cb.onValue(data, textual);
|
||||
|
|
|
@ -51,10 +51,15 @@ public class GenericDataStreamWriter {
|
|||
}
|
||||
}
|
||||
|
||||
private static void writeValue(OutputStream out, ValueNode value) throws IOException {
|
||||
private static void writeValue(OutputStream out, ValueNode n) throws IOException {
|
||||
out.write(DataStructureNodeIO.GENERIC_VALUE_ID);
|
||||
out.write(value.isTextual() ? 1 : 0);
|
||||
out.write(value.getRawData().length);
|
||||
out.write(value.getRawData());
|
||||
if (n.isNull()) {
|
||||
out.write(DataStructureNodeIO.VALUE_TYPE_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
out.write(n.isTextual() ? DataStructureNodeIO.VALUE_TYPE_TEXT : DataStructureNodeIO.VALUE_TYPE_BARE);
|
||||
out.write(n.getRawData().length);
|
||||
out.write(n.getRawData());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,4 +12,8 @@ public class DataStructureNodeIO {
|
|||
public static final int TYPED_TUPLE_ID = 6;
|
||||
public static final int TYPED_ARRAY_ID = 7;
|
||||
public static final int TYPED_VALUE_ID = 8;
|
||||
|
||||
public static final int VALUE_TYPE_BARE = 0;
|
||||
public static final int VALUE_TYPE_TEXT = 1;
|
||||
public static final int VALUE_TYPE_NULL = 2;
|
||||
}
|
||||
|
|
|
@ -21,9 +21,18 @@ public class MutableValueNode extends ValueNode {
|
|||
|
||||
@Override
|
||||
public String toString(int indent) {
|
||||
if (isNull()) {
|
||||
return "null (M)";
|
||||
}
|
||||
|
||||
return (textual ? "\"" : "") + new String(data) + (textual ? "\"" : "") + " (M)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNull() {
|
||||
return data == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTextual() {
|
||||
return textual;
|
||||
|
|
|
@ -129,7 +129,13 @@ public class TypedDataStreamParser {
|
|||
}
|
||||
|
||||
private void parseValue(InputStream in, TypedDataStreamCallback cb) throws IOException {
|
||||
var textual = in.read() != 0;
|
||||
var type = in.read();
|
||||
if (type == DataStructureNodeIO.VALUE_TYPE_NULL) {
|
||||
cb.onValue(null, false);
|
||||
return;
|
||||
}
|
||||
|
||||
var textual = type == DataStructureNodeIO.VALUE_TYPE_TEXT;
|
||||
var size = in.read();
|
||||
var data = in.readNBytes(size);
|
||||
cb.onValue(data, textual);
|
||||
|
|
|
@ -32,7 +32,12 @@ public class TypedDataStreamWriter {
|
|||
|
||||
private static void writeValue(OutputStream out, ValueNode n) throws IOException {
|
||||
out.write(DataStructureNodeIO.TYPED_VALUE_ID);
|
||||
out.write(n.isTextual() ? 1 : 0);
|
||||
if (n.isNull()) {
|
||||
out.write(DataStructureNodeIO.VALUE_TYPE_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
out.write(n.isTextual() ? DataStructureNodeIO.VALUE_TYPE_TEXT : DataStructureNodeIO.VALUE_TYPE_BARE);
|
||||
out.write(n.getRawData().length);
|
||||
out.write(n.getRawData());
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
package io.xpipe.core.dialog;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
@AllArgsConstructor
|
||||
public class ConfigParameter {
|
||||
String key;
|
||||
|
||||
@JsonCreator
|
||||
public ConfigParameter(String key) {
|
||||
this.key = key;
|
||||
this.converter = null;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
QueryConverter<?> converter;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> QueryConverter<T> getConverter() {
|
||||
return (QueryConverter<T>) converter;
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package io.xpipe.core.dialog;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Value
|
||||
@AllArgsConstructor(onConstructor_={@JsonCreator})
|
||||
public class ConfigParameterSetInstance {
|
||||
|
||||
/**
|
||||
* The available configuration parameters.
|
||||
*/
|
||||
List<ConfigParameter> configParameters;
|
||||
|
||||
/**
|
||||
* The current configuration options that are set.
|
||||
*/
|
||||
Map<String, String> currentValues;
|
||||
|
||||
public ConfigParameterSetInstance(Map<ConfigParameter, Object> map) {
|
||||
configParameters = map.keySet().stream().toList();
|
||||
currentValues = map.entrySet().stream().collect(Collectors.toMap(
|
||||
e -> e.getKey().getKey(),
|
||||
e -> e.getKey().getConverter().convertToString(e.getValue())));
|
||||
}
|
||||
|
||||
public <X, T extends Function<X,?>> ConfigParameterSetInstance(Map<ConfigParameter, T> map, Object v) {
|
||||
configParameters = map.keySet().stream().toList();
|
||||
currentValues = map.entrySet().stream().collect(Collectors.toMap(
|
||||
e -> e.getKey().getKey(),
|
||||
e -> e.getKey().getConverter().convertToString(apply(e.getValue(), v))));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <X, T extends Function<X,?>, V> Object apply(T func, Object v) {
|
||||
return func.apply((X) v);
|
||||
}
|
||||
|
||||
public void update(ConfigParameter p, String val) {
|
||||
currentValues.put(p.getKey(), val);
|
||||
}
|
||||
|
||||
public Map<ConfigParameter, Object> evaluate() {
|
||||
return configParameters.stream().collect(Collectors.toMap(
|
||||
p -> p,
|
||||
p -> p.getConverter().convertFromString(currentValues.get(p.getKey()))));
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package io.xpipe.core.source;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import io.xpipe.core.dialog.ConfigParameter;
|
||||
import io.xpipe.core.dialog.ConfigParameterSetInstance;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Represents the current configuration of a data source.
|
||||
* This configuration can either be in progress or complete.
|
||||
*/
|
||||
@Value
|
||||
@AllArgsConstructor(onConstructor_={@JsonCreator})
|
||||
public class DataSourceConfigInstance {
|
||||
|
||||
public static DataSourceConfigInstance xpbt() {
|
||||
return new DataSourceConfigInstance("xpbt", new ConfigParameterSetInstance(Map.of()));
|
||||
}
|
||||
|
||||
/**
|
||||
* The data source provider id.
|
||||
*/
|
||||
String provider;
|
||||
|
||||
/**
|
||||
* The available configuration parameters.
|
||||
*/
|
||||
ConfigParameterSetInstance configInstance;
|
||||
|
||||
public DataSourceConfigInstance(String provider, Map<ConfigParameter, Object> map) {
|
||||
this.provider = provider;
|
||||
this.configInstance = new ConfigParameterSetInstance(map);
|
||||
}
|
||||
|
||||
public <X, T extends Function<X,?>> DataSourceConfigInstance(String provider, Map<ConfigParameter, T> map, Object val) {
|
||||
this.provider = provider;
|
||||
this.configInstance = new ConfigParameterSetInstance(map, val);
|
||||
}
|
||||
|
||||
public Map<ConfigParameter, Object> evaluate() {
|
||||
return configInstance.evaluate();
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@ module io.xpipe.core {
|
|||
exports io.xpipe.core.data.node;
|
||||
exports io.xpipe.core.data.typed;
|
||||
exports io.xpipe.core.dialog;
|
||||
exports io.xpipe.core.connection;
|
||||
|
||||
opens io.xpipe.core.store;
|
||||
opens io.xpipe.core.source;
|
||||
|
@ -19,6 +18,7 @@ module io.xpipe.core {
|
|||
opens io.xpipe.core.data.node;
|
||||
opens io.xpipe.core.data.typed;
|
||||
opens io.xpipe.core.dialog;
|
||||
exports io.xpipe.core.charsetter;
|
||||
|
||||
requires com.fasterxml.jackson.core;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
|
|
|
@ -5,16 +5,14 @@
|
|||
## X-Pipe Extension API
|
||||
|
||||
The X-Pipe extension API allows you to create extensions of any kind for X-Pipe.
|
||||
|
||||
This includes:
|
||||
- Custom data stores, including configuration GUI and CLI
|
||||
- Custom data sources, including configuration GUI and CLI
|
||||
- Custom preferences entries
|
||||
|
||||
### Custom data sources
|
||||
|
||||
A custom data source type can be implemented by creating a custom [DataSourceProvider]().
|
||||
A custom data source type can be implemented by creating a custom
|
||||
[DataSourceProvider](src/main/java/io/xpipe/extension/DataSourceProvider.java).
|
||||
This provider contains all the information required for proper handling of your custom data sources,
|
||||
whether you access it from the CLI, any API, or the X-Pipe commander gui.
|
||||
|
||||
### Custom data sinks
|
||||
|
||||
A custom data sink type can be implemented by creating a custom [DataSinkProvider]().
|
||||
As the notion of a sink is abstract, it allows you to basically implement any type of sink you want.
|
||||
Whether the target is a programming language, another application, a database, or a regular file.
|
|
@ -32,7 +32,6 @@ repositories {
|
|||
dependencies {
|
||||
compileOnly 'org.junit.jupiter:junit-jupiter-api:5.8.2'
|
||||
implementation project(':core')
|
||||
implementation project(':charsetter')
|
||||
|
||||
implementation 'io.xpipe:fxcomps:0.1'
|
||||
implementation 'com.google.code.gson:gson:2.9.0'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.xpipe.extension;
|
||||
|
||||
import io.xpipe.charsetter.NewLine;
|
||||
import io.xpipe.core.charsetter.NewLine;
|
||||
import io.xpipe.core.dialog.Dialog;
|
||||
import io.xpipe.core.dialog.QueryConverter;
|
||||
import io.xpipe.core.source.DataSource;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.extension;
|
||||
|
||||
import io.xpipe.charsetter.Charsetter;
|
||||
import io.xpipe.charsetter.CharsetterContext;
|
||||
import io.xpipe.core.charsetter.Charsetter;
|
||||
import io.xpipe.core.charsetter.CharsetterContext;
|
||||
import io.xpipe.core.util.JacksonHelper;
|
||||
import io.xpipe.extension.util.ModuleHelper;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.xpipe.extension.comp;
|
||||
|
||||
import io.xpipe.charsetter.NewLine;
|
||||
import io.xpipe.core.charsetter.NewLine;
|
||||
import io.xpipe.core.source.DataSource;
|
||||
import io.xpipe.extension.I18n;
|
||||
import io.xpipe.fxcomps.Comp;
|
||||
|
|
|
@ -28,7 +28,6 @@ module io.xpipe.extension {
|
|||
requires org.kordamp.ikonli.javafx;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
requires static org.junit.jupiter.api;
|
||||
requires io.xpipe.charsetter;
|
||||
|
||||
uses DataSourceProvider;
|
||||
uses SupportedApplicationProvider;
|
||||
|
|
100
jreleaser.gradle
Normal file
100
jreleaser.gradle
Normal file
|
@ -0,0 +1,100 @@
|
|||
def isPreRelease = project.version.endsWith('-pre')
|
||||
def isFullRelease = !isPreRelease && !project.version.endsWith('-SNAPSHOT')
|
||||
def proj = project
|
||||
def canonicalVersion = file('canonical_version').text
|
||||
|
||||
jreleaser {
|
||||
environment {
|
||||
properties.put('rawChangelog', file("changelogs/${canonicalVersion}.txt").exists() ?
|
||||
file("changelogs/${canonicalVersion}.txt").text.replace('\r\n', '\n') : "")
|
||||
}
|
||||
|
||||
project {
|
||||
name = 'Pdx-Unlimiter'
|
||||
description = 'A smart savegame manager, editor, and toolbox for all current major Paradox Grand Strategy games.'
|
||||
longDescription = 'The Pdx-Unlimiter is a tool for all major Paradox Grand Strategy games that provides a ' +
|
||||
'powerful and smart savegame manager to quickly organize and play all of your savegames with ease. ' +
|
||||
'Furthermore, it also comes with an Ironman converter, a powerful savegame editor, some savescumming ' +
|
||||
'tools, integrations for various other great community-made tools for all major Paradox games.'
|
||||
website = 'https://github.com/crschnick/pdx_unlimiter'
|
||||
authors = ['Christopher Schnick']
|
||||
license = 'GPL3'
|
||||
copyright = ' '
|
||||
|
||||
java {
|
||||
groupId = 'com.crschnick.pdxu'
|
||||
version = '17'
|
||||
multiProject = true
|
||||
}
|
||||
|
||||
snapshot {
|
||||
enabled = true
|
||||
pattern = '.*-SNAPSHOT'
|
||||
label = 'early-access'
|
||||
}
|
||||
}
|
||||
|
||||
release {
|
||||
github {
|
||||
skipRelease = !isFullRelease && !isPreRelease
|
||||
skipTag = !isFullRelease && !isPreRelease
|
||||
owner = 'crschnick'
|
||||
overwrite = false
|
||||
tagName = '{{projectVersion}}'
|
||||
releaseName = '{{tagName}}'
|
||||
token = proj.hasProperty("PDXU_GITHUB_TOKEN") ? proj.property("PDXU_GITHUB_TOKEN") : System.getenv("JRELEASER_GITHUB_TOKEN")
|
||||
|
||||
files = true
|
||||
artifacts = true
|
||||
checksums = false
|
||||
signatures = false
|
||||
|
||||
// Always set a pre-release, as drafts do not fully work
|
||||
prerelease {
|
||||
enabled = true
|
||||
pattern = '.*'
|
||||
}
|
||||
|
||||
update {
|
||||
enabled = true
|
||||
section('ASSETS')
|
||||
section('TITLE')
|
||||
section('BODY')
|
||||
}
|
||||
|
||||
changelog {
|
||||
enabled = true
|
||||
formatted = 'ALWAYS'
|
||||
contentTemplate = isFullRelease ? file('misc/github_full.tpl') : file('misc/github_pre.tpl')
|
||||
}
|
||||
}
|
||||
}
|
||||
distributions {
|
||||
app {
|
||||
if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {
|
||||
artifact {
|
||||
distributionType = 'BINARY'
|
||||
path = 'build/pdx_unlimiter-windows.zip'
|
||||
platform = 'windows'
|
||||
}
|
||||
} else {
|
||||
artifact {
|
||||
distributionType = 'BINARY'
|
||||
path = 'build/pdx_unlimiter-linux.zip'
|
||||
platform = 'linux'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
announce {
|
||||
enabled = isFullRelease || isPreRelease
|
||||
discord {
|
||||
active = 'ALWAYS'
|
||||
|
||||
webhook = proj.hasProperty("PDXU_DISCORD_WEBHOOK") ? proj.property("PDXU_DISCORD_WEBHOOK") : System.getenv("JRELEASER_DISCORD_WEBHOOK")
|
||||
|
||||
messageTemplate = isFullRelease ? 'misc/discord_full.tpl' : 'misc/discord_pre.tpl'
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue