diff --git a/api/build.gradle b/api/build.gradle index 16556726..a14164ac 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -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" diff --git a/api/src/main/java/module-info.java b/api/src/main/java/module-info.java index c16f6d57..a8fe12e9 100644 --- a/api/src/main/java/module-info.java +++ b/api/src/main/java/module-info.java @@ -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; } \ No newline at end of file diff --git a/beacon/build.gradle b/beacon/build.gradle index 3ffbeb78..697d6031 100644 --- a/beacon/build.gradle +++ b/beacon/build.gradle @@ -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' diff --git a/beacon/src/main/java/io/xpipe/beacon/BeaconClient.java b/beacon/src/main/java/io/xpipe/beacon/BeaconClient.java index 840ac9e8..b7df5c68 100644 --- a/beacon/src/main/java/io/xpipe/beacon/BeaconClient.java +++ b/beacon/src/main/java/io/xpipe/beacon/BeaconClient.java @@ -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 { @@ -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); diff --git a/beacon/src/main/java/module-info.java b/beacon/src/main/java/module-info.java index b88ea676..d2887a0f 100644 --- a/beacon/src/main/java/module-info.java +++ b/beacon/src/main/java/module-info.java @@ -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; diff --git a/core/build.gradle b/core/build.gradle index 27efc2ec..a7ba8991 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -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' diff --git a/core/src/main/java/io/xpipe/core/source/DataSourceConnection.java b/core/src/main/java/io/xpipe/core/source/DataSourceConnection.java index 65eab2ea..6acf3f49 100644 --- a/core/src/main/java/io/xpipe/core/source/DataSourceConnection.java +++ b/core/src/main/java/io/xpipe/core/source/DataSourceConnection.java @@ -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; } diff --git a/core/src/main/java/io/xpipe/core/source/DataSourceDescriptor.java b/core/src/main/java/io/xpipe/core/source/DataSourceDescriptor.java index 566f88e0..a8fe70cf 100644 --- a/core/src/main/java/io/xpipe/core/source/DataSourceDescriptor.java +++ b/core/src/main/java/io/xpipe/core/source/DataSourceDescriptor.java @@ -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 { + /** + * Determines on optional default name for this data store that is + * used when determining a suitable default name for a data source. + */ default Optional 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(); } diff --git a/core/src/main/java/io/xpipe/core/source/DataSourceInfo.java b/core/src/main/java/io/xpipe/core/source/DataSourceInfo.java index 5798d159..6249900f 100644 --- a/core/src/main/java/io/xpipe/core/source/DataSourceInfo.java +++ b/core/src/main/java/io/xpipe/core/source/DataSourceInfo.java @@ -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"); diff --git a/core/src/main/java/io/xpipe/core/source/DataSourceType.java b/core/src/main/java/io/xpipe/core/source/DataSourceType.java index 68d2139b..be4d7862 100644 --- a/core/src/main/java/io/xpipe/core/source/DataSourceType.java +++ b/core/src/main/java/io/xpipe/core/source/DataSourceType.java @@ -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 } diff --git a/core/src/main/java/io/xpipe/core/source/StructureDataReadConnection.java b/core/src/main/java/io/xpipe/core/source/StructureDataReadConnection.java deleted file mode 100644 index 11292105..00000000 --- a/core/src/main/java/io/xpipe/core/source/StructureDataReadConnection.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.xpipe.core.source; - -public interface StructureDataReadConnection extends DataSourceConnection { - -} diff --git a/core/src/main/java/io/xpipe/core/source/StructureDataSourceDescriptor.java b/core/src/main/java/io/xpipe/core/source/StructureDataSourceDescriptor.java index ea4d3cb8..47a2e972 100644 --- a/core/src/main/java/io/xpipe/core/source/StructureDataSourceDescriptor.java +++ b/core/src/main/java/io/xpipe/core/source/StructureDataSourceDescriptor.java @@ -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 implements DataSourceDescriptor { + + 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() { diff --git a/core/src/main/java/io/xpipe/core/source/StructureReadConnection.java b/core/src/main/java/io/xpipe/core/source/StructureReadConnection.java new file mode 100644 index 00000000..07b6f95e --- /dev/null +++ b/core/src/main/java/io/xpipe/core/source/StructureReadConnection.java @@ -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; +} diff --git a/core/src/main/java/io/xpipe/core/source/StructureWriteConnection.java b/core/src/main/java/io/xpipe/core/source/StructureWriteConnection.java new file mode 100644 index 00000000..55735d31 --- /dev/null +++ b/core/src/main/java/io/xpipe/core/source/StructureWriteConnection.java @@ -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; +} diff --git a/core/src/main/java/io/xpipe/core/source/TableDataReadConnection.java b/core/src/main/java/io/xpipe/core/source/TableDataReadConnection.java deleted file mode 100644 index 46954dea..00000000 --- a/core/src/main/java/io/xpipe/core/source/TableDataReadConnection.java +++ /dev/null @@ -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 lineAcceptor) throws Exception; - - ArrayNode readLines(int maxLines) throws Exception; - - void forwardLines(OutputStream out, int maxLines) throws Exception; -} diff --git a/core/src/main/java/io/xpipe/core/source/TableDataSourceDescriptor.java b/core/src/main/java/io/xpipe/core/source/TableDataSourceDescriptor.java index c3d7b3ca..003903bb 100644 --- a/core/src/main/java/io/xpipe/core/source/TableDataSourceDescriptor.java +++ b/core/src/main/java/io/xpipe/core/source/TableDataSourceDescriptor.java @@ -4,21 +4,21 @@ import io.xpipe.core.store.DataStore; public abstract class TableDataSourceDescriptor implements DataSourceDescriptor { - 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() { diff --git a/core/src/main/java/io/xpipe/core/source/TableReadConnection.java b/core/src/main/java/io/xpipe/core/source/TableReadConnection.java new file mode 100644 index 00000000..0f897cfd --- /dev/null +++ b/core/src/main/java/io/xpipe/core/source/TableReadConnection.java @@ -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 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; + }); + } +} diff --git a/core/src/main/java/io/xpipe/core/source/TableDataWriteConnection.java b/core/src/main/java/io/xpipe/core/source/TableWriteConnection.java similarity index 66% rename from core/src/main/java/io/xpipe/core/source/TableDataWriteConnection.java rename to core/src/main/java/io/xpipe/core/source/TableWriteConnection.java index 8284d466..9b7a038f 100644 --- a/core/src/main/java/io/xpipe/core/source/TableDataWriteConnection.java +++ b/core/src/main/java/io/xpipe/core/source/TableWriteConnection.java @@ -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 writeLinesAcceptor(); diff --git a/core/src/main/java/io/xpipe/core/store/DataStore.java b/core/src/main/java/io/xpipe/core/store/DataStore.java index c7550e3d..befc70ba 100644 --- a/core/src/main/java/io/xpipe/core/store/DataStore.java +++ b/core/src/main/java/io/xpipe/core/store/DataStore.java @@ -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 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 determineDefaultName() { return Optional.empty(); } - default Optional getLastModified() { + /** + * Determines the last modified of this data store if this data store supports it. + */ + default Optional determineLastModified() { return Optional.empty(); } } diff --git a/core/src/main/java/io/xpipe/core/store/FileDataStore.java b/core/src/main/java/io/xpipe/core/store/FileDataStore.java deleted file mode 100644 index 1877793d..00000000 --- a/core/src/main/java/io/xpipe/core/store/FileDataStore.java +++ /dev/null @@ -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(); -} diff --git a/core/src/main/java/io/xpipe/core/store/InputStreamDataStore.java b/core/src/main/java/io/xpipe/core/store/InputStreamDataStore.java index c7a23eff..466c9300 100644 --- a/core/src/main/java/io/xpipe/core/store/InputStreamDataStore.java +++ b/core/src/main/java/io/xpipe/core/store/InputStreamDataStore.java @@ -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; diff --git a/core/src/main/java/io/xpipe/core/store/LocalFileDataStore.java b/core/src/main/java/io/xpipe/core/store/LocalFileDataStore.java index 4e1b2434..086f6a01 100644 --- a/core/src/main/java/io/xpipe/core/store/LocalFileDataStore.java +++ b/core/src/main/java/io/xpipe/core/store/LocalFileDataStore.java @@ -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 getLastModified() { + public Optional 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; } diff --git a/core/src/main/java/io/xpipe/core/store/RemoteFileDataStore.java b/core/src/main/java/io/xpipe/core/store/RemoteFileDataStore.java index 2b57e82e..a5ce120f 100644 --- a/core/src/main/java/io/xpipe/core/store/RemoteFileDataStore.java +++ b/core/src/main/java/io/xpipe/core/store/RemoteFileDataStore.java @@ -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 determineDefaultName() { @@ -13,30 +13,10 @@ public class RemoteFileDataStore extends FileDataStore { } @Override - public Optional getLastModified() { + public Optional 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; diff --git a/core/src/main/java/io/xpipe/core/store/StreamDataStore.java b/core/src/main/java/io/xpipe/core/store/StreamDataStore.java index 2c7396ae..9ca3627d 100644 --- a/core/src/main/java/io/xpipe/core/store/StreamDataStore.java +++ b/core/src/main/java/io/xpipe/core/store/StreamDataStore.java @@ -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; } diff --git a/core/src/main/java/io/xpipe/core/util/JacksonHelper.java b/core/src/main/java/io/xpipe/core/util/JacksonHelper.java index bd41b1a7..dca63ed1 100644 --- a/core/src/main/java/io/xpipe/core/util/JacksonHelper.java +++ b/core/src/main/java/io/xpipe/core/util/JacksonHelper.java @@ -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"); diff --git a/core/src/main/java/module-info.java b/core/src/main/java/module-info.java index 07e8485c..d429ea04 100644 --- a/core/src/main/java/module-info.java +++ b/core/src/main/java/module-info.java @@ -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; diff --git a/extension/build.gradle b/extension/build.gradle index cf7167b2..555d24e0 100644 --- a/extension/build.gradle +++ b/extension/build.gradle @@ -15,7 +15,7 @@ apply from: "$rootDir/deps/publish-base.gradle" version = file('../version').text group = 'io.xpipe' -archivesBaseName = 'core' +archivesBaseName = 'extension' repositories { mavenCentral() diff --git a/extension/src/main/java/io/xpipe/extension/DataSourceGuiProvider.java b/extension/src/main/java/io/xpipe/extension/DataSourceGuiProvider.java deleted file mode 100644 index 1065a317..00000000 --- a/extension/src/main/java/io/xpipe/extension/DataSourceGuiProvider.java +++ /dev/null @@ -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> source); - - DataSourceDescriptor createDefaultDataSource(DataStore input) throws Exception; - - String getDisplayName(); - - String getDisplayImage(); - - String getFileName(); - - Map, String> getFileExtensions(); - - String getDataSourceShortDescription(DataSourceDescriptor source); - - String getDataSourceLongDescription(DataSourceDescriptor source); - - Class> getType(); -} diff --git a/extension/src/main/java/io/xpipe/extension/DataSourceGuiProviders.java b/extension/src/main/java/io/xpipe/extension/DataSourceGuiProviders.java deleted file mode 100644 index 9b5cd37c..00000000 --- a/extension/src/main/java/io/xpipe/extension/DataSourceGuiProviders.java +++ /dev/null @@ -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 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 byClass(Class clazz) { - if (ALL == null) { - throw new IllegalStateException("Not initialized"); - } - return ALL.stream().filter(d -> d.getType().equals(clazz)).findAny(); - } - - public static Set getAll() { - if (ALL == null) { - throw new IllegalStateException("Not initialized"); - } - return ALL; - } -} diff --git a/extension/src/main/java/io/xpipe/extension/DataSourceProvider.java b/extension/src/main/java/io/xpipe/extension/DataSourceProvider.java index e73bf4fa..7ea57e88 100644 --- a/extension/src/main/java/io/xpipe/extension/DataSourceProvider.java +++ b/extension/src/main/java/io/xpipe/extension/DataSourceProvider.java @@ -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, String> getFileExtensions(); + } + + interface GuiProvider { + + Region createConfigOptions(DataStore input, Property> source); + + String getDisplayName(); + + String getDisplayImage(); + + Supplier 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> getType(); + Class> getDescriptorClass(); } diff --git a/extension/src/main/java/io/xpipe/extension/DataSourceProviders.java b/extension/src/main/java/io/xpipe/extension/DataSourceProviders.java index 9347c0f6..0c63150f 100644 --- a/extension/src/main/java/io/xpipe/extension/DataSourceProviders.java +++ b/extension/src/main/java/io/xpipe/extension/DataSourceProviders.java @@ -28,7 +28,7 @@ public class DataSourceProviders { public static TableDataSourceDescriptor createLocalTableDescriptor(TupleType type) { try { return (TableDataSourceDescriptor) - 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 byDataSourceClass(Class clazz) { + public static Optional 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 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 byURL(URL url) { diff --git a/extension/src/main/java/io/xpipe/extension/SupportedApplicationProvider.java b/extension/src/main/java/io/xpipe/extension/SupportedApplicationProvider.java index 4ffc44c2..faa7d28b 100644 --- a/extension/src/main/java/io/xpipe/extension/SupportedApplicationProvider.java +++ b/extension/src/main/java/io/xpipe/extension/SupportedApplicationProvider.java @@ -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 id); Region createStructureRetrieveInstructions(ObservableValue id); - Region createRawRetrieveInstructions(ObservableValue id); + Region createTextRetrieveInstructions(ObservableValue id); - Image getLogo(); + Region createRawRetrieveInstructions(ObservableValue id); String getId(); - String getName(); + Supplier getName(); } diff --git a/extension/src/main/java/io/xpipe/extension/comp/ToggleGroupComp.java b/extension/src/main/java/io/xpipe/extension/comp/ToggleGroupComp.java index d7c987a6..d5a3a6bc 100644 --- a/extension/src/main/java/io/xpipe/extension/comp/ToggleGroupComp.java +++ b/extension/src/main/java/io/xpipe/extension/comp/ToggleGroupComp.java @@ -46,6 +46,9 @@ public class ToggleGroupComp extends Comp> { } } 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) -> { diff --git a/extension/src/main/java/module-info.java b/extension/src/main/java/module-info.java index d30b8833..cf86e499 100644 --- a/extension/src/main/java/module-info.java +++ b/extension/src/main/java/module-info.java @@ -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;