diff --git a/app/src/main/java/io/xpipe/app/comp/storage/store/StoreCreationBarComp.java b/app/src/main/java/io/xpipe/app/comp/storage/store/StoreCreationBarComp.java index 7ca6f63f..c398f74a 100644 --- a/app/src/main/java/io/xpipe/app/comp/storage/store/StoreCreationBarComp.java +++ b/app/src/main/java/io/xpipe/app/comp/storage/store/StoreCreationBarComp.java @@ -55,7 +55,15 @@ public class StoreCreationBarComp extends SimpleComp { .shortcut(new KeyCodeCombination(KeyCode.D, KeyCombination.SHORTCUT_DOWN)) .apply(new FancyTooltipAugment<>("addDatabase")); - var box = new VerticalComp(List.of(newHostStore, newShellStore, newStreamStore, newDbStore)) + var newTunnelStore = new ButtonComp(AppI18n.observable("addTunnel"), new FontIcon("mdi2v-vector-polyline-plus"), () -> { + GuiDsStoreCreator.showCreation( + v -> v.getDisplayCategory().equals(DataStoreProvider.DisplayCategory.TUNNEL)); + }) + .styleClass(Styles.FLAT) + .shortcut(new KeyCodeCombination(KeyCode.T, KeyCombination.SHORTCUT_DOWN)) + .apply(new FancyTooltipAugment<>("addTunnel")); + + var box = new VerticalComp(List.of(newHostStore, newShellStore, newStreamStore, newDbStore, newTunnelStore)) .apply(struc -> struc.get().setFillWidth(true)); box.apply(s -> AppFont.medium(s.get())); var bar = box.createRegion(); diff --git a/app/src/main/java/io/xpipe/app/comp/storage/store/StoreEntryWrapper.java b/app/src/main/java/io/xpipe/app/comp/storage/store/StoreEntryWrapper.java index 2262b8e5..140902aa 100644 --- a/app/src/main/java/io/xpipe/app/comp/storage/store/StoreEntryWrapper.java +++ b/app/src/main/java/io/xpipe/app/comp/storage/store/StoreEntryWrapper.java @@ -197,6 +197,7 @@ public class StoreEntryWrapper implements StorageFilter.Filterable { found.createAction(entry.getStore().asNeeded()).execute(); } else if (getEntry().getStore() instanceof FixedHierarchyStore) { refreshWithChildrenAsync(); + } else { } } diff --git a/app/src/main/java/io/xpipe/app/comp/store/DataStoreSelectorComp.java b/app/src/main/java/io/xpipe/app/comp/store/DataStoreSelectorComp.java index 27a073c9..65569317 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/DataStoreSelectorComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/DataStoreSelectorComp.java @@ -22,7 +22,7 @@ import lombok.experimental.FieldDefaults; @AllArgsConstructor public class DataStoreSelectorComp extends Comp> { - DataStoreProvider.DataCategory category; + DataStoreProvider.DisplayCategory category; Property chosenStore; @Override @@ -34,7 +34,7 @@ public class DataStoreSelectorComp extends Comp> { "inProgress", null, null, - v -> v.getCategory().equals(category), + v -> v.getDisplayCategory().equals(category), entry -> { chosenStore.setValue(entry.getStore()); }, diff --git a/app/src/main/java/io/xpipe/app/comp/store/DsDbStoreChooserComp.java b/app/src/main/java/io/xpipe/app/comp/store/DsDbStoreChooserComp.java deleted file mode 100644 index 74345c8c..00000000 --- a/app/src/main/java/io/xpipe/app/comp/store/DsDbStoreChooserComp.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.xpipe.app.comp.store; - -import io.xpipe.app.core.AppFont; -import io.xpipe.app.core.AppI18n; -import io.xpipe.app.ext.DataSourceProvider; -import io.xpipe.app.ext.DataStoreProvider; -import io.xpipe.app.fxcomps.SimpleComp; -import io.xpipe.app.fxcomps.impl.TabPaneComp; -import io.xpipe.app.storage.DataStoreEntry; -import io.xpipe.core.store.DataStore; -import javafx.beans.binding.Bindings; -import javafx.beans.property.Property; -import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.value.ObservableValue; -import javafx.scene.layout.Region; - -import java.util.List; -import java.util.function.Predicate; - -public class DsDbStoreChooserComp extends SimpleComp { - - private final Property input; - private final ObservableValue> provider; - - public DsDbStoreChooserComp(Property input, ObservableValue> provider) { - this.input = input; - this.provider = provider; - } - - @Override - protected Region createSimple() { - var filter = Bindings.createObjectBinding( - () -> (Predicate) e -> { - if (provider.getValue() == null) { - return e.getProvider().getCategory() == DataStoreProvider.DataCategory.DATABASE; - } - - return provider.getValue().couldSupportStore(e.getStore()); - }, - provider); - - var connections = new TabPaneComp.Entry( - AppI18n.observable("savedConnections"), - "mdi2m-monitor", - NamedStoreChoiceComp.create(filter, input, DataStoreProvider.DataCategory.DATABASE) - .styleClass("store-local-file-chooser")); - - var pane = new TabPaneComp(new SimpleObjectProperty<>(connections), List.of(connections)); - pane.apply(s -> AppFont.normal(s.get())); - return pane.createRegion(); - } -} diff --git a/app/src/main/java/io/xpipe/app/comp/store/DsStreamStoreChoiceComp.java b/app/src/main/java/io/xpipe/app/comp/store/DsStreamStoreChoiceComp.java index d16160a5..4c696fd9 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/DsStreamStoreChoiceComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/DsStreamStoreChoiceComp.java @@ -121,7 +121,7 @@ public class DsStreamStoreChoiceComp extends SimpleComp implements Validatable { var other = new TabPaneComp.Entry( AppI18n.observable("other"), "mdrmz-web_asset", - new DataStoreSelectorComp(DataStoreProvider.DataCategory.STREAM, otherStore)); + new DataStoreSelectorComp(DataStoreProvider.DisplayCategory.HOST, otherStore)); var selectedTab = new SimpleObjectProperty(); if (localStore.get() != null) { diff --git a/app/src/main/java/io/xpipe/app/comp/store/GuiDsStoreCreator.java b/app/src/main/java/io/xpipe/app/comp/store/GuiDsStoreCreator.java index 9adba431..8dad7240 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/GuiDsStoreCreator.java +++ b/app/src/main/java/io/xpipe/app/comp/store/GuiDsStoreCreator.java @@ -105,11 +105,11 @@ public class GuiDsStoreCreator extends MultiStepComp.Step> { v -> true, newE -> { ThreadHelper.runAsync(() -> { - e.applyChanges(newE); if (!DataStorage.get().getStoreEntries().contains(e)) { DataStorage.get().addStoreEntry(e); + } else { + DataStorage.get().updateEntry(e, newE); } - DataStorage.get().refresh(); }); }, true); diff --git a/app/src/main/java/io/xpipe/app/comp/store/NamedStoreChoiceComp.java b/app/src/main/java/io/xpipe/app/comp/store/NamedStoreChoiceComp.java index 7a47d64a..e8dfe424 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/NamedStoreChoiceComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/NamedStoreChoiceComp.java @@ -146,7 +146,7 @@ public class NamedStoreChoiceComp extends SimpleComp implements Validatable { var text = new LabelComp(AppI18n.observable("noMatchingStoreFound")) .apply(struc -> VBox.setVgrow(struc.get(), Priority.ALWAYS)); var addButton = new ButtonComp(AppI18n.observable("addStore"), null, () -> { - GuiDsStoreCreator.showCreation(v -> v.getCategory().equals(category)); + // GuiDsStoreCreator.showCreation(v -> v.getCategory().equals(category)); }); var notice = new VerticalComp(List.of(text, addButton)) .apply(struc -> { diff --git a/app/src/main/java/io/xpipe/app/core/AppI18n.java b/app/src/main/java/io/xpipe/app/core/AppI18n.java index 34df6c68..a058d268 100644 --- a/app/src/main/java/io/xpipe/app/core/AppI18n.java +++ b/app/src/main/java/io/xpipe/app/core/AppI18n.java @@ -195,6 +195,10 @@ public class AppI18n { } public String getMarkdownDocumentation(String name) { + if (!markdownDocumentations.containsKey(name)) { + TrackEvent.withWarn("Markdown documentation for key " + name + " not found").handle(); + } + return markdownDocumentations.getOrDefault(name, ""); } diff --git a/app/src/main/java/io/xpipe/app/core/mode/OperationMode.java b/app/src/main/java/io/xpipe/app/core/mode/OperationMode.java index 64066374..4e98dd3a 100644 --- a/app/src/main/java/io/xpipe/app/core/mode/OperationMode.java +++ b/app/src/main/java/io/xpipe/app/core/mode/OperationMode.java @@ -1,6 +1,7 @@ package io.xpipe.app.core.mode; import io.xpipe.app.core.*; +import io.xpipe.app.ext.DataStoreProviders; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.issue.ErrorHandler; import io.xpipe.app.issue.TrackEvent; @@ -105,6 +106,11 @@ public abstract class OperationMode { setup(args); LauncherCommand.runLauncher(usedArgs); inStartup = false; + postInit(args); + } + + public static void postInit(String[] args) { + DataStoreProviders.postInit(AppExtensionManager.getInstance().getExtendedLayer()); } public static boolean isInStartup() { diff --git a/app/src/main/java/io/xpipe/app/exchange/cli/StoreProviderListExchangeImpl.java b/app/src/main/java/io/xpipe/app/exchange/cli/StoreProviderListExchangeImpl.java index ee1db68c..ee4202fe 100644 --- a/app/src/main/java/io/xpipe/app/exchange/cli/StoreProviderListExchangeImpl.java +++ b/app/src/main/java/io/xpipe/app/exchange/cli/StoreProviderListExchangeImpl.java @@ -15,12 +15,12 @@ public class StoreProviderListExchangeImpl extends StoreProviderListExchange @Override public Response handleRequest(BeaconHandler handler, Request msg) { - var categories = DataStoreProvider.DataCategory.values(); + var categories = DataStoreProvider.DisplayCategory.values(); var all = DataStoreProviders.getAll(); var map = Arrays.stream(categories) .collect(Collectors.toMap(category -> getName(category), category -> all.stream() .filter(dataStoreProvider -> - dataStoreProvider.getCategory().equals(category)) + dataStoreProvider.getDisplayCategory().equals(category)) .map(p -> ProviderEntry.builder() .id(p.getId()) .description(p.getDisplayDescription()) @@ -31,7 +31,7 @@ public class StoreProviderListExchangeImpl extends StoreProviderListExchange return Response.builder().entries(map).build(); } - private String getName(DataStoreProvider.DataCategory category) { + private String getName(DataStoreProvider.DisplayCategory category) { return category.name().substring(0, 1).toUpperCase() + category.name().substring(1).toLowerCase(); } diff --git a/app/src/main/java/io/xpipe/app/ext/DataStoreProvider.java b/app/src/main/java/io/xpipe/app/ext/DataStoreProvider.java index e421f6af..3371cc01 100644 --- a/app/src/main/java/io/xpipe/app/ext/DataStoreProvider.java +++ b/app/src/main/java/io/xpipe/app/ext/DataStoreProvider.java @@ -25,7 +25,6 @@ public interface DataStoreProvider { } default void validate() { - getCategory(); for (Class storeClass : getStoreClasses()) { if (!JacksonizedValue.class.isAssignableFrom(storeClass)) { throw new ExtensionException( @@ -34,6 +33,8 @@ public interface DataStoreProvider { } } + default void preAdd(DataStore store) {} + default Comp customDisplay(StoreSection s) { return new StandardStoreEntryComp(s.getWrapper(), null); } @@ -90,27 +91,7 @@ public interface DataStoreProvider { return null; } - default DataCategory getCategory() { - var c = getStoreClasses().get(0); - if (StreamDataStore.class.isAssignableFrom(c)) { - return DataCategory.STREAM; - } - - if (FileSystem.class.isAssignableFrom(c) || ShellStore.class.isAssignableFrom(c)) { - return DataCategory.SHELL; - } - - throw new ExtensionException("Provider " + getId() + " has no set category"); - } - default DisplayCategory getDisplayCategory() { - var category = getCategory(); - if (category.equals(DataCategory.SHELL)) { - return DisplayCategory.HOST; - } - if (category.equals(DataCategory.DATABASE)) { - return DisplayCategory.DATABASE; - } return DisplayCategory.OTHER; } @@ -130,19 +111,26 @@ public interface DataStoreProvider { return true; } + default void postInit(){ + } + default void storageInit() throws Exception {} default boolean isShareable() { return false; } - String queryInformationString(DataStore store, int length) throws Exception; + default String queryInformationString(DataStore store, int length) throws Exception { + return null; + } default String queryInvalidInformationString(DataStore store, int length) throws Exception { return null; } - String toSummaryString(DataStore store, int length); + default String toSummaryString(DataStore store, int length) { + return null; + } default String i18n(String key) { return AppI18n.get(getId() + "." + key); @@ -205,6 +193,7 @@ public interface DataStoreProvider { DATABASE, SHELL, COMMAND, + TUNNEL, OTHER } } diff --git a/app/src/main/java/io/xpipe/app/ext/DataStoreProviders.java b/app/src/main/java/io/xpipe/app/ext/DataStoreProviders.java index 22cf3fbb..2cb5c091 100644 --- a/app/src/main/java/io/xpipe/app/ext/DataStoreProviders.java +++ b/app/src/main/java/io/xpipe/app/ext/DataStoreProviders.java @@ -17,7 +17,6 @@ public class DataStoreProviders { if (ALL == null) { ALL = ServiceLoader.load(layer, DataStoreProvider.class).stream() .map(ServiceLoader.Provider::get) - .sorted(Comparator.comparing(DataStoreProvider::getId)) .collect(Collectors.toList()); ALL.removeIf(p -> { try { @@ -35,6 +34,20 @@ public class DataStoreProviders { } } + public static void postInit(ModuleLayer layer) { + ALL = ServiceLoader.load(layer, DataStoreProvider.class).stream() + .map(ServiceLoader.Provider::get) + .sorted(Comparator.comparing(DataStoreProvider::getId)) + .collect(Collectors.toList()); + ALL.forEach(p -> { + try { + p.postInit(); + } catch (Throwable e) { + ErrorEvent.fromThrowable(e).handle(); + } + }); + } + public static Optional byName(String name) { if (ALL == null) { throw new IllegalStateException("Not initialized"); diff --git a/app/src/main/java/io/xpipe/app/storage/DataStateProviderImpl.java b/app/src/main/java/io/xpipe/app/storage/DataStateProviderImpl.java index d1de0897..42b87827 100644 --- a/app/src/main/java/io/xpipe/app/storage/DataStateProviderImpl.java +++ b/app/src/main/java/io/xpipe/app/storage/DataStateProviderImpl.java @@ -42,6 +42,11 @@ public class DataStateProviderImpl extends DataStateProvider { return c.cast(result); } + public boolean isInStorage(DataStore store) { + var entry = DataStorage.get().getStoreEntryIfPresent(store); + return entry.isPresent(); + } + @Override public Path getInternalStreamStore(UUID id) { return DataStorage.get().getInternalStreamPath(id); diff --git a/app/src/main/java/io/xpipe/app/storage/DataStorage.java b/app/src/main/java/io/xpipe/app/storage/DataStorage.java index 4b082f36..b9aa19b7 100644 --- a/app/src/main/java/io/xpipe/app/storage/DataStorage.java +++ b/app/src/main/java/io/xpipe/app/storage/DataStorage.java @@ -92,6 +92,7 @@ public abstract class DataStorage { Collections.reverse(ordered); synchronized (this) { + ordered.forEach(entry -> entry.finalizeEntry()); this.storeEntries.removeAll(ordered); this.listeners.forEach(l -> l.onStoreRemove(ordered.toArray(DataStoreEntry[]::new))); } @@ -213,6 +214,12 @@ public abstract class DataStorage { } } + public void updateEntry(DataStoreEntry entry, DataStoreEntry newEntry) { + newEntry.finalizeEntry(); + entry.applyChanges(newEntry); + entry.initializeEntry(); + } + public void refreshAsync(DataStoreEntry element, boolean deep) { ThreadHelper.runAsync(() -> { try { @@ -233,6 +240,8 @@ public abstract class DataStorage { } public void addStoreEntry(@NonNull DataStoreEntry e) { + e.getProvider().preAdd(e.getStore()); + synchronized (this) { e.setDirectory(getStoresDir().resolve(e.getUuid().toString())); this.storeEntries.add(e); @@ -241,16 +250,22 @@ public abstract class DataStorage { save(); this.listeners.forEach(l -> l.onStoreAdd(e)); + e.initializeEntry(); } public void addStoreEntries(@NonNull DataStoreEntry... es) { synchronized (this) { for (DataStoreEntry e : es) { + e.getProvider().preAdd(e.getStore()); + e.setDirectory(getStoresDir().resolve(e.getUuid().toString())); this.storeEntries.add(e); propagateUpdate(e); } this.listeners.forEach(l -> l.onStoreAdd(es)); + for (DataStoreEntry e : es) { + e.initializeEntry(); + } } save(); } @@ -284,6 +299,7 @@ public abstract class DataStorage { } public void deleteStoreEntry(@NonNull DataStoreEntry store) { + store.finalizeEntry(); synchronized (this) { this.storeEntries.remove(store); } @@ -298,13 +314,6 @@ public abstract class DataStorage { public abstract void load(); - public void refresh() { - getStoreEntries().forEach(entry -> { - entry.simpleRefresh(); - }); - save(); - } - public abstract void save(); public synchronized Optional getStoreEntry(UUID id) { diff --git a/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java b/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java index 1e3b175e..dc42a6c1 100644 --- a/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java +++ b/app/src/main/java/io/xpipe/app/storage/DataStoreEntry.java @@ -288,6 +288,36 @@ public class DataStoreEntry extends StorageElement { } } + @SneakyThrows + public void initializeEntry() { + try { + state = State.VALIDATING; + listeners.forEach(l -> l.onUpdate()); + store.initializeValidate(); + state = State.COMPLETE_AND_VALID; + } catch (Exception e) { + state = State.COMPLETE_BUT_INVALID; + ErrorEvent.fromThrowable(e).handle(); + } finally { + propagateUpdate(); + } + } + + @SneakyThrows + public void finalizeEntry() { + try { + state = State.VALIDATING; + listeners.forEach(l -> l.onUpdate()); + store.finalizeValidate(); + state = State.COMPLETE_AND_VALID; + } catch (Exception e) { + state = State.COMPLETE_BUT_INVALID; + ErrorEvent.fromThrowable(e).handle(); + } finally { + propagateUpdate(); + } + } + @Override protected boolean shouldSave() { return getStore() == null || getStore().shouldSave(); diff --git a/app/src/main/java/io/xpipe/app/util/OptionsBuilder.java b/app/src/main/java/io/xpipe/app/util/OptionsBuilder.java index 9a8d3775..8149c2ea 100644 --- a/app/src/main/java/io/xpipe/app/util/OptionsBuilder.java +++ b/app/src/main/java/io/xpipe/app/util/OptionsBuilder.java @@ -42,6 +42,12 @@ public class OptionsBuilder { entries.add(entry); } + public OptionsBuilder sub(OptionsBuilder builder) { + props.addAll(builder.props); + pushComp(builder.buildComp()); + return this; + } + public OptionsBuilder addTitle(String titleKey) { finishCurrent(); entries.add(new OptionsComp.Entry( diff --git a/app/src/main/resources/io/xpipe/app/resources/lang/dscreation_en.properties b/app/src/main/resources/io/xpipe/app/resources/lang/dscreation_en.properties index 18975442..066226ef 100644 --- a/app/src/main/resources/io/xpipe/app/resources/lang/dscreation_en.properties +++ b/app/src/main/resources/io/xpipe/app/resources/lang/dscreation_en.properties @@ -42,6 +42,7 @@ clean=Clean refresh=Refresh remove=Remove addDatabase=Add Database ... +addTunnel=Add Tunnel ... addHost=Add Remote Host ... addShell=Add Environment ... addCommand=Add Command ... diff --git a/app/src/main/resources/io/xpipe/app/resources/lang/translations_en.properties b/app/src/main/resources/io/xpipe/app/resources/lang/translations_en.properties index d5a33bca..0e10dc70 100644 --- a/app/src/main/resources/io/xpipe/app/resources/lang/translations_en.properties +++ b/app/src/main/resources/io/xpipe/app/resources/lang/translations_en.properties @@ -116,7 +116,6 @@ noMatchingSourceFound=No matching source found addSource=Add Source edit=Edit addStream=Add File -addDatabase=Add Database pipeStream=Pipe File pipeDatabase=Pipe Database transfer=Transfer diff --git a/core/src/main/java/io/xpipe/core/impl/InternalStreamStore.java b/core/src/main/java/io/xpipe/core/impl/InternalStreamStore.java index 4fc37f41..2bf7bb7a 100644 --- a/core/src/main/java/io/xpipe/core/impl/InternalStreamStore.java +++ b/core/src/main/java/io/xpipe/core/impl/InternalStreamStore.java @@ -9,13 +9,10 @@ import lombok.Getter; import lombok.experimental.SuperBuilder; import lombok.extern.jackson.Jacksonized; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.time.Instant; -import java.util.Optional; import java.util.UUID; @JsonTypeName("internalStream") @@ -35,20 +32,10 @@ public class InternalStreamStore extends JacksonizedValue implements StreamDataS return DataFlow.INPUT_OUTPUT; } - @Override - public Optional determineDefaultName() { - return Optional.of(uuid.toString()); - } - private Path getFile() { return DataStateProvider.get().getInternalStreamStore(uuid); } - @Override - public Optional determineLastModified() throws IOException { - return Optional.of(Files.getLastModifiedTime(getFile()).toInstant()); - } - @Override public InputStream openInput() throws Exception { return Files.newInputStream(getFile()); diff --git a/core/src/main/java/io/xpipe/core/impl/LocalDirectoryDataStore.java b/core/src/main/java/io/xpipe/core/impl/LocalDirectoryDataStore.java index b1c186d0..47958657 100644 --- a/core/src/main/java/io/xpipe/core/impl/LocalDirectoryDataStore.java +++ b/core/src/main/java/io/xpipe/core/impl/LocalDirectoryDataStore.java @@ -5,11 +5,7 @@ import com.fasterxml.jackson.annotation.JsonTypeName; import io.xpipe.core.store.DataStore; import lombok.EqualsAndHashCode; -import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; -import java.time.Instant; -import java.util.Optional; @JsonTypeName("localDir") @EqualsAndHashCode @@ -22,21 +18,6 @@ public class LocalDirectoryDataStore implements DataStore { this.file = file; } - @Override - public Optional determineDefaultName() { - return Optional.of(file.getFileName().toString()); - } - - @Override - public Optional determineLastModified() { - try { - var l = Files.getLastModifiedTime(file); - return Optional.of(l.toInstant()); - } catch (IOException e) { - return Optional.empty(); - } - } - public Path getPath() { return file; } diff --git a/core/src/main/java/io/xpipe/core/impl/NamedStore.java b/core/src/main/java/io/xpipe/core/impl/NamedStore.java index ff1e9dd2..87d3821c 100644 --- a/core/src/main/java/io/xpipe/core/impl/NamedStore.java +++ b/core/src/main/java/io/xpipe/core/impl/NamedStore.java @@ -6,9 +6,6 @@ import lombok.Getter; import lombok.experimental.SuperBuilder; import lombok.extern.jackson.Jacksonized; -import java.time.Instant; -import java.util.Optional; - /** * A store that refers to another store in the XPipe storage. * The referenced store has to be resolved by the caller manually, as this class does not act as a resolver. @@ -36,13 +33,4 @@ public final class NamedStore implements DataStore { throw new UnsupportedOperationException(); } - @Override - public Optional determineDefaultName() { - throw new UnsupportedOperationException(); - } - - @Override - public Optional determineLastModified() { - throw new UnsupportedOperationException(); - } } 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 78384b55..81185142 100644 --- a/core/src/main/java/io/xpipe/core/store/DataStore.java +++ b/core/src/main/java/io/xpipe/core/store/DataStore.java @@ -5,10 +5,6 @@ import io.xpipe.core.impl.StdinDataStore; import io.xpipe.core.impl.StdoutDataStore; import io.xpipe.core.source.DataSource; -import java.io.IOException; -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, @@ -77,6 +73,10 @@ public interface DataStore { */ default void validate() throws Exception {} + default void initializeValidate() throws Exception {} + + default void finalizeValidate() throws Exception {} + default void checkComplete() throws Exception {} default boolean delete() { @@ -90,19 +90,4 @@ public interface DataStore { 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(); - } - - /** - * Determines the last modified of this data store if this data store supports it. - */ - default Optional determineLastModified() throws IOException { - return Optional.empty(); - } } diff --git a/core/src/main/java/io/xpipe/core/store/FilenameStore.java b/core/src/main/java/io/xpipe/core/store/FilenameStore.java index 571a66b6..4a7ec873 100644 --- a/core/src/main/java/io/xpipe/core/store/FilenameStore.java +++ b/core/src/main/java/io/xpipe/core/store/FilenameStore.java @@ -1,20 +1,11 @@ package io.xpipe.core.store; -import java.util.Optional; - /** * Represents a store that has a filename. * Note that this does not only apply to file stores but any other store as well that has some kind of file name. */ public interface FilenameStore extends DataStore { - @Override - default Optional determineDefaultName() { - var n = getFileName(); - var i = n.lastIndexOf('.'); - return Optional.of(i != -1 ? n.substring(0, i) : n); - } - default String getFileExtension() { var split = getFileName().split("[\\\\.]"); if (split.length == 0) { diff --git a/core/src/main/java/io/xpipe/core/store/StatefulDataStore.java b/core/src/main/java/io/xpipe/core/store/StatefulDataStore.java index 10f5d520..1ba34363 100644 --- a/core/src/main/java/io/xpipe/core/store/StatefulDataStore.java +++ b/core/src/main/java/io/xpipe/core/store/StatefulDataStore.java @@ -6,6 +6,10 @@ import java.util.function.Supplier; public interface StatefulDataStore extends DataStore { + default boolean isInStorage() { + return DataStateProvider.get().isInStorage(this); + } + default T getState(String key, Class c, T def) { return DataStateProvider.get().getState(this, key, c, () -> def); } diff --git a/core/src/main/java/io/xpipe/core/util/DataStateProvider.java b/core/src/main/java/io/xpipe/core/util/DataStateProvider.java index 52fd192b..23a71a50 100644 --- a/core/src/main/java/io/xpipe/core/util/DataStateProvider.java +++ b/core/src/main/java/io/xpipe/core/util/DataStateProvider.java @@ -25,5 +25,7 @@ public abstract class DataStateProvider { public abstract T getState(DataStore store, String key, Class c, Supplier def); + public abstract boolean isInStorage(DataStore store); + public abstract Path getInternalStreamStore(UUID id); } diff --git a/ext/base/src/main/java/io/xpipe/ext/base/HttpStore.java b/ext/base/src/main/java/io/xpipe/ext/base/HttpStore.java index f41c5216..39c70d37 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/HttpStore.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/HttpStore.java @@ -25,7 +25,6 @@ import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.util.Arrays; import java.util.Map; -import java.util.Optional; @JsonTypeName("http") @SuperBuilder @@ -101,11 +100,6 @@ public class HttpStore extends JacksonizedValue implements StreamDataStore, Stat Validators.nonNull(headers, "Headers"); } - @Override - public Optional determineDefaultName() { - return Optional.ofNullable(getURL().getHost()); - } - @Override public void validate() throws Exception { var client = createClient(); diff --git a/ext/base/src/main/java/io/xpipe/ext/base/InMemoryStoreProvider.java b/ext/base/src/main/java/io/xpipe/ext/base/InMemoryStoreProvider.java index f7a55f9d..a6fe60f5 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/InMemoryStoreProvider.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/InMemoryStoreProvider.java @@ -70,11 +70,6 @@ public class InMemoryStoreProvider implements DataStoreProvider { }); } - @Override - public DataCategory getCategory() { - return DataCategory.STREAM; - } - @Override public DataStore defaultStore() { return new InMemoryStore(new byte[0]); diff --git a/version b/version index d5e98f72..e21e727f 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.3.2 \ No newline at end of file +1.4.0 \ No newline at end of file