mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
Refactor exchanges, add dialog APIs, add store providers
This commit is contained in:
parent
f4f9c1d978
commit
696568d5bc
50 changed files with 791 additions and 206 deletions
|
@ -13,7 +13,7 @@ import lombok.extern.jackson.Jacksonized;
|
|||
/**
|
||||
* Performs an edit for a data source.
|
||||
*/
|
||||
public class EditExecuteExchange implements MessageExchange<EditExecuteExchange.Request, EditExecuteExchange.Response> {
|
||||
public class EditExecuteExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -12,23 +12,13 @@ import lombok.extern.jackson.Jacksonized;
|
|||
/**
|
||||
* Requests to edit a data source.
|
||||
*/
|
||||
public class EditPreparationExchange implements MessageExchange<EditPreparationExchange.Request, EditPreparationExchange.Response> {
|
||||
public class EditPreparationExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "editPreparation";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<EditPreparationExchange.Request> getRequestClass() {
|
||||
return EditPreparationExchange.Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<EditPreparationExchange.Response> getResponseClass() {
|
||||
return EditPreparationExchange.Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package io.xpipe.beacon.exchange;
|
||||
|
||||
import io.xpipe.beacon.message.RequestMessage;
|
||||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
/**
|
||||
* A message exchange scheme that implements a certain functionality.
|
||||
*/
|
||||
public interface MessageExchange<RQ extends RequestMessage, RP extends ResponseMessage> {
|
||||
public interface MessageExchange {
|
||||
|
||||
/**
|
||||
* The unique id of this exchange that will be included in the messages.
|
||||
|
@ -19,10 +17,10 @@ public interface MessageExchange<RQ extends RequestMessage, RP extends ResponseM
|
|||
*/
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
default Class<RQ> getRequestClass() {
|
||||
default Class<?> getRequestClass() {
|
||||
var c = getClass().getSuperclass();
|
||||
var name = (MessageExchange.class.isAssignableFrom(c) ? c : getClass()).getName() + "$Request";
|
||||
return (Class<RQ>) Class.forName(name);
|
||||
return Class.forName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,9 +28,9 @@ public interface MessageExchange<RQ extends RequestMessage, RP extends ResponseM
|
|||
*/
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
default Class<RP> getResponseClass() {
|
||||
default Class<?> getResponseClass() {
|
||||
var c = getClass().getSuperclass();
|
||||
var name = (MessageExchange.class.isAssignableFrom(c) ? c : getClass()).getName() + "$Response";
|
||||
return (Class<RP>) Class.forName(name);
|
||||
return Class.forName(name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,37 +10,34 @@ import java.util.stream.Collectors;
|
|||
|
||||
public class MessageExchanges {
|
||||
|
||||
private static Set<MessageExchange<?,?>> ALL;
|
||||
private static Set<MessageExchange> ALL;
|
||||
|
||||
private static void loadAll() {
|
||||
if (ALL == null) {
|
||||
ALL = ServiceLoader.load(MessageExchange.class).stream()
|
||||
.map(s -> (MessageExchange<?,?>) s.get()).collect(Collectors.toSet());
|
||||
.map(s -> (MessageExchange) s.get()).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange<RQ, RP>> byId(String name) {
|
||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange> byId(String name) {
|
||||
loadAll();
|
||||
var r = ALL.stream().filter(d -> d.getId().equals(name)).findAny();
|
||||
return Optional.ofNullable((MessageExchange<RQ, RP>) r.orElse(null));
|
||||
return Optional.ofNullable((MessageExchange) r.orElse(null));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange<RQ, RP>> byRequest(RQ req) {
|
||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange> byRequest(RQ req) {
|
||||
loadAll();
|
||||
var r = ALL.stream().filter(d -> d.getRequestClass().equals(req.getClass())).findAny();
|
||||
return Optional.ofNullable((MessageExchange<RQ, RP>) r.orElse(null));
|
||||
return r;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange<RQ, RP>> byResponse(RP rep) {
|
||||
public static <RQ extends RequestMessage, RP extends ResponseMessage> Optional<MessageExchange> byResponse(RP rep) {
|
||||
loadAll();
|
||||
var r = ALL.stream().filter(d -> d.getResponseClass().equals(rep.getClass())).findAny();
|
||||
return Optional.ofNullable((MessageExchange<RQ, RP>) r.orElse(null));
|
||||
return r;
|
||||
}
|
||||
|
||||
public static Set<MessageExchange<?,?>> getAll() {
|
||||
public static Set<MessageExchange> getAll() {
|
||||
loadAll();
|
||||
return ALL;
|
||||
}
|
||||
|
|
|
@ -12,23 +12,13 @@ import lombok.extern.jackson.Jacksonized;
|
|||
/**
|
||||
* Queries general information about a data source.
|
||||
*/
|
||||
public class QueryDataSourceExchange implements MessageExchange<QueryDataSourceExchange.Request, QueryDataSourceExchange.Response> {
|
||||
public class QueryDataSourceExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "queryDataSource";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<QueryDataSourceExchange.Request> getRequestClass() {
|
||||
return QueryDataSourceExchange.Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<QueryDataSourceExchange.Response> getResponseClass() {
|
||||
return QueryDataSourceExchange.Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -13,23 +13,13 @@ import lombok.extern.jackson.Jacksonized;
|
|||
/**
|
||||
* Sends stream-based data to a daemon.
|
||||
*/
|
||||
public class ReadExecuteExchange implements MessageExchange<ReadExecuteExchange.Request, ReadExecuteExchange.Response> {
|
||||
public class ReadExecuteExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "readExecute";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ReadExecuteExchange.Request> getRequestClass() {
|
||||
return ReadExecuteExchange.Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ReadExecuteExchange.Response> getResponseClass() {
|
||||
return ReadExecuteExchange.Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -3,7 +3,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.core.store.StreamDataStore;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
@ -12,23 +12,13 @@ import lombok.extern.jackson.Jacksonized;
|
|||
/**
|
||||
* Prepares a client to send stream-based data to a daemon.
|
||||
*/
|
||||
public class ReadPreparationExchange implements MessageExchange<ReadPreparationExchange.Request, ReadPreparationExchange.Response> {
|
||||
public class ReadPreparationExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "readPreparation";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ReadPreparationExchange.Request> getRequestClass() {
|
||||
return ReadPreparationExchange.Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ReadPreparationExchange.Response> getResponseClass() {
|
||||
return ReadPreparationExchange.Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
@ -36,7 +26,7 @@ public class ReadPreparationExchange implements MessageExchange<ReadPreparationE
|
|||
String provider;
|
||||
|
||||
@NonNull
|
||||
StreamDataStore store;
|
||||
DataStore store;
|
||||
|
||||
boolean configureAll;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import lombok.NonNull;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class RemoveCollectionExchange implements MessageExchange<RemoveCollectionExchange.Request, RemoveCollectionExchange.Response> {
|
||||
public class RemoveCollectionExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -9,7 +9,7 @@ import lombok.NonNull;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class RemoveEntryExchange implements MessageExchange<RemoveEntryExchange.Request, RemoveEntryExchange.Response> {
|
||||
public class RemoveEntryExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -7,7 +7,7 @@ import lombok.NonNull;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class RenameCollectionExchange implements MessageExchange<RenameCollectionExchange.Request, RenameCollectionExchange.Response> {
|
||||
public class RenameCollectionExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -9,7 +9,7 @@ import lombok.NonNull;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class RenameEntryExchange implements MessageExchange<RenameEntryExchange.Request, RenameEntryExchange.Response> {
|
||||
public class RenameEntryExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -9,23 +9,13 @@ import lombok.extern.jackson.Jacksonized;
|
|||
/**
|
||||
* Requests the daemon to stop.
|
||||
*/
|
||||
public class StopExchange implements MessageExchange<StopExchange.Request, StopExchange.Response> {
|
||||
public class StopExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "stop";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<StopExchange.Request> getRequestClass() {
|
||||
return StopExchange.Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<StopExchange.Response> getResponseClass() {
|
||||
return StopExchange.Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -10,23 +10,13 @@ import lombok.extern.jackson.Jacksonized;
|
|||
/**
|
||||
* Stores a stream of data in a storage.
|
||||
*/
|
||||
public class StoreStreamExchange implements MessageExchange<StoreStreamExchange.Request, StoreStreamExchange.Response> {
|
||||
public class StoreStreamExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "storeStream";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<StoreStreamExchange.Request> getRequestClass() {
|
||||
return StoreStreamExchange.Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<StoreStreamExchange.Response> getResponseClass() {
|
||||
return StoreStreamExchange.Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -9,7 +9,7 @@ import lombok.NonNull;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class QueryRawDataExchange implements MessageExchange<QueryRawDataExchange.Request, QueryRawDataExchange.Response> {
|
||||
public class QueryRawDataExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -12,23 +12,13 @@ import lombok.extern.jackson.Jacksonized;
|
|||
/**
|
||||
* Queries data of a table data source in the xpbt format.
|
||||
*/
|
||||
public class QueryTableDataExchange implements MessageExchange<QueryTableDataExchange.Request, QueryTableDataExchange.Response> {
|
||||
public class QueryTableDataExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "queryTableData";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<QueryTableDataExchange.Request> getRequestClass() {
|
||||
return QueryTableDataExchange.Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<QueryTableDataExchange.Response> getResponseClass() {
|
||||
return QueryTableDataExchange.Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -9,7 +9,7 @@ import lombok.NonNull;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class QueryTextDataExchange implements MessageExchange<QueryTextDataExchange.Request, QueryTextDataExchange.Response> {
|
||||
public class QueryTextDataExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -12,7 +12,7 @@ import lombok.NonNull;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class ConvertExchange implements MessageExchange<ConvertExchange.Request, ConvertExchange.Response> {
|
||||
public class ConvertExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -3,12 +3,14 @@ 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.core.config.DialogElement;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class DialogExchange implements MessageExchange<DialogExchange.Request, DialogExchange.Response> {
|
||||
import java.util.UUID;
|
||||
|
||||
public class DialogExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
@ -29,8 +31,7 @@ public class DialogExchange implements MessageExchange<DialogExchange.Request, D
|
|||
@Builder
|
||||
@Value
|
||||
public static class Request implements RequestMessage {
|
||||
DataSourceConfigInstance instance;
|
||||
String key;
|
||||
UUID dialogKey;
|
||||
String value;
|
||||
}
|
||||
|
||||
|
@ -38,6 +39,7 @@ public class DialogExchange implements MessageExchange<DialogExchange.Request, D
|
|||
@Builder
|
||||
@Value
|
||||
public static class Response implements ResponseMessage {
|
||||
DialogElement element;
|
||||
String errorMsg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,23 +10,13 @@ import lombok.extern.jackson.Jacksonized;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public class ListCollectionsExchange implements MessageExchange<ListCollectionsExchange.Request, ListCollectionsExchange.Response> {
|
||||
public class ListCollectionsExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "listCollections";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Request> getRequestClass() {
|
||||
return Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Response> getResponseClass() {
|
||||
return Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -10,23 +10,13 @@ import lombok.extern.jackson.Jacksonized;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public class ListEntriesExchange implements MessageExchange<ListEntriesExchange.Request, ListEntriesExchange.Response> {
|
||||
public class ListEntriesExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "listEntries";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Request> getRequestClass() {
|
||||
return Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Response> getResponseClass() {
|
||||
return Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -8,23 +8,13 @@ import lombok.NonNull;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class ModeExchange implements MessageExchange<ModeExchange.Request, ModeExchange.Response> {
|
||||
public class ModeExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "mode";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ModeExchange.Request> getRequestClass() {
|
||||
return ModeExchange.Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<ModeExchange.Response> getResponseClass() {
|
||||
return ModeExchange.Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -13,7 +13,7 @@ import lombok.extern.jackson.Jacksonized;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ProviderListExchange implements MessageExchange<ProviderListExchange.Request, ProviderListExchange.Response> {
|
||||
public class ProviderListExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -9,23 +9,13 @@ import lombok.NonNull;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class SelectExchange implements MessageExchange<SelectExchange.Request, SelectExchange.Response> {
|
||||
public class SelectExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "select";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<SelectExchange.Request> getRequestClass() {
|
||||
return SelectExchange.Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<SelectExchange.Response> getResponseClass() {
|
||||
return SelectExchange.Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -7,23 +7,13 @@ import lombok.Builder;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class StatusExchange implements MessageExchange<StatusExchange.Request, StatusExchange.Response> {
|
||||
public class StatusExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "status";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Request> getRequestClass() {
|
||||
return Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Response> getResponseClass() {
|
||||
return Response.class;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
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.config.DialogElement;
|
||||
import lombok.Builder;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class StoreAddExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "storeAdd";
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
public static class Request implements RequestMessage {
|
||||
@NonNull
|
||||
String input;
|
||||
}
|
||||
|
||||
@Jacksonized
|
||||
@Builder
|
||||
@Value
|
||||
public static class Response implements ResponseMessage {
|
||||
UUID dialogKey;
|
||||
DialogElement dialogElement;
|
||||
}
|
||||
}
|
|
@ -7,23 +7,13 @@ import lombok.Builder;
|
|||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
public class VersionExchange implements MessageExchange<VersionExchange.Request, VersionExchange.Response> {
|
||||
public class VersionExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "version";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<VersionExchange.Request> getRequestClass() {
|
||||
return VersionExchange.Request.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<VersionExchange.Response> getResponseClass() {
|
||||
return VersionExchange.Response.class;
|
||||
}
|
||||
|
||||
@lombok.extern.jackson.Jacksonized
|
||||
@lombok.Builder
|
||||
@lombok.Value
|
||||
|
|
|
@ -13,7 +13,7 @@ import lombok.extern.jackson.Jacksonized;
|
|||
/**
|
||||
* Output the data source contents.
|
||||
*/
|
||||
public class WriteExecuteExchange implements MessageExchange<WriteExecuteExchange.Request, WriteExecuteExchange.Response> {
|
||||
public class WriteExecuteExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -14,7 +14,7 @@ import lombok.extern.jackson.Jacksonized;
|
|||
/**
|
||||
* Prepares a client to output the data source contents.
|
||||
*/
|
||||
public class WritePreparationExchange implements MessageExchange<WritePreparationExchange.Request, WritePreparationExchange.Response> {
|
||||
public class WritePreparationExchange implements MessageExchange {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
|
|
|
@ -29,6 +29,7 @@ module io.xpipe.beacon {
|
|||
ModeExchange,
|
||||
StatusExchange,
|
||||
StopExchange,
|
||||
StoreAddExchange,
|
||||
WritePreparationExchange,
|
||||
WriteExecuteExchange,
|
||||
SelectExchange,
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package io.xpipe.core.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import lombok.Getter;
|
||||
|
||||
@JsonTypeName("query")
|
||||
@Getter
|
||||
public class BaseQueryElement extends DialogElement {
|
||||
|
||||
private final String description;
|
||||
private final boolean required;
|
||||
protected String value;
|
||||
|
||||
@JsonCreator
|
||||
public BaseQueryElement(String description, boolean required, String value) {
|
||||
this.description = description;
|
||||
this.required = required;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
67
core/src/main/java/io/xpipe/core/config/ChoiceElement.java
Normal file
67
core/src/main/java/io/xpipe/core/config/ChoiceElement.java
Normal file
|
@ -0,0 +1,67 @@
|
|||
package io.xpipe.core.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@JsonTypeName("choice")
|
||||
public class ChoiceElement extends DialogElement {
|
||||
|
||||
private final List<Element> elements;
|
||||
|
||||
private int selected;
|
||||
|
||||
@Override
|
||||
public boolean apply(String value) {
|
||||
if (value == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value.length() != 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var c = value.charAt(0);
|
||||
if (Character.isDigit(c)) {
|
||||
selected = Integer.parseInt(value) - 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < elements.size(); i++) {
|
||||
if (elements.get(i).getCharacter() != null && elements.get(i).getCharacter().equals(c)) {
|
||||
selected = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
@Jacksonized
|
||||
@AllArgsConstructor
|
||||
public static class Element {
|
||||
Character character;
|
||||
String description;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public ChoiceElement(List<Element> elements, int selected) {
|
||||
this.elements = elements;
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
public List<Element> getElements() {
|
||||
return elements;
|
||||
}
|
||||
|
||||
public int getSelected() {
|
||||
return selected;
|
||||
}
|
||||
}
|
|
@ -17,10 +17,10 @@ public class ConfigParameter {
|
|||
}
|
||||
|
||||
@JsonIgnore
|
||||
ConfigConverter<?> converter;
|
||||
QueryConverter<?> converter;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> ConfigConverter<T> getConverter() {
|
||||
return (ConfigConverter<T>) converter;
|
||||
public <T> QueryConverter<T> getConverter() {
|
||||
return (QueryConverter<T>) converter;
|
||||
}
|
||||
}
|
||||
|
|
176
core/src/main/java/io/xpipe/core/config/Dialog.java
Normal file
176
core/src/main/java/io/xpipe/core/config/Dialog.java
Normal file
|
@ -0,0 +1,176 @@
|
|||
package io.xpipe.core.config;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class Dialog {
|
||||
|
||||
private static class Sequence extends Dialog {
|
||||
|
||||
private int index = 0;
|
||||
private final DialogElement[] es;
|
||||
|
||||
public Sequence(DialogElement... es) {
|
||||
this.es = es;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogElement start() {
|
||||
index = 0;
|
||||
return es[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogElement receive(String answer) {
|
||||
if (es[index].apply(answer)) {
|
||||
if (index == es.length - 1) {
|
||||
complete();
|
||||
return null;
|
||||
} else {
|
||||
return es[++index];
|
||||
}
|
||||
}
|
||||
|
||||
return es[index];
|
||||
}
|
||||
}
|
||||
|
||||
public static Dialog chain(DialogElement... es) {
|
||||
return new Dialog.Sequence(es);
|
||||
}
|
||||
|
||||
public static Dialog chain(Dialog... ds) {
|
||||
return new Dialog() {
|
||||
|
||||
private int current = 0;
|
||||
|
||||
@Override
|
||||
public DialogElement start() {
|
||||
current = 0;
|
||||
return ds[0].start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogElement receive(String answer) {
|
||||
DialogElement currentElement = ds[current].receive(answer);
|
||||
if (currentElement == null) {
|
||||
ds[current].complete();
|
||||
if (current == ds.length - 1) {
|
||||
complete();
|
||||
return null;
|
||||
} else {
|
||||
return ds[++current].start();
|
||||
}
|
||||
}
|
||||
|
||||
return currentElement;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Dialog of(DialogElement e) {
|
||||
return new Dialog() {
|
||||
|
||||
|
||||
@Override
|
||||
public DialogElement start() {
|
||||
return e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogElement receive(String answer) {
|
||||
if (e.apply(answer)) {
|
||||
complete();
|
||||
return null;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Dialog retryIf(Dialog d, Supplier<String> msg) {
|
||||
return new Dialog() {
|
||||
|
||||
private boolean retry;
|
||||
|
||||
@Override
|
||||
public DialogElement start() {
|
||||
return d.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogElement receive(String answer) {
|
||||
if (retry) {
|
||||
retry = false;
|
||||
return d.start();
|
||||
}
|
||||
|
||||
var next = d.receive(answer);
|
||||
if (next == null) {
|
||||
var s = msg.get();
|
||||
if (s != null) {
|
||||
retry = true;
|
||||
return new HeaderElement(s);
|
||||
}
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
}.evaluateTo(d.onCompletion);
|
||||
}
|
||||
|
||||
public static Dialog choice(ChoiceElement choice, Function<Integer, Dialog> c) {
|
||||
return new Dialog() {
|
||||
|
||||
private Dialog choiceMade;
|
||||
|
||||
@Override
|
||||
public DialogElement start() {
|
||||
choiceMade = null;
|
||||
return choice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialogElement receive(String answer) {
|
||||
if (choiceMade != null) {
|
||||
var r = choiceMade.receive(answer);
|
||||
if (r == null) {
|
||||
complete();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
if (choice.apply(answer)) {
|
||||
choiceMade = c.apply(choice.getSelected());
|
||||
return choiceMade.start();
|
||||
}
|
||||
|
||||
return choice;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Object eval;
|
||||
private Supplier<?> onCompletion;
|
||||
|
||||
public abstract DialogElement start();
|
||||
|
||||
public Dialog evaluateTo(Supplier<?> s) {
|
||||
onCompletion = s;
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getResult() {
|
||||
return (T) eval;
|
||||
}
|
||||
|
||||
public void complete() {
|
||||
if (onCompletion != null) {
|
||||
eval = onCompletion.get();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract DialogElement receive(String answer);
|
||||
}
|
25
core/src/main/java/io/xpipe/core/config/DialogElement.java
Normal file
25
core/src/main/java/io/xpipe/core/config/DialogElement.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package io.xpipe.core.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@EqualsAndHashCode
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
public abstract class DialogElement {
|
||||
|
||||
protected String id;
|
||||
|
||||
public DialogElement() {
|
||||
this.id = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public boolean apply(String value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
24
core/src/main/java/io/xpipe/core/config/HeaderElement.java
Normal file
24
core/src/main/java/io/xpipe/core/config/HeaderElement.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
package io.xpipe.core.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
|
||||
@JsonTypeName("header")
|
||||
public class HeaderElement extends DialogElement {
|
||||
|
||||
protected String header;
|
||||
|
||||
@JsonCreator
|
||||
public HeaderElement(String header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(String value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getHeader() {
|
||||
return header;
|
||||
}
|
||||
}
|
|
@ -2,9 +2,9 @@ package io.xpipe.core.config;
|
|||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public abstract class ConfigConverter<T> {
|
||||
public abstract class QueryConverter<T> {
|
||||
|
||||
public static final ConfigConverter<Charset> CHARSET = new ConfigConverter<Charset>() {
|
||||
public static final QueryConverter<Charset> CHARSET = new QueryConverter<Charset>() {
|
||||
@Override
|
||||
protected Charset fromString(String s) {
|
||||
return Charset.forName(s);
|
||||
|
@ -16,7 +16,7 @@ public abstract class ConfigConverter<T> {
|
|||
}
|
||||
};
|
||||
|
||||
public static final ConfigConverter<String> STRING = new ConfigConverter<String>() {
|
||||
public static final QueryConverter<String> STRING = new QueryConverter<String>() {
|
||||
@Override
|
||||
protected String fromString(String s) {
|
||||
return s;
|
||||
|
@ -28,7 +28,19 @@ public abstract class ConfigConverter<T> {
|
|||
}
|
||||
};
|
||||
|
||||
public static final ConfigConverter<Character> CHARACTER = new ConfigConverter<Character>() {
|
||||
public static final QueryConverter<Integer> INTEGER = new QueryConverter<Integer>() {
|
||||
@Override
|
||||
protected Integer fromString(String s) {
|
||||
return Integer.parseInt(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toString(Integer value) {
|
||||
return value.toString();
|
||||
}
|
||||
};
|
||||
|
||||
public static final QueryConverter<Character> CHARACTER = new QueryConverter<Character>() {
|
||||
@Override
|
||||
protected Character fromString(String s) {
|
||||
if (s.length() != 1) {
|
||||
|
@ -44,7 +56,7 @@ public abstract class ConfigConverter<T> {
|
|||
}
|
||||
};
|
||||
|
||||
public static final ConfigConverter<Boolean> BOOLEAN = new ConfigConverter<Boolean>() {
|
||||
public static final QueryConverter<Boolean> BOOLEAN = new QueryConverter<Boolean>() {
|
||||
@Override
|
||||
protected Boolean fromString(String s) {
|
||||
if (s.equalsIgnoreCase("y") || s.equalsIgnoreCase("yes") || s.equalsIgnoreCase("true")) {
|
47
core/src/main/java/io/xpipe/core/config/QueryElement.java
Normal file
47
core/src/main/java/io/xpipe/core/config/QueryElement.java
Normal file
|
@ -0,0 +1,47 @@
|
|||
package io.xpipe.core.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
|
||||
@JsonSerialize(as = BaseQueryElement.class)
|
||||
public class QueryElement extends BaseQueryElement {
|
||||
|
||||
@JsonIgnore
|
||||
private final QueryConverter<?> converter;
|
||||
|
||||
public QueryElement(String description, boolean required, String value, QueryConverter<?> converter) {
|
||||
super(description, required, value);
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public QueryElement(String description, boolean required, Object value, QueryConverter<?> converter) {
|
||||
super(description, required, value != null ? value.toString() : null);
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(String value) {
|
||||
if (value == null && this.value != null) {
|
||||
if (isRequired() && this.value == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.value = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
converter.convertFromString(value);
|
||||
} catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getConvertedValue() {
|
||||
return (T) converter.convertFromString(value);
|
||||
}
|
||||
}
|
|
@ -38,8 +38,12 @@ public abstract class DataSource<DS extends DataStore> {
|
|||
return c;
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return true;
|
||||
protected boolean supportsRead() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean supportsWrite() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,9 +69,13 @@ public abstract class DataSource<DS extends DataStore> {
|
|||
*/
|
||||
public abstract DataSourceInfo determineInfo() throws Exception;
|
||||
|
||||
public abstract DataSourceReadConnection openReadConnection() throws Exception;
|
||||
public DataSourceReadConnection openReadConnection() throws Exception {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public abstract DataSourceConnection openWriteConnection() throws Exception;
|
||||
public DataSourceConnection openWriteConnection() throws Exception {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public DataSourceConnection openAppendingWriteConnection() throws Exception {
|
||||
throw new UnsupportedOperationException("Appending write is not supported");
|
||||
|
|
94
core/src/main/java/io/xpipe/core/source/JdbcQuerySource.java
Normal file
94
core/src/main/java/io/xpipe/core/source/JdbcQuerySource.java
Normal file
|
@ -0,0 +1,94 @@
|
|||
package io.xpipe.core.source;
|
||||
|
||||
import io.xpipe.core.data.node.*;
|
||||
import io.xpipe.core.data.type.TupleType;
|
||||
import io.xpipe.core.data.type.ValueType;
|
||||
import io.xpipe.core.store.JdbcStore;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public abstract class JdbcQuerySource extends TableDataSource<JdbcStore> {
|
||||
|
||||
JdbcStore store;
|
||||
|
||||
protected abstract String createQuery();
|
||||
|
||||
public Connection createConnection() throws SQLException {
|
||||
return store.createConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRead() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TableReadConnection newReadConnection() {
|
||||
return new TableReadConnection() {
|
||||
|
||||
private Connection connection;
|
||||
private Statement statement;
|
||||
private TupleType dataType;
|
||||
private ResultSet resultSet;
|
||||
|
||||
@Override
|
||||
public void init() throws Exception {
|
||||
connection = createConnection();
|
||||
statement = connection.createStatement();
|
||||
|
||||
resultSet = statement.executeQuery(createQuery());
|
||||
var meta = resultSet.getMetaData();
|
||||
var names = new ArrayList<String>();
|
||||
for (int i = 0; i < meta.getColumnCount(); i++) {
|
||||
names.add(meta.getColumnName(i + 1));
|
||||
}
|
||||
dataType = TupleType.of(names, Collections.nCopies(names.size(), ValueType.of()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
statement.close();
|
||||
connection.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TupleType getDataType() {
|
||||
return dataType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() throws Exception {
|
||||
return resultSet.getFetchSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void withRows(DataStructureNodeAcceptor<TupleNode> lineAcceptor) throws Exception {
|
||||
while (resultSet.next()) {
|
||||
var vals = new ArrayList<DataStructureNode>();
|
||||
for (int i = 0; i < dataType.getSize(); i++) {
|
||||
vals.add(ValueNode.of(resultSet.getString(i)));
|
||||
}
|
||||
|
||||
var node = TupleNode.of(dataType.getNames(), vals);
|
||||
if (!lineAcceptor.accept(node)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayNode readRows(int maxLines) throws Exception {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ public interface TableReadConnection extends DataSourceReadConnection {
|
|||
public static TableReadConnection empty() {
|
||||
return new TableReadConnection() {
|
||||
@Override
|
||||
public TupleType getDataType() throws Exception {
|
||||
public TupleType getDataType() {
|
||||
return TupleType.empty();
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ public interface TableReadConnection extends DataSourceReadConnection {
|
|||
/**
|
||||
* Returns the data type of the table data.
|
||||
*/
|
||||
TupleType getDataType() throws Exception;
|
||||
TupleType getDataType();
|
||||
|
||||
/**
|
||||
* Returns the amount of rows to be read or -1 if the amount is unknown.
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import lombok.Value;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
@Value
|
||||
@JsonTypeName("commandInput")
|
||||
public class CommandInputStore implements StreamDataStore {
|
||||
|
||||
String cmd;
|
||||
|
||||
@Override
|
||||
public InputStream openInput() throws Exception {
|
||||
var proc = Runtime.getRuntime().exec(cmd);
|
||||
return proc.getInputStream();
|
||||
}
|
||||
}
|
52
core/src/main/java/io/xpipe/core/store/HttpRequestStore.java
Normal file
52
core/src/main/java/io/xpipe/core/store/HttpRequestStore.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import lombok.Value;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Value
|
||||
@JsonTypeName("httpRequest")
|
||||
public class HttpRequestStore implements StreamDataStore {
|
||||
|
||||
public static boolean isHttpRequest(String s) {
|
||||
return s.startsWith("http:") || s.startsWith("https:");
|
||||
}
|
||||
|
||||
public static Optional<HttpRequestStore> fromString(String s) {
|
||||
try {
|
||||
var uri = new URI(s);
|
||||
return Optional.of(new HttpRequestStore(uri, Map.of()));
|
||||
} catch (URISyntaxException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
URI uri;
|
||||
Map<String, String> headers;
|
||||
|
||||
@Override
|
||||
public InputStream openInput() throws Exception {
|
||||
var b = HttpRequest.newBuilder().uri(uri);
|
||||
headers.forEach(b::setHeader);
|
||||
var req = b.GET().build();
|
||||
|
||||
var client = HttpClient.newHttpClient();
|
||||
var res = client.send(req, HttpResponse.BodyHandlers.ofByteArray());
|
||||
|
||||
return new ByteArrayInputStream(res.body());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return false;
|
||||
}
|
||||
}
|
34
core/src/main/java/io/xpipe/core/store/JdbcStore.java
Normal file
34
core/src/main/java/io/xpipe/core/store/JdbcStore.java
Normal file
|
@ -0,0 +1,34 @@
|
|||
package io.xpipe.core.store;
|
||||
|
||||
import lombok.*;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
public abstract class JdbcStore implements DataStore {
|
||||
|
||||
String hostname;
|
||||
int port;
|
||||
|
||||
public void checkConnect() throws Exception {
|
||||
try (Connection con = createConnection()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public Connection createConnection() throws SQLException {
|
||||
return DriverManager.getConnection(toUrl(), toProperties());
|
||||
}
|
||||
|
||||
public abstract String toUrl();
|
||||
|
||||
public abstract Properties toProperties();
|
||||
}
|
|
@ -49,7 +49,9 @@ public interface StreamDataStore extends DataStore {
|
|||
throw new UnsupportedOperationException("Can't open store output");
|
||||
}
|
||||
|
||||
boolean exists();
|
||||
default boolean exists() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean persistent() {
|
||||
return false;
|
||||
|
|
|
@ -11,6 +11,9 @@ import com.fasterxml.jackson.databind.SerializerProvider;
|
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.jsontype.NamedType;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import io.xpipe.core.config.BaseQueryElement;
|
||||
import io.xpipe.core.config.ChoiceElement;
|
||||
import io.xpipe.core.config.HeaderElement;
|
||||
import io.xpipe.core.data.type.ArrayType;
|
||||
import io.xpipe.core.data.type.TupleType;
|
||||
import io.xpipe.core.data.type.ValueType;
|
||||
|
@ -18,6 +21,7 @@ import io.xpipe.core.data.type.WildcardType;
|
|||
import io.xpipe.core.source.DataSourceInfo;
|
||||
import io.xpipe.core.source.DataSourceReference;
|
||||
import io.xpipe.core.store.CollectionEntryDataStore;
|
||||
import io.xpipe.core.store.HttpRequestStore;
|
||||
import io.xpipe.core.store.LocalDirectoryDataStore;
|
||||
import io.xpipe.core.store.LocalFileDataStore;
|
||||
|
||||
|
@ -33,6 +37,7 @@ public class CoreJacksonModule extends SimpleModule {
|
|||
new NamedType(LocalFileDataStore.class),
|
||||
new NamedType(LocalDirectoryDataStore.class),
|
||||
new NamedType(CollectionEntryDataStore.class),
|
||||
new NamedType(HttpRequestStore.class),
|
||||
new NamedType(ValueType.class),
|
||||
new NamedType(TupleType.class),
|
||||
new NamedType(ArrayType.class),
|
||||
|
@ -41,7 +46,10 @@ public class CoreJacksonModule extends SimpleModule {
|
|||
new NamedType(DataSourceInfo.Structure.class),
|
||||
new NamedType(DataSourceInfo.Text.class),
|
||||
new NamedType(DataSourceInfo.Collection.class),
|
||||
new NamedType(DataSourceInfo.Raw.class)
|
||||
new NamedType(DataSourceInfo.Raw.class),
|
||||
new NamedType(BaseQueryElement.class),
|
||||
new NamedType(ChoiceElement.class),
|
||||
new NamedType(HeaderElement.class)
|
||||
);
|
||||
|
||||
addSerializer(Charset.class, new CharsetSerializer());
|
||||
|
|
|
@ -22,7 +22,9 @@ module io.xpipe.core {
|
|||
|
||||
requires com.fasterxml.jackson.core;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
requires java.net.http;
|
||||
requires static lombok;
|
||||
requires java.sql;
|
||||
|
||||
uses com.fasterxml.jackson.databind.Module;
|
||||
provides com.fasterxml.jackson.databind.Module with CoreJacksonModule;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.extension;
|
||||
|
||||
import io.xpipe.charsetter.NewLine;
|
||||
import io.xpipe.core.config.ConfigConverter;
|
||||
import io.xpipe.core.config.QueryConverter;
|
||||
import io.xpipe.core.config.ConfigParameter;
|
||||
import io.xpipe.core.source.DataSource;
|
||||
import io.xpipe.core.source.DataSourceType;
|
||||
|
@ -9,7 +9,6 @@ import io.xpipe.core.store.DataStore;
|
|||
import javafx.beans.property.Property;
|
||||
import javafx.scene.layout.Region;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.Value;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -93,13 +92,6 @@ public interface DataSourceProvider<T extends DataSource<?>> {
|
|||
|
||||
interface ConfigProvider<T extends DataSource<?>> {
|
||||
|
||||
@Value
|
||||
static class Parameter {
|
||||
ConfigParameter parameter;
|
||||
Object currentValue;
|
||||
boolean required;
|
||||
}
|
||||
|
||||
static <T extends DataSource<?>> ConfigProvider<T> empty(List<String> names, Function<DataStore, T> func) {
|
||||
return new ConfigProvider<>() {
|
||||
@Override
|
||||
|
@ -124,9 +116,9 @@ public interface DataSourceProvider<T extends DataSource<?>> {
|
|||
}
|
||||
|
||||
ConfigParameter CHARSET = new ConfigParameter(
|
||||
"charset", ConfigConverter.CHARSET);
|
||||
"charset", QueryConverter.CHARSET);
|
||||
|
||||
public static final ConfigConverter<NewLine> NEW_LINE_CONVERTER = new ConfigConverter<NewLine>() {
|
||||
public static final QueryConverter<NewLine> NEW_LINE_CONVERTER = new QueryConverter<NewLine>() {
|
||||
@Override
|
||||
protected NewLine fromString(String s) {
|
||||
return NewLine.id(s);
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package io.xpipe.extension;
|
||||
|
||||
import io.xpipe.core.config.Dialog;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
public interface DataStoreProvider {
|
||||
|
||||
default void init() throws Exception {
|
||||
}
|
||||
|
||||
default String i18n(String key) {
|
||||
return I18n.get(getId() + "." + key);
|
||||
}
|
||||
|
||||
default String i18nKey(String key) {
|
||||
return getId() + "." + key;
|
||||
}
|
||||
|
||||
default String getDisplayName() {
|
||||
return i18n("displayName");
|
||||
}
|
||||
|
||||
default String getDisplayDescription() {
|
||||
return i18n("displayDescription");
|
||||
}
|
||||
|
||||
default String getDisplayIconFileName() {
|
||||
return getId() + ":icon.png";
|
||||
}
|
||||
|
||||
default Dialog dialogForURL(URL url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Dialog defaultDialog();
|
||||
|
||||
List<String> getPossibleNames();
|
||||
|
||||
default String getId() {
|
||||
var n = getClass().getPackageName();
|
||||
var i = n.lastIndexOf('.');
|
||||
return i != -1 ? n.substring(i + 1) : n;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package io.xpipe.extension;
|
||||
|
||||
import io.xpipe.core.config.Dialog;
|
||||
import io.xpipe.extension.event.ErrorEvent;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DataStoreProviders {
|
||||
|
||||
private static Set<DataStoreProvider> ALL;
|
||||
|
||||
public static void init(ModuleLayer layer) {
|
||||
if (ALL == null) {
|
||||
ALL = ServiceLoader.load(layer, DataStoreProvider.class).stream()
|
||||
.map(p -> (DataStoreProvider) p.get()).collect(Collectors.toSet());
|
||||
ALL.forEach(p -> {
|
||||
try {
|
||||
p.init();
|
||||
} catch (Exception e) {
|
||||
ErrorEvent.fromThrowable(e).handle();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<DataStoreProvider> byName(String name) {
|
||||
if (ALL == null) {
|
||||
throw new IllegalStateException("Not initialized");
|
||||
}
|
||||
|
||||
return ALL.stream().filter(d -> d.getPossibleNames().stream()
|
||||
.anyMatch(s -> s.equalsIgnoreCase(name))).findAny();
|
||||
}
|
||||
|
||||
public static Optional<Dialog> byURL(URL url) {
|
||||
if (ALL == null) {
|
||||
throw new IllegalStateException("Not initialized");
|
||||
}
|
||||
|
||||
return ALL.stream().map(d -> d.dialogForURL(url)).filter(Objects::nonNull).findAny();
|
||||
}
|
||||
|
||||
public static Set<DataStoreProvider> getAll() {
|
||||
return ALL;
|
||||
}
|
||||
}
|
|
@ -35,4 +35,5 @@ module io.xpipe.extension {
|
|||
uses io.xpipe.extension.I18n;
|
||||
uses io.xpipe.extension.event.EventHandler;
|
||||
uses io.xpipe.extension.prefs.PrefsProvider;
|
||||
uses io.xpipe.extension.DataStoreProvider;
|
||||
}
|
Loading…
Reference in a new issue