mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-21 23:20:23 +00:00
Cleanup and document
This commit is contained in:
parent
cd93f934ff
commit
774689e42a
34 changed files with 247 additions and 201 deletions
|
@ -6,8 +6,6 @@ plugins {
|
|||
}
|
||||
|
||||
apply from: "$rootDir/deps/java.gradle"
|
||||
apply from: "$rootDir/deps/commons.gradle"
|
||||
apply from: "$rootDir/deps/jackson.gradle"
|
||||
apply from: "$rootDir/deps/junit.gradle"
|
||||
apply from: 'publish.gradle'
|
||||
apply from: "$rootDir/deps/publish-base.gradle"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module io.xpipe.api {
|
||||
requires transitive io.xpipe.core;
|
||||
requires transitive io.xpipe.beacon;
|
||||
requires io.xpipe.beacon;
|
||||
|
||||
exports io.xpipe.api;
|
||||
}
|
|
@ -6,8 +6,6 @@ plugins {
|
|||
}
|
||||
|
||||
apply from: "$rootDir/deps/java.gradle"
|
||||
apply from: "$rootDir/deps/commons.gradle"
|
||||
apply from: "$rootDir/deps/slf4j.gradle"
|
||||
apply from: "$rootDir/deps/jackson.gradle"
|
||||
apply from: "$rootDir/deps/lombok.gradle"
|
||||
apply from: 'publish.gradle'
|
||||
|
|
|
@ -12,8 +12,6 @@ import io.xpipe.beacon.message.RequestMessage;
|
|||
import io.xpipe.beacon.message.ResponseMessage;
|
||||
import io.xpipe.beacon.message.ServerErrorMessage;
|
||||
import io.xpipe.core.util.JacksonHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -27,8 +25,6 @@ import static io.xpipe.beacon.BeaconConfig.BODY_SEPARATOR;
|
|||
|
||||
public class BeaconClient {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger("beacon");
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FailableBiConsumer<T, U, E extends Throwable> {
|
||||
|
||||
|
@ -127,7 +123,9 @@ public class BeaconClient {
|
|||
var msg = JsonNodeFactory.instance.objectNode();
|
||||
msg.set("xPipeMessage", json);
|
||||
|
||||
log.atTrace().addKeyValue("class", req.getClass().getSimpleName()).log("Sending request to server");
|
||||
if (BeaconConfig.debugEnabled()) {
|
||||
System.out.println("Sending request to server of type " + req.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
try {
|
||||
var mapper = JacksonHelper.newMapper().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||
|
|
|
@ -4,13 +4,11 @@ module io.xpipe.beacon {
|
|||
exports io.xpipe.beacon;
|
||||
exports io.xpipe.beacon.exchange;
|
||||
exports io.xpipe.beacon.message;
|
||||
requires org.slf4j;
|
||||
|
||||
requires com.fasterxml.jackson.core;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
requires com.fasterxml.jackson.module.paramnames;
|
||||
requires io.xpipe.core;
|
||||
requires io.xpipe.extension;
|
||||
requires transitive io.xpipe.core;
|
||||
|
||||
opens io.xpipe.beacon;
|
||||
opens io.xpipe.beacon.exchange;
|
||||
|
|
|
@ -6,7 +6,6 @@ plugins {
|
|||
}
|
||||
|
||||
apply from: "$rootDir/deps/java.gradle"
|
||||
apply from: "$rootDir/deps/commons.gradle"
|
||||
apply from: "$rootDir/deps/jackson.gradle"
|
||||
apply from: "$rootDir/deps/lombok.gradle"
|
||||
apply from: 'publish.gradle'
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
package io.xpipe.core.source;
|
||||
|
||||
/**
|
||||
* Represents any type of connection to a data source.
|
||||
*/
|
||||
public interface DataSourceConnection extends AutoCloseable {
|
||||
|
||||
/**
|
||||
* Initializes this connection. Required to be called
|
||||
* exactly once prior to attempting to use this connection.
|
||||
*/
|
||||
void init() throws Exception;
|
||||
}
|
||||
|
|
|
@ -4,13 +4,31 @@ import io.xpipe.core.store.DataStore;
|
|||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Represents a formal description on what exactly makes up the
|
||||
* actual data source and how to access/locate it for a given data store.
|
||||
*
|
||||
* This instance is only valid in combination with its associated data store instance.
|
||||
*/
|
||||
public interface DataSourceDescriptor<DS extends DataStore> {
|
||||
|
||||
/**
|
||||
* Determines on optional default name for this data store that is
|
||||
* used when determining a suitable default name for a data source.
|
||||
*/
|
||||
default Optional<String> determineDefaultName(DS store) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the data source info.
|
||||
* This is usually called only once on data source
|
||||
* creation as this process might be expensive.
|
||||
*/
|
||||
DataSourceInfo determineInfo(DS store) throws Exception;
|
||||
|
||||
/**
|
||||
* Returns the general data source type.
|
||||
*/
|
||||
DataSourceType getType();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,15 @@ import io.xpipe.core.data.type.TupleType;
|
|||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
|
||||
/**
|
||||
* A data source info instances contains all required
|
||||
* essential information of a specific data source type.
|
||||
*
|
||||
* This information is usually determined only once on data
|
||||
* source creation, as this process might be expensive.
|
||||
*
|
||||
* @see DataSourceType
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
public abstract class DataSourceInfo {
|
||||
|
||||
|
@ -31,6 +40,9 @@ public abstract class DataSourceInfo {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts this instance to a table info.
|
||||
*/
|
||||
public Table asTable() {
|
||||
if (!getType().equals(DataSourceType.TABLE)) {
|
||||
throw new IllegalStateException("Not a table");
|
||||
|
|
|
@ -2,6 +2,10 @@ package io.xpipe.core.source;
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Represents the fundamental type of a data source.
|
||||
* This distinction is necessary as the general workflow differs for each type.
|
||||
*/
|
||||
public enum DataSourceType {
|
||||
|
||||
@JsonProperty("table")
|
||||
|
@ -10,6 +14,9 @@ public enum DataSourceType {
|
|||
@JsonProperty("structure")
|
||||
STRUCTURE,
|
||||
|
||||
@JsonProperty("text")
|
||||
TEXT,
|
||||
|
||||
@JsonProperty("raw")
|
||||
RAW
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package io.xpipe.core.source;
|
||||
|
||||
public interface StructureDataReadConnection extends DataSourceConnection {
|
||||
|
||||
}
|
|
@ -1,8 +1,24 @@
|
|||
package io.xpipe.core.source;
|
||||
|
||||
public abstract class StructureDataSourceDescriptor implements DataSourceDescriptor {
|
||||
import io.xpipe.core.store.DataStore;
|
||||
|
||||
public abstract DataSourceConnection openConnection() throws Exception;
|
||||
public abstract class StructureDataSourceDescriptor<DS extends DataStore> implements DataSourceDescriptor<DS> {
|
||||
|
||||
public final StructureReadConnection openReadConnection(DS store) throws Exception {
|
||||
var con = newReadConnection(store);
|
||||
con.init();
|
||||
return con;
|
||||
}
|
||||
|
||||
public final StructureWriteConnection openWriteConnection(DS store) throws Exception {
|
||||
var con = newWriteConnection(store);
|
||||
con.init();
|
||||
return con;
|
||||
}
|
||||
|
||||
protected abstract StructureWriteConnection newWriteConnection(DS store);
|
||||
|
||||
protected abstract StructureReadConnection newReadConnection(DS store);
|
||||
|
||||
@Override
|
||||
public DataSourceType getType() {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package io.xpipe.core.source;
|
||||
|
||||
import io.xpipe.core.data.node.DataStructureNode;
|
||||
|
||||
public interface StructureReadConnection extends DataSourceConnection {
|
||||
|
||||
/**
|
||||
* Reads the complete contents.
|
||||
*/
|
||||
DataStructureNode read() throws Exception;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package io.xpipe.core.source;
|
||||
|
||||
import io.xpipe.core.data.node.DataStructureNode;
|
||||
|
||||
public interface StructureWriteConnection extends DataSourceConnection {
|
||||
|
||||
/**
|
||||
* Writes the contents to the data source.
|
||||
*/
|
||||
void write(DataStructureNode node) throws Exception;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package io.xpipe.core.source;
|
||||
|
||||
|
||||
import io.xpipe.core.data.node.DataStructureNodeAcceptor;
|
||||
import io.xpipe.core.data.node.ArrayNode;
|
||||
import io.xpipe.core.data.node.TupleNode;
|
||||
import io.xpipe.core.data.type.TupleType;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface TableDataReadConnection extends DataSourceConnection {
|
||||
|
||||
TupleType getDataType() throws Exception;
|
||||
|
||||
int getRowCount() throws Exception;
|
||||
|
||||
void withLines(DataStructureNodeAcceptor<TupleNode> lineAcceptor) throws Exception;
|
||||
|
||||
ArrayNode readLines(int maxLines) throws Exception;
|
||||
|
||||
void forwardLines(OutputStream out, int maxLines) throws Exception;
|
||||
}
|
|
@ -4,21 +4,21 @@ import io.xpipe.core.store.DataStore;
|
|||
|
||||
public abstract class TableDataSourceDescriptor<DS extends DataStore> implements DataSourceDescriptor<DS> {
|
||||
|
||||
public final TableDataReadConnection openReadConnection(DS store) throws Exception {
|
||||
public final TableReadConnection openReadConnection(DS store) throws Exception {
|
||||
var con = newReadConnection(store);
|
||||
con.init();
|
||||
return con;
|
||||
}
|
||||
|
||||
public final TableDataWriteConnection openWriteConnection(DS store) throws Exception {
|
||||
public final TableWriteConnection openWriteConnection(DS store) throws Exception {
|
||||
var con = newWriteConnection(store);
|
||||
con.init();
|
||||
return con;
|
||||
}
|
||||
|
||||
protected abstract TableDataWriteConnection newWriteConnection(DS store);
|
||||
protected abstract TableWriteConnection newWriteConnection(DS store);
|
||||
|
||||
protected abstract TableDataReadConnection newReadConnection(DS store);
|
||||
protected abstract TableReadConnection newReadConnection(DS store);
|
||||
|
||||
@Override
|
||||
public DataSourceType getType() {
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package io.xpipe.core.source;
|
||||
|
||||
|
||||
import io.xpipe.core.data.node.DataStructureNodeAcceptor;
|
||||
import io.xpipe.core.data.node.ArrayNode;
|
||||
import io.xpipe.core.data.node.TupleNode;
|
||||
import io.xpipe.core.data.type.TupleType;
|
||||
import io.xpipe.core.data.typed.TypedDataStreamWriter;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A connection for sequentially reading the data of a table data source.
|
||||
*/
|
||||
public interface TableReadConnection extends DataSourceConnection {
|
||||
|
||||
/**
|
||||
* Returns the data type of the table data.
|
||||
*/
|
||||
TupleType getDataType() throws Exception;
|
||||
|
||||
/**
|
||||
* Returns the amount of rows to be read or -1 if the amount is unknown.
|
||||
*/
|
||||
int getRowCount() throws Exception;
|
||||
|
||||
/**
|
||||
* Consumes the table rows until the acceptor returns false.
|
||||
*/
|
||||
void withRows(DataStructureNodeAcceptor<TupleNode> lineAcceptor) throws Exception;
|
||||
|
||||
/**
|
||||
* Reads multiple rows in bulk.
|
||||
*/
|
||||
ArrayNode readRows(int maxLines) throws Exception;
|
||||
|
||||
/**
|
||||
* Writes the rows to an OutputStream in the X-Pipe binary format.
|
||||
*/
|
||||
default void forwardRows(OutputStream out, int maxLines) throws Exception {
|
||||
var dataType = getDataType();
|
||||
AtomicInteger rowCounter = new AtomicInteger();
|
||||
withRows(l -> {
|
||||
TypedDataStreamWriter.writeStructure(out, l, dataType);
|
||||
rowCounter.getAndIncrement();
|
||||
return rowCounter.get() != maxLines;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -4,7 +4,10 @@ import io.xpipe.core.data.node.DataStructureNodeAcceptor;
|
|||
import io.xpipe.core.data.node.ArrayNode;
|
||||
import io.xpipe.core.data.node.TupleNode;
|
||||
|
||||
public interface TableDataWriteConnection extends DataSourceConnection {
|
||||
/**
|
||||
* A connection for sequentially writing data to a table data source.
|
||||
*/
|
||||
public interface TableWriteConnection extends DataSourceConnection {
|
||||
|
||||
DataStructureNodeAcceptor<TupleNode> writeLinesAcceptor();
|
||||
|
|
@ -1,23 +1,41 @@
|
|||
package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import io.xpipe.core.source.DataSourceDescriptor;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A data store represents some form of a location where data is stored, e.g. a file or a database.
|
||||
* It does not contain any information on what data is stored,
|
||||
* how the data is stored inside, or what part of the data store makes up the actual data source.
|
||||
*
|
||||
* @see DataSourceDescriptor
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
public interface DataStore {
|
||||
|
||||
/**
|
||||
* Casts this instance to the required type without checking whether a cast is possible.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <DS extends DataStore> DS asNeeded() {
|
||||
return (DS) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines on optional default name for this data store that is
|
||||
* used when determining a suitable default name for a data source.
|
||||
*/
|
||||
default Optional<String> determineDefaultName() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
default Optional<Instant> getLastModified() {
|
||||
/**
|
||||
* Determines the last modified of this data store if this data store supports it.
|
||||
*/
|
||||
default Optional<Instant> determineLastModified() {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
public abstract class FileDataStore implements StreamDataStore {
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
@JsonIgnore
|
||||
public abstract boolean isLocal();
|
||||
|
||||
@JsonIgnore
|
||||
public abstract LocalFileDataStore getLocal();
|
||||
|
||||
@JsonIgnore
|
||||
public abstract RemoteFileDataStore getRemote();
|
||||
}
|
|
@ -4,6 +4,13 @@ import java.io.BufferedInputStream;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A data store that is only represented by an InputStream.
|
||||
* One common use case of this class are piped inputs.
|
||||
*
|
||||
* As the data in a pipe can only be read once, this implementation
|
||||
* internally uses a BufferedInputStream to support mark/rest.
|
||||
*/
|
||||
public class InputStreamDataStore implements StreamDataStore {
|
||||
|
||||
private final InputStream in;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.xpipe.core.store;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
|
@ -14,7 +13,7 @@ import java.time.Instant;
|
|||
import java.util.Optional;
|
||||
|
||||
@JsonTypeName("local")
|
||||
public class LocalFileDataStore extends FileDataStore {
|
||||
public class LocalFileDataStore implements StreamDataStore {
|
||||
|
||||
private final Path file;
|
||||
|
||||
|
@ -29,7 +28,7 @@ public class LocalFileDataStore extends FileDataStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Optional<Instant> getLastModified() {
|
||||
public Optional<Instant> determineLastModified() {
|
||||
try {
|
||||
var l = Files.getLastModifiedTime(file);
|
||||
return Optional.of(l.toInstant());
|
||||
|
@ -38,27 +37,6 @@ public class LocalFileDataStore extends FileDataStore {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return file.getFileName().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public boolean isLocal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFileDataStore getLocal() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteFileDataStore getRemote() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Path getFile() {
|
||||
return file;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import java.io.OutputStream;
|
|||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
public class RemoteFileDataStore extends FileDataStore {
|
||||
public class RemoteFileDataStore implements StreamDataStore {
|
||||
|
||||
@Override
|
||||
public Optional<String> determineDefaultName() {
|
||||
|
@ -13,30 +13,10 @@ public class RemoteFileDataStore extends FileDataStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Optional<Instant> getLastModified() {
|
||||
public Optional<Instant> determineLastModified() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalFileDataStore getLocal() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteFileDataStore getRemote() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream openInput() throws Exception {
|
||||
return null;
|
||||
|
|
|
@ -3,9 +3,19 @@ package io.xpipe.core.store;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A data store that can be accessed using InputStreams and/or OutputStreams.
|
||||
* These streams must support mark/reset.
|
||||
*/
|
||||
public interface StreamDataStore extends DataStore {
|
||||
|
||||
/**
|
||||
* Opens an input stream. This input stream does not necessarily have to be a new instance.
|
||||
*/
|
||||
InputStream openInput() throws Exception;
|
||||
|
||||
/**
|
||||
* Opens an output stream. This output stream does not necessarily have to be a new instance.
|
||||
*/
|
||||
OutputStream openOutput() throws Exception;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@ public class JacksonHelper {
|
|||
return modules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new ObjectMapper that is able to map all required X-Pipe classes and also possible extensions.
|
||||
*/
|
||||
public static ObjectMapper newMapper() {
|
||||
if (!init) {
|
||||
throw new IllegalStateException("Not initialized");
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import io.xpipe.core.util.CoreJacksonModule;
|
||||
|
||||
module io.xpipe.core {
|
||||
requires transitive com.fasterxml.jackson.core;
|
||||
requires transitive com.fasterxml.jackson.databind;
|
||||
requires transitive com.fasterxml.jackson.module.paramnames;
|
||||
requires com.fasterxml.jackson.core;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
requires com.fasterxml.jackson.module.paramnames;
|
||||
|
||||
requires static lombok;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ apply from: "$rootDir/deps/publish-base.gradle"
|
|||
|
||||
version = file('../version').text
|
||||
group = 'io.xpipe'
|
||||
archivesBaseName = 'core'
|
||||
archivesBaseName = 'extension'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package io.xpipe.extension;
|
||||
|
||||
import io.xpipe.core.source.DataSourceDescriptor;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface DataSourceGuiProvider {
|
||||
|
||||
default boolean isHidden() {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean supportsFile(Path file);
|
||||
|
||||
Region createConfigOptions(DataStore input, Property<? extends DataSourceDescriptor<?>> source);
|
||||
|
||||
DataSourceDescriptor<?> createDefaultDataSource(DataStore input) throws Exception;
|
||||
|
||||
String getDisplayName();
|
||||
|
||||
String getDisplayImage();
|
||||
|
||||
String getFileName();
|
||||
|
||||
Map<Supplier<String>, String> getFileExtensions();
|
||||
|
||||
String getDataSourceShortDescription(DataSourceDescriptor<?> source);
|
||||
|
||||
String getDataSourceLongDescription(DataSourceDescriptor<?> source);
|
||||
|
||||
Class<? extends DataSourceDescriptor<?>> getType();
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package io.xpipe.extension;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DataSourceGuiProviders {
|
||||
|
||||
private static Set<DataSourceGuiProvider> ALL;
|
||||
|
||||
public static void loadAll(ModuleLayer layer) {
|
||||
if (ALL == null) {
|
||||
ALL = new HashSet<>();
|
||||
ALL.addAll(ServiceLoader.load(layer, DataSourceGuiProvider.class).stream()
|
||||
.map(ServiceLoader.Provider::get).collect(Collectors.toSet()));
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<DataSourceGuiProvider> byClass(Class<?> clazz) {
|
||||
if (ALL == null) {
|
||||
throw new IllegalStateException("Not initialized");
|
||||
}
|
||||
return ALL.stream().filter(d -> d.getType().equals(clazz)).findAny();
|
||||
}
|
||||
|
||||
public static Set<DataSourceGuiProvider> getAll() {
|
||||
if (ALL == null) {
|
||||
throw new IllegalStateException("Not initialized");
|
||||
}
|
||||
return ALL;
|
||||
}
|
||||
}
|
|
@ -2,16 +2,52 @@ package io.xpipe.extension;
|
|||
|
||||
import io.xpipe.core.source.DataSourceDescriptor;
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface DataSourceProvider {
|
||||
|
||||
interface FileProvider {
|
||||
|
||||
boolean supportsFile(Path file);
|
||||
|
||||
String getFileName();
|
||||
|
||||
Map<Supplier<String>, String> getFileExtensions();
|
||||
}
|
||||
|
||||
interface GuiProvider {
|
||||
|
||||
Region createConfigOptions(DataStore input, Property<? extends DataSourceDescriptor<?>> source);
|
||||
|
||||
String getDisplayName();
|
||||
|
||||
String getDisplayImage();
|
||||
|
||||
Supplier<String> getDescription(DataSourceDescriptor<?> source);
|
||||
}
|
||||
|
||||
interface CliProvider {
|
||||
|
||||
}
|
||||
|
||||
FileProvider getFileProvider();
|
||||
|
||||
GuiProvider getGuiProvider();
|
||||
|
||||
CliProvider getCliProvider();
|
||||
|
||||
String getId();
|
||||
|
||||
boolean supportsFile(Path file);
|
||||
/**
|
||||
* Attempt to create a useful data source descriptor from a data store.
|
||||
* The result does not need to be always right, it should only reflect the best effort.
|
||||
*/
|
||||
DataSourceDescriptor<?> createDefaultDescriptor(DataStore input) throws Exception;
|
||||
|
||||
DataSourceDescriptor<?> createDefaultDataSource(DataStore input) throws Exception;
|
||||
|
||||
Class<? extends DataSourceDescriptor<?>> getType();
|
||||
Class<? extends DataSourceDescriptor<?>> getDescriptorClass();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public class DataSourceProviders {
|
|||
public static TableDataSourceDescriptor<LocalFileDataStore> createLocalTableDescriptor(TupleType type) {
|
||||
try {
|
||||
return (TableDataSourceDescriptor<LocalFileDataStore>)
|
||||
DataSourceProviders.byId("xpbt").orElseThrow().getType()
|
||||
DataSourceProviders.byId("xpbt").orElseThrow().getDescriptorClass()
|
||||
.getDeclaredConstructors()[0].newInstance(type);
|
||||
} catch (Exception ex) {
|
||||
ErrorEvent.fromThrowable(ex).terminal(true).build().handle();
|
||||
|
@ -36,12 +36,12 @@ public class DataSourceProviders {
|
|||
}
|
||||
}
|
||||
|
||||
public static Optional<DataSourceProvider> byDataSourceClass(Class<?> clazz) {
|
||||
public static Optional<DataSourceProvider> byDescriptorClass(Class<?> clazz) {
|
||||
if (ALL == null) {
|
||||
throw new IllegalStateException("Not initialized");
|
||||
}
|
||||
|
||||
return ALL.stream().filter(d -> d.getType().equals(clazz)).findAny();
|
||||
return ALL.stream().filter(d -> d.getDescriptorClass().equals(clazz)).findAny();
|
||||
}
|
||||
|
||||
public static Optional<DataSourceProvider> byId(String name) {
|
||||
|
@ -57,7 +57,8 @@ public class DataSourceProviders {
|
|||
throw new IllegalStateException("Not initialized");
|
||||
}
|
||||
|
||||
return ALL.stream().filter(d -> d.supportsFile(file)).findAny();
|
||||
return ALL.stream().filter(d -> d.getFileProvider() != null)
|
||||
.filter(d -> d.getFileProvider().supportsFile(file)).findAny();
|
||||
}
|
||||
|
||||
public static Optional<DataSourceProvider> byURL(URL url) {
|
||||
|
|
|
@ -2,20 +2,21 @@ package io.xpipe.extension;
|
|||
|
||||
import io.xpipe.core.source.DataSourceId;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface SupportedApplicationProvider {
|
||||
|
||||
Region createTableRetrieveInstructions(ObservableValue<DataSourceId> id);
|
||||
|
||||
Region createStructureRetrieveInstructions(ObservableValue<DataSourceId> id);
|
||||
|
||||
Region createRawRetrieveInstructions(ObservableValue<DataSourceId> id);
|
||||
Region createTextRetrieveInstructions(ObservableValue<DataSourceId> id);
|
||||
|
||||
Image getLogo();
|
||||
Region createRawRetrieveInstructions(ObservableValue<DataSourceId> id);
|
||||
|
||||
String getId();
|
||||
|
||||
String getName();
|
||||
Supplier<String> getName();
|
||||
}
|
||||
|
|
|
@ -46,6 +46,9 @@ public class ToggleGroupComp<T> extends Comp<CompStructure<HBox>> {
|
|||
}
|
||||
}
|
||||
box.getChildren().get(0).getStyleClass().add("first");
|
||||
for (int i = 1; i < box.getChildren().size() - 1; i++) {
|
||||
box.getChildren().get(i).getStyleClass().add("center");
|
||||
}
|
||||
box.getChildren().get(box.getChildren().size() - 1).getStyleClass().add("last");
|
||||
|
||||
group.selectedToggleProperty().addListener((obsVal, oldVal, newVal) -> {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import io.xpipe.extension.DataSourceGuiProvider;
|
||||
import io.xpipe.extension.DataSourceProvider;
|
||||
import io.xpipe.extension.SupportedApplicationProvider;
|
||||
|
||||
|
@ -16,7 +15,6 @@ module io.xpipe.extension {
|
|||
exports io.xpipe.extension.event;
|
||||
|
||||
uses DataSourceProvider;
|
||||
uses DataSourceGuiProvider;
|
||||
uses SupportedApplicationProvider;
|
||||
uses io.xpipe.extension.I18n;
|
||||
uses io.xpipe.extension.event.EventHandler;
|
||||
|
|
Loading…
Reference in a new issue