This commit is contained in:
Christopher Schnick
2022-10-15 16:06:02 +02:00
parent 27843ae0fd
commit 55da767dab
186 changed files with 1541 additions and 1606 deletions

View File

@@ -4,7 +4,10 @@ import io.xpipe.core.store.FileStore;
import io.xpipe.core.store.StreamDataStore;
import lombok.Value;
import java.io.*;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.*;
@@ -15,8 +18,12 @@ import java.util.Map;
public abstract class Charsetter {
private static final int MAX_BYTES = 8192;
public static Charsetter INSTANCE;
private static CharsetterUniverse universe;
protected Charsetter() {}
protected static void checkInit() {
if (universe == null) {
throw new IllegalStateException("Charsetter not initialized");
@@ -27,30 +34,25 @@ public abstract class Charsetter {
universe = CharsetterUniverse.create(ctx);
}
@Value
public static class Result {
StreamCharset charset;
NewLine newLine;
}
protected Charsetter() {
}
public static Charsetter INSTANCE;
public static Charsetter get() {
return INSTANCE;
}
@FunctionalInterface
public interface FailableSupplier<R, E extends Throwable> {
R get() throws E;
}
@FunctionalInterface
public interface FailableConsumer<T, E extends Throwable> {
void accept(T var1) throws E;
private static int count(byte[] outerArray, byte[] smallerArray) {
int count = 0;
for (int i = 0; i < outerArray.length - smallerArray.length + 1; ++i) {
boolean found = true;
for (int j = 0; j < smallerArray.length; ++j) {
if (outerArray[i + j] != smallerArray[j]) {
found = false;
break;
}
}
if (found) {
count++;
}
}
return count;
}
public BufferedReader reader(StreamDataStore store, StreamCharset charset) throws Exception {
@@ -73,16 +75,15 @@ public abstract class Charsetter {
return new BufferedReader(new InputStreamReader(stream, charset.getCharset()));
}
public abstract Result read(FailableSupplier<InputStream, Exception> in, FailableConsumer<InputStreamReader, Exception> con) throws Exception;
private static final int MAX_BYTES = 8192;
public abstract Result read(
FailableSupplier<InputStream, Exception> in, FailableConsumer<InputStreamReader, Exception> con)
throws Exception;
public Result detect(StreamDataStore store) throws Exception {
Result result = new Result(null, null);
if (store.canOpen()) {
try (InputStream inputStream = store.openBufferedInput()) {
StreamCharset detected = null;
for (var charset : StreamCharset.COMMON) {
@@ -135,25 +136,10 @@ public abstract class Charsetter {
return null;
}
return count.entrySet().stream().min(Comparator.comparingInt(Map.Entry::getValue))
.orElseThrow().getKey();
}
private static int count(byte[] outerArray, byte[] smallerArray) {
int count = 0;
for (int i = 0; i < outerArray.length - smallerArray.length + 1; ++i) {
boolean found = true;
for (int j = 0; j < smallerArray.length; ++j) {
if (outerArray[i + j] != smallerArray[j]) {
found = false;
break;
}
}
if (found) {
count++;
}
}
return count;
return count.entrySet().stream()
.min(Comparator.comparingInt(Map.Entry::getValue))
.orElseThrow()
.getKey();
}
public Charset inferCharset(byte[] content) {
@@ -179,4 +165,21 @@ public abstract class Charsetter {
return StandardCharsets.UTF_8;
}
@FunctionalInterface
public interface FailableSupplier<R, E extends Throwable> {
R get() throws E;
}
@FunctionalInterface
public interface FailableConsumer<T, E extends Throwable> {
void accept(T var1) throws E;
}
@Value
public static class Result {
StreamCharset charset;
NewLine newLine;
}
}

View File

@@ -11,15 +11,13 @@ import java.util.Locale;
@AllArgsConstructor
public class CharsetterContext {
public static CharsetterContext empty() {
return new CharsetterContext(Charset.defaultCharset().name(), Locale.getDefault(), Locale.getDefault(), List.of());
}
String systemCharsetName;
Locale systemLocale;
Locale appLocale;
List<String> observedCharsets;
public static CharsetterContext empty() {
return new CharsetterContext(
Charset.defaultCharset().name(), Locale.getDefault(), Locale.getDefault(), List.of());
}
}

View File

@@ -5,24 +5,11 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Arrays;
public enum NewLine {
@JsonProperty("lf")
LF("\n", "lf"),
@JsonProperty("crlf")
CRLF("\r\n", "crlf");
public static NewLine platform() {
return Arrays.stream(values())
.filter(n -> n.getNewLine().equals(System.getProperty("line.separator")))
.findFirst().orElseThrow();
}
public static NewLine id(String id) {
return Arrays.stream(values())
.filter(n -> n.getId().equalsIgnoreCase(id))
.findFirst().orElseThrow();
}
private final String newLine;
private final String id;
@@ -31,6 +18,20 @@ public enum NewLine {
this.id = id;
}
public static NewLine platform() {
return Arrays.stream(values())
.filter(n -> n.getNewLine().equals(System.getProperty("line.separator")))
.findFirst()
.orElseThrow();
}
public static NewLine id(String id) {
return Arrays.stream(values())
.filter(n -> n.getId().equalsIgnoreCase(id))
.findFirst()
.orElseThrow();
}
public String getNewLine() {
return newLine;
}

View File

@@ -13,10 +13,42 @@ import java.util.stream.Stream;
@Value
public class StreamCharset {
public static final StreamCharset UTF8 = new StreamCharset(StandardCharsets.UTF_8, null);
public static final StreamCharset UTF8_BOM =
new StreamCharset(StandardCharsets.UTF_8, new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
public static final StreamCharset UTF16 = new StreamCharset(StandardCharsets.UTF_16, null);
public static final StreamCharset UTF16_BOM =
new StreamCharset(StandardCharsets.UTF_16, new byte[] {(byte) 0xFE, (byte) 0xFF});
public static final StreamCharset UTF16_LE = new StreamCharset(StandardCharsets.UTF_16LE, null);
public static final StreamCharset UTF16_LE_BOM =
new StreamCharset(StandardCharsets.UTF_16LE, new byte[] {(byte) 0xFF, (byte) 0xFE});
public static final StreamCharset UTF32 = new StreamCharset(Charset.forName("utf-32"), null);
public static final StreamCharset UTF32_BOM =
new StreamCharset(Charset.forName("utf-32"), new byte[] {0x00, 0x00, (byte) 0xFE, (byte) 0xFF});
public static final List<StreamCharset> COMMON = List.of(
UTF8,
UTF8_BOM,
UTF16,
UTF16_BOM,
UTF16_LE,
UTF16_LE_BOM,
UTF32,
UTF32_BOM,
new StreamCharset(StandardCharsets.US_ASCII, null),
new StreamCharset(StandardCharsets.ISO_8859_1, null),
new StreamCharset(Charset.forName("Windows-1251"), null),
new StreamCharset(Charset.forName("Windows-1252"), null));
public static final List<StreamCharset> RARE = Charset.availableCharsets().values().stream()
.filter(charset -> COMMON.stream().noneMatch(c -> c.getCharset().equals(charset)))
.map(charset -> new StreamCharset(charset, null))
.toList();
Charset charset;
byte[] byteOrderMark;
public static StreamCharset get(Charset charset, boolean byteOrderMark) {
return Stream.concat(COMMON.stream(), RARE.stream())
.filter(streamCharset -> streamCharset.getCharset()
.equals(charset) && streamCharset.hasByteOrderMark() == byteOrderMark)
.filter(streamCharset ->
streamCharset.getCharset().equals(charset) && streamCharset.hasByteOrderMark() == byteOrderMark)
.findFirst()
.orElseThrow();
}
@@ -24,66 +56,15 @@ public class StreamCharset {
@JsonCreator
public static StreamCharset get(String s) {
var byteOrderMark = s.endsWith("-bom");
var charset = Charset.forName(s.substring(
0, s.length() - (byteOrderMark ?
4 :
0)));
var charset = Charset.forName(s.substring(0, s.length() - (byteOrderMark ? 4 : 0)));
return StreamCharset.get(charset, byteOrderMark);
}
Charset charset;
byte[] byteOrderMark;
@JsonValue
public String toString() {
return getCharset()
.name().toLowerCase(Locale.ROOT) + (hasByteOrderMark() ?
"-bom" :
"");
return getCharset().name().toLowerCase(Locale.ROOT) + (hasByteOrderMark() ? "-bom" : "");
}
public static final StreamCharset UTF8 = new StreamCharset(StandardCharsets.UTF_8, null);
public static final StreamCharset UTF8_BOM = new StreamCharset(StandardCharsets.UTF_8, new byte[]{
(byte) 0xEF,
(byte) 0xBB,
(byte) 0xBF
});
public static final StreamCharset UTF16 = new StreamCharset(StandardCharsets.UTF_16, null);
public static final StreamCharset UTF16_BOM = new StreamCharset(StandardCharsets.UTF_16, new byte[]{
(byte) 0xFE,
(byte) 0xFF
});
public static final StreamCharset UTF16_LE = new StreamCharset(StandardCharsets.UTF_16LE, null);
public static final StreamCharset UTF16_LE_BOM = new StreamCharset(StandardCharsets.UTF_16LE, new byte[]{
(byte) 0xFF,
(byte) 0xFE
});
public static final StreamCharset UTF32 = new StreamCharset(Charset.forName("utf-32"), null);
public static final StreamCharset UTF32_BOM = new StreamCharset(Charset.forName("utf-32"), new byte[]{
0x00,
0x00,
(byte) 0xFE,
(byte) 0xFF
});
public static final List<StreamCharset> COMMON = List.of(
UTF8, UTF8_BOM, UTF16, UTF16_BOM, UTF16_LE, UTF16_LE_BOM, UTF32, UTF32_BOM, new StreamCharset(StandardCharsets.US_ASCII, null),
new StreamCharset(StandardCharsets.ISO_8859_1, null),
new StreamCharset(Charset.forName("Windows-1251"), null), new StreamCharset(Charset.forName("Windows-1252"), null)
);
public static final List<StreamCharset> RARE = Charset.availableCharsets()
.values()
.stream()
.filter(charset -> COMMON.stream()
.noneMatch(c -> c.getCharset()
.equals(charset)))
.map(charset -> new StreamCharset(charset, null))
.toList();
public boolean hasByteOrderMark() {
return byteOrderMark != null;
}

View File

@@ -1,7 +1,7 @@
package io.xpipe.core.data.generic;
import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.ValueNode;
import java.util.ArrayList;
@@ -16,8 +16,8 @@ public class GenericArrayReader implements GenericAbstractReader {
private int currentIndex = 0;
private GenericAbstractReader currentReader;
private DataStructureNode created;
public GenericArrayReader() {
}
public GenericArrayReader() {}
public static GenericArrayReader newReader(int length) {
var ar = new GenericArrayReader();

View File

@@ -4,22 +4,15 @@ import java.util.Map;
public interface GenericDataStreamCallback {
default void onName(String name) {
}
default void onName(String name) {}
default void onArrayStart(int length) {
}
default void onArrayStart(int length) {}
default void onArrayEnd(Map<Integer, String> metaAttributes) {
}
default void onArrayEnd(Map<Integer, String> metaAttributes) {}
default void onTupleStart(int length) {
}
default void onTupleStart(int length) {}
default void onTupleEnd(Map<Integer, String> metaAttributes) {
}
default void onTupleEnd(Map<Integer, String> metaAttributes) {}
default void onValue(byte[] value, Map<Integer, String> metaAttributes) {
}
default void onValue(byte[] value, Map<Integer, String> metaAttributes) {}
}

View File

@@ -86,7 +86,6 @@ public class GenericDataStructureNodeReader implements GenericDataStreamCallback
return;
}
node = ValueNode.of(value).tag(metaAttributes);
}
}

View File

@@ -18,8 +18,8 @@ public class GenericTupleReader implements GenericAbstractReader {
private int currentIndex = 0;
private GenericAbstractReader currentReader;
private DataStructureNode created;
public GenericTupleReader() {
}
public GenericTupleReader() {}
public static GenericTupleReader newReader(int length) {
var tr = new GenericTupleReader();

View File

@@ -8,6 +8,8 @@ import java.util.stream.Collectors;
public abstract class ArrayNode extends DataStructureNode {
protected ArrayNode() {}
public static ArrayNode empty() {
return of(List.of());
}
@@ -20,9 +22,6 @@ public abstract class ArrayNode extends DataStructureNode {
return new SimpleArrayNode(nodes);
}
protected ArrayNode() {
}
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -32,7 +31,8 @@ public abstract class ArrayNode extends DataStructureNode {
return false;
}
var toReturn = getNodes().equals(that.getNodes()) && Objects.equals(getMetaAttributes(), that.getMetaAttributes());
var toReturn =
getNodes().equals(that.getNodes()) && Objects.equals(getMetaAttributes(), that.getMetaAttributes());
// Useful for debugging
if (toReturn == false) {
@@ -64,6 +64,7 @@ public abstract class ArrayNode extends DataStructureNode {
@Override
public final ArrayType determineDataType() {
return ArrayType.ofSharedType(getNodes().stream().map(DataStructureNode::determineDataType).toList());
return ArrayType.ofSharedType(
getNodes().stream().map(DataStructureNode::determineDataType).toList());
}
}

View File

@@ -67,7 +67,6 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
return this;
}
public String getMetaAttribute(Integer key) {
if (metaAttributes == null) {
return null;
@@ -104,9 +103,6 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
throw unsupported("get nodes");
}
public record KeyValue(String key, DataStructureNode value) {
}
protected abstract String getName();
protected UnsupportedOperationException unsupported(String s) {
@@ -125,12 +121,15 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
}
public String metaToString() {
return "(" + (metaAttributes != null ?
metaAttributes.entrySet()
.stream()
.map(e -> e.getValue() != null ? e.getKey() + ":" + e.getValue() : e.getKey().toString())
.collect(Collectors.joining("|")) :
"") + ")";
return "("
+ (metaAttributes != null
? metaAttributes.entrySet().stream()
.map(e -> e.getValue() != null
? e.getKey() + ":" + e.getValue()
: e.getKey().toString())
.collect(Collectors.joining("|"))
: "")
+ ")";
}
public abstract String toString(int indent);
@@ -146,11 +145,11 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
public boolean isValue() {
return false;
}
public DataStructureNode set(int index, DataStructureNode node) {
throw unsupported("set at index");
}
public final ValueNode asValue() {
if (!isValue()) {
throw new UnsupportedOperationException(getName() + " is not a value node");
@@ -235,4 +234,6 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
public Iterator<DataStructureNode> iterator() {
throw unsupported("iterator creation");
}
public record KeyValue(String key, DataStructureNode value) {}
}

View File

@@ -152,9 +152,7 @@ public class DataStructureNodePointer {
@Override
public DataStructureNode tryMatch(DataStructureNode n) {
var res = n.stream()
.filter(selector)
.findAny();
var res = n.stream().filter(selector).findAny();
return res.orElse(null);
}
@@ -184,7 +182,6 @@ public class DataStructureNodePointer {
return new Builder(new ArrayList<>(path));
}
public Builder name(String name) {
path.add(new NameElement(name));
return this;
@@ -219,7 +216,8 @@ public class DataStructureNodePointer {
});
}
public Builder pointerEvaluation(DataStructureNodePointer pointer, Function<DataStructureNode, String> converter) {
public Builder pointerEvaluation(
DataStructureNodePointer pointer, Function<DataStructureNode, String> converter) {
path.add(new FunctionElement((current) -> {
var res = pointer.get(current);
if (res != null) {

View File

@@ -84,7 +84,9 @@ public class LinkedTupleNode extends TupleNode {
@Override
public DataType determineDataType() {
return TupleType.of(getKeyNames(), getNodes().stream().map(DataStructureNode::determineDataType).toList());
return TupleType.of(
getKeyNames(),
getNodes().stream().map(DataStructureNode::determineDataType).toList());
}
@Override
@@ -142,7 +144,6 @@ public class LinkedTupleNode extends TupleNode {
return "LinkedTupleNode(" + size() + ")";
}
@Override
public int size() {
return tupleNodes.stream().mapToInt(TupleNode::size).sum();
@@ -174,6 +175,7 @@ public class LinkedTupleNode extends TupleNode {
return this;
}
return new LinkedTupleNode(tupleNodes.stream().map(n -> n.isMutable() ? n : n.mutable()).toList());
return new LinkedTupleNode(
tupleNodes.stream().map(n -> n.isMutable() ? n : n.mutable()).toList());
}
}

View File

@@ -10,8 +10,6 @@ import java.util.function.Consumer;
import java.util.stream.Stream;
@AllArgsConstructor
public class SimpleArrayNode extends ArrayNode {
List<DataStructureNode> nodes;
@@ -79,6 +77,4 @@ public class SimpleArrayNode extends ArrayNode {
nodes.remove(index);
return this;
}
}

View File

@@ -23,8 +23,11 @@ public class SimpleValueNode extends ValueNode {
@Override
public String toString(int indent) {
var string = getRawData().length == 0 && !hasMetaAttribute(IS_TEXT) ? "<null>" : new String(getRawData(), StandardCharsets.UTF_8);
return (hasMetaAttribute(IS_TEXT) ? "\"" : "") + string + (hasMetaAttribute(IS_TEXT) ? "\"" : "") + " " + metaToString();
var string = getRawData().length == 0 && !hasMetaAttribute(IS_TEXT)
? "<null>"
: new String(getRawData(), StandardCharsets.UTF_8);
return (hasMetaAttribute(IS_TEXT) ? "\"" : "") + string + (hasMetaAttribute(IS_TEXT) ? "\"" : "") + " "
+ metaToString();
}
@Override

View File

@@ -5,7 +5,6 @@ import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public abstract class TupleNode extends DataStructureNode {
public static Builder builder() {
@@ -46,13 +45,15 @@ public abstract class TupleNode extends DataStructureNode {
public String toString(int indent) {
var is = " ".repeat(indent);
var start = "{\n";
var kvs = getKeyValuePairs().stream().map(kv -> {
if (kv.key() == null) {
return is + " " + kv.value().toString(indent + 1) + "\n";
} else {
return is + " " + kv.key() + "=" + kv.value().toString(indent + 1) + "\n";
}
}).collect(Collectors.joining());
var kvs = getKeyValuePairs().stream()
.map(kv -> {
if (kv.key() == null) {
return is + " " + kv.value().toString(indent + 1) + "\n";
} else {
return is + " " + kv.key() + "=" + kv.value().toString(indent + 1) + "\n";
}
})
.collect(Collectors.joining());
var end = is + "}";
return start + kvs + end;
}
@@ -65,8 +66,9 @@ public abstract class TupleNode extends DataStructureNode {
if (!(o instanceof TupleNode that)) {
return false;
}
var toReturn = getKeyNames().equals(that.getKeyNames()) && getNodes().equals(that.getNodes()) &&
Objects.equals(getMetaAttributes(), that.getMetaAttributes());
var toReturn = getKeyNames().equals(that.getKeyNames())
&& getNodes().equals(that.getNodes())
&& Objects.equals(getMetaAttributes(), that.getMetaAttributes());
// Useful for debugging
if (toReturn == false) {
@@ -98,11 +100,11 @@ public abstract class TupleNode extends DataStructureNode {
public TupleNode build() {
boolean hasKeys = entries.stream().anyMatch(kv -> kv.key() != null);
return hasKeys ? TupleNode.of(
entries.stream().map(KeyValue::key).toList(),
entries.stream().map(KeyValue::value).toList()
) :
TupleNode.of(entries.stream().map(KeyValue::value).toList());
return hasKeys
? TupleNode.of(
entries.stream().map(KeyValue::key).toList(),
entries.stream().map(KeyValue::value).toList())
: TupleNode.of(entries.stream().map(KeyValue::value).toList());
}
}
}

View File

@@ -11,32 +11,7 @@ import java.util.Objects;
public abstract class ValueNode extends DataStructureNode {
protected ValueNode() {
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ValueNode that)) {
return false;
}
var toReturn = Arrays.equals(getRawData(), that.getRawData()) && Objects.equals(getMetaAttributes(), that.getMetaAttributes());
// Useful for debugging
if (toReturn == false) {
return false;
}
return toReturn;
}
@Override
public int hashCode() {
return Arrays.hashCode(getRawData()) + Objects.hash(getMetaAttributes());
}
protected ValueNode() {}
public static ValueNode nullValue() {
return new SimpleValueNode(new byte[0]).tag(IS_NULL).asValue();
@@ -79,6 +54,7 @@ public abstract class ValueNode extends DataStructureNode {
created.tag(IS_FLOATING_POINT);
return created;
}
public static ValueNode ofBoolean(Boolean bool) {
var created = of(bool);
created.tag(IS_BOOLEAN);
@@ -93,6 +69,30 @@ public abstract class ValueNode extends DataStructureNode {
return of(o.toString().getBytes(StandardCharsets.UTF_8));
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ValueNode that)) {
return false;
}
var toReturn = Arrays.equals(getRawData(), that.getRawData())
&& Objects.equals(getMetaAttributes(), that.getMetaAttributes());
// Useful for debugging
if (toReturn == false) {
return false;
}
return toReturn;
}
@Override
public int hashCode() {
return Arrays.hashCode(getRawData()) + Objects.hash(getMetaAttributes());
}
@Override
public final int asInt() {
return Integer.parseInt(asString());
@@ -114,5 +114,4 @@ public abstract class ValueNode extends DataStructureNode {
}
public abstract byte[] getRawData();
}

View File

@@ -2,15 +2,11 @@ package io.xpipe.core.data.type;
public interface DataTypeVisitor {
default void onValue(ValueType type) {
}
default void onValue(ValueType type) {}
default void onTuple(TupleType type) {
}
default void onTuple(TupleType type) {}
default void onArray(ArrayType type) {
}
default void onArray(ArrayType type) {}
default void onWildcard(WildcardType type) {
}
default void onWildcard(WildcardType type) {}
}

View File

@@ -41,9 +41,7 @@ public class DataTypeVisitors {
* Creates a visitor that allows for visiting possible recursive columns of table.
*/
public static DataTypeVisitor table(
Consumer<String> newTuple,
Runnable endTuple,
BiConsumer<String, DataStructureNodePointer> newValue) {
Consumer<String> newTuple, Runnable endTuple, BiConsumer<String, DataStructureNodePointer> newValue) {
return new DataTypeVisitor() {
private final Stack<TupleType> tuples = new Stack<>();
private final Stack<Integer> keyIndices = new Stack<>();

View File

@@ -17,6 +17,8 @@ import java.util.Optional;
@Value
public class WildcardType extends DataType {
private WildcardType() {}
/**
* Creates a new instance.
*/
@@ -24,8 +26,6 @@ public class WildcardType extends DataType {
return new WildcardType();
}
private WildcardType() {}
@Override
public String getName() {
return "wildcard";

View File

@@ -7,27 +7,19 @@ import java.util.Map;
public interface TypedDataStreamCallback {
default void onValue(byte[] data, Map<Integer, String> metaAttributes) {
}
default void onValue(byte[] data, Map<Integer, String> metaAttributes) {}
default void onGenericNode(DataStructureNode node) {
}
default void onGenericNode(DataStructureNode node) {}
default void onTupleBegin(TupleType type) {
}
default void onTupleBegin(TupleType type) {}
default void onTupleEnd(Map<Integer, String> metaAttributes) {
}
default void onTupleEnd(Map<Integer, String> metaAttributes) {}
default void onArrayBegin(int size) {
}
default void onArrayBegin(int size) {}
default void onArrayEnd(Map<Integer, String> metaAttributes) {
}
default void onArrayEnd(Map<Integer, String> metaAttributes) {}
default void onNodeBegin() {
}
default void onNodeBegin() {}
default void onNodeEnd() {
}
default void onNodeEnd() {}
}

View File

@@ -1,9 +1,9 @@
package io.xpipe.core.data.typed;
import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.DataStructureNodeIO;
import io.xpipe.core.data.generic.GenericDataStreamParser;
import io.xpipe.core.data.generic.GenericDataStructureNodeReader;
import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.DataStructureNodeIO;
import io.xpipe.core.data.type.ArrayType;
import io.xpipe.core.data.type.DataType;
import io.xpipe.core.data.type.TupleType;
@@ -21,7 +21,7 @@ public class TypedDataStreamParser {
this.dataType = dataType;
}
private boolean hasNext(InputStream in) throws IOException {
private boolean hasNext(InputStream in) throws IOException {
var b = in.read();
if (b == -1) {
return false;
@@ -34,7 +34,8 @@ public class TypedDataStreamParser {
return true;
}
public void parseStructures(InputStream in, TypedAbstractReader cb, Consumer<DataStructureNode> consumer) throws IOException {
public void parseStructures(InputStream in, TypedAbstractReader cb, Consumer<DataStructureNode> consumer)
throws IOException {
while (hasNext(in)) {
cb.onNodeBegin();
parse(in, cb, dataType);

View File

@@ -12,20 +12,13 @@ import java.util.Stack;
public class TypedDataStructureNodeReader implements TypedAbstractReader {
public static TypedDataStructureNodeReader of(DataType type) {
return new TypedDataStructureNodeReader(type);
}
private DataStructureNode readNode;
private final Stack<List<DataStructureNode>> children;
private final Stack<DataStructureNode> nodes;
private int arrayDepth;
private final List<DataType> flattened;
private DataStructureNode readNode;
private int arrayDepth;
private DataType expectedType;
private int currentExpectedTypeIndex;
private TypedDataStructureNodeReader(DataType type) {
flattened = new ArrayList<>();
type.visit(DataTypeVisitors.flatten(flattened::add));
@@ -34,6 +27,10 @@ public class TypedDataStructureNodeReader implements TypedAbstractReader {
expectedType = flattened.get(0);
}
public static TypedDataStructureNodeReader of(DataType type) {
return new TypedDataStructureNodeReader(type);
}
@Override
public void onNodeBegin() {
if (nodes.size() != 0 || children.size() != 0) {
@@ -134,7 +131,8 @@ public class TypedDataStructureNodeReader implements TypedAbstractReader {
private void moveExpectedType(boolean force) {
if (!isInArray() || force) {
currentExpectedTypeIndex++;
expectedType = currentExpectedTypeIndex == flattened.size() ? null : flattened.get(currentExpectedTypeIndex);
expectedType =
currentExpectedTypeIndex == flattened.size() ? null : flattened.get(currentExpectedTypeIndex);
}
}

View File

@@ -20,7 +20,8 @@ public class BaseQueryElement extends DialogElement {
protected String value;
@JsonCreator
public BaseQueryElement(String description, boolean newLine, boolean required, boolean secret, boolean quiet, String value) {
public BaseQueryElement(
String description, boolean newLine, boolean required, boolean secret, boolean quiet, String value) {
this.description = description;
this.newLine = newLine;
this.required = required;

View File

@@ -18,6 +18,18 @@ public class ChoiceElement extends DialogElement {
private int selected;
@JsonCreator
public ChoiceElement(String description, List<Choice> elements, boolean required, int selected) {
if (elements.stream().allMatch(Choice::isDisabled)) {
throw new IllegalArgumentException("All choices are disabled");
}
this.description = description;
this.elements = elements;
this.required = required;
this.selected = selected;
}
@Override
public boolean requiresExplicitUserInput() {
return required && selected == -1;
@@ -42,7 +54,8 @@ public class ChoiceElement extends DialogElement {
}
for (int i = 0; i < elements.size(); i++) {
if (elements.get(i).getCharacter() != null && elements.get(i).getCharacter().equals(c)) {
if (elements.get(i).getCharacter() != null
&& elements.get(i).getCharacter().equals(c)) {
selected = i;
return true;
}
@@ -59,18 +72,6 @@ public class ChoiceElement extends DialogElement {
return false;
}
@JsonCreator
public ChoiceElement(String description, List<Choice> elements, boolean required, int selected) {
if (elements.stream().allMatch(Choice::isDisabled)) {
throw new IllegalArgumentException("All choices are disabled");
}
this.description = description;
this.elements = elements;
this.required = required;
this.selected = selected;
}
public List<Choice> getElements() {
return elements;
}

View File

@@ -2,7 +2,9 @@ package io.xpipe.core.dialog;
import io.xpipe.core.util.SecretValue;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -24,6 +26,10 @@ import java.util.function.Supplier;
*/
public abstract class Dialog {
private final List<Consumer<?>> completion = new ArrayList<>();
protected Object eval;
private Supplier<?> evaluation;
/**
* Creates an empty dialogue. This dialogue completes immediately and does not handle any questions or answers.
*/
@@ -43,33 +49,6 @@ public abstract class Dialog {
};
}
public static class Choice extends Dialog {
private final ChoiceElement element;
private Choice(String description, List<io.xpipe.core.dialog.Choice> elements, boolean required, int selected) {
this.element = new ChoiceElement(description, elements, required, selected);
}
@Override
public DialogElement start() throws Exception {
return element;
}
@Override
protected DialogElement next(String answer) throws Exception {
if (element.apply(answer)) {
return null;
}
return element;
}
private int getSelected() {
return element.getSelected();
}
}
/**
* Creates a choice dialogue.
*
@@ -78,7 +57,8 @@ public abstract class Dialog {
* @param required signals whether a choice is required or can be left empty
* @param selected the selected element index
*/
public static Dialog.Choice choice(String description, List<io.xpipe.core.dialog.Choice> elements, boolean required, int selected) {
public static Dialog.Choice choice(
String description, List<io.xpipe.core.dialog.Choice> elements, boolean required, int selected) {
Dialog.Choice c = new Dialog.Choice(description, elements, required, selected);
c.evaluateTo(c::getSelected);
return c;
@@ -94,8 +74,11 @@ public abstract class Dialog {
* @param vals the range of possible elements
*/
@SafeVarargs
public static <T> Dialog.Choice choice(String description, Function<T, String> toString, boolean required, T def, T... vals) {
var elements = Arrays.stream(vals).map(v -> new io.xpipe.core.dialog.Choice(null, toString.apply(v))).toList();
public static <T> Dialog.Choice choice(
String description, Function<T, String> toString, boolean required, T def, T... vals) {
var elements = Arrays.stream(vals)
.map(v -> new io.xpipe.core.dialog.Choice(null, toString.apply(v)))
.toList();
var index = Arrays.asList(vals).indexOf(def);
if (def != null && index == -1) {
throw new IllegalArgumentException("Default value " + def.toString() + " is not in possible values");
@@ -111,38 +94,6 @@ public abstract class Dialog {
return c;
}
public static class Query extends Dialog {
private final QueryElement element;
private <T> Query(String description, boolean newLine, boolean required, boolean quiet, T value, QueryConverter<T> converter, boolean hidden) {
this.element = new QueryElement(description, newLine, required, quiet, value, converter, hidden);
}
@Override
public DialogElement start() throws Exception {
return element;
}
@Override
protected DialogElement next(String answer) throws Exception {
if (element.requiresExplicitUserInput() && (answer == null || answer.trim()
.length() == 0)) {
return element;
}
if (element.apply(answer)) {
return null;
}
return element;
}
private <T> T getConvertedValue() {
return element.getConvertedValue();
}
}
/**
* Creates a simple query dialogue.
*
@@ -155,7 +106,13 @@ public abstract class Dialog {
* @param value the default value
* @param converter the converter
*/
public static <T> Dialog.Query query(String description, boolean newLine, boolean required, boolean quiet, T value, QueryConverter<T> converter) {
public static <T> Dialog.Query query(
String description,
boolean newLine,
boolean required,
boolean quiet,
T value,
QueryConverter<T> converter) {
var q = new <T>Dialog.Query(description, newLine, required, quiet, value, converter, false);
q.evaluateTo(q::getConvertedValue);
return q;
@@ -201,8 +158,7 @@ public abstract class Dialog {
DialogElement currentElement = ds[current].receive(answer);
if (currentElement == null) {
DialogElement next = null;
while (current < ds.length - 1 && (next = ds[++current].start()) == null) {
}
while (current < ds.length - 1 && (next = ds[++current].start()) == null) {}
;
return next;
}
@@ -218,7 +174,6 @@ public abstract class Dialog {
public static <T> Dialog repeatIf(Dialog d, Predicate<T> shouldRepeat) {
return new Dialog() {
@Override
public DialogElement start() throws Exception {
eval = null;
@@ -272,11 +227,6 @@ public abstract class Dialog {
return of(new BusyElement());
}
public static interface FailableSupplier<T> {
T get() throws Exception;
}
/**
* Creates a dialogue that will only evaluate when needed.
* This allows a dialogue to incorporate completion information about a previous dialogue.
@@ -305,7 +255,6 @@ public abstract class Dialog {
private static Dialog of(DialogElement e) {
return new Dialog() {
@Override
public DialogElement start() throws Exception {
eval = null;
@@ -323,7 +272,6 @@ public abstract class Dialog {
};
}
/**
* Creates a dialogue that will not be executed if the condition is true.
*/
@@ -393,7 +341,12 @@ public abstract class Dialog {
* @param selected the index of the element that is selected by default
* @param c the dialogue index mapping function
*/
public static Dialog fork(String description, List<io.xpipe.core.dialog.Choice> elements, boolean required, int selected, Function<Integer, Dialog> c) {
public static Dialog fork(
String description,
List<io.xpipe.core.dialog.Choice> elements,
boolean required,
int selected,
Function<Integer, Dialog> c) {
var choice = new ChoiceElement(description, elements, required, selected);
return new Dialog() {
@@ -427,13 +380,9 @@ public abstract class Dialog {
};
}
protected Object eval;
private Supplier<?> evaluation;
private final List<Consumer<?>> completion = new ArrayList<>();
/* TODO: Implement automatic completion mechanism for start as well
* In case start returns null, the completion is not automatically done.
* */
* In case start returns null, the completion is not automatically done.
* */
public abstract DialogElement start() throws Exception;
public Dialog evaluateTo(Dialog d) {
@@ -493,4 +442,75 @@ public abstract class Dialog {
}
protected abstract DialogElement next(String answer) throws Exception;
public static interface FailableSupplier<T> {
T get() throws Exception;
}
public static class Choice extends Dialog {
private final ChoiceElement element;
private Choice(String description, List<io.xpipe.core.dialog.Choice> elements, boolean required, int selected) {
this.element = new ChoiceElement(description, elements, required, selected);
}
@Override
public DialogElement start() throws Exception {
return element;
}
@Override
protected DialogElement next(String answer) throws Exception {
if (element.apply(answer)) {
return null;
}
return element;
}
private int getSelected() {
return element.getSelected();
}
}
public static class Query extends Dialog {
private final QueryElement element;
private <T> Query(
String description,
boolean newLine,
boolean required,
boolean quiet,
T value,
QueryConverter<T> converter,
boolean hidden) {
this.element = new QueryElement(description, newLine, required, quiet, value, converter, hidden);
}
@Override
public DialogElement start() throws Exception {
return element;
}
@Override
protected DialogElement next(String answer) throws Exception {
if (element.requiresExplicitUserInput()
&& (answer == null || answer.trim().length() == 0)) {
return element;
}
if (element.apply(answer)) {
return null;
}
return element;
}
private <T> T getConvertedValue() {
return element.getConvertedValue();
}
}
}

View File

@@ -5,8 +5,7 @@ package io.xpipe.core.dialog;
*/
public class DialogCancelException extends Exception {
public DialogCancelException() {
}
public DialogCancelException() {}
public DialogCancelException(String message) {
super(message);
@@ -20,7 +19,8 @@ public class DialogCancelException extends Exception {
super(cause);
}
public DialogCancelException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
public DialogCancelException(
String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@@ -23,7 +23,6 @@ public abstract class QueryConverter<T> {
}
};
public static final QueryConverter<StreamCharset> CHARSET = new QueryConverter<StreamCharset>() {
@Override
protected StreamCharset fromString(String s) {
@@ -60,26 +59,27 @@ public abstract class QueryConverter<T> {
}
};
public static final QueryConverter<Map.Entry<String, String>> HTTP_HEADER = new QueryConverter<Map.Entry<String, String>>() {
@Override
protected Map.Entry<String, String> fromString(String s) {
if (!s.contains(":")) {
throw new IllegalArgumentException("Missing colon");
}
public static final QueryConverter<Map.Entry<String, String>> HTTP_HEADER =
new QueryConverter<Map.Entry<String, String>>() {
@Override
protected Map.Entry<String, String> fromString(String s) {
if (!s.contains(":")) {
throw new IllegalArgumentException("Missing colon");
}
var split = s.split(":");
if (split.length != 2) {
throw new IllegalArgumentException("Too many colons");
}
var split = s.split(":");
if (split.length != 2) {
throw new IllegalArgumentException("Too many colons");
}
return new AbstractMap.SimpleEntry<>(split[0].trim(), split[1].trim());
}
return new AbstractMap.SimpleEntry<>(split[0].trim(), split[1].trim());
}
@Override
protected String toString(Map.Entry<String, String> value) {
return value.getKey() + ": " + value.getValue();
}
};
@Override
protected String toString(Map.Entry<String, String> value) {
return value.getKey() + ": " + value.getValue();
}
};
public static final QueryConverter<URI> URI = new QueryConverter<URI>() {
@Override
@@ -141,9 +141,7 @@ public abstract class QueryConverter<T> {
@Override
protected String toString(Boolean value) {
return value ?
"yes" :
"no";
return value ? "yes" : "no";
}
};

View File

@@ -7,7 +7,14 @@ public class QueryElement extends BaseQueryElement {
private final QueryConverter<?> converter;
public <T> QueryElement(String description, boolean newLine, boolean required, boolean quiet, T value, QueryConverter<T> converter, boolean hidden) {
public <T> QueryElement(
String description,
boolean newLine,
boolean required,
boolean quiet,
T value,
QueryConverter<T> converter,
boolean hidden) {
super(description, newLine, required, hidden, quiet, value != null ? converter.toString(value) : null);
this.converter = converter;
}

View File

@@ -50,5 +50,3 @@ public abstract class BatchTableWriteConnection implements TableWriteConnection
protected abstract DataStructureNodeAcceptor<ArrayNode> writeBatchLinesAcceptor();
}

View File

@@ -37,7 +37,6 @@ public class BinarySource extends RawDataSource<StreamDataStore> {
};
}
@Override
protected RawReadConnection newReadConnection() {
return new RawReadConnection() {

View File

@@ -48,8 +48,7 @@ public class LimitTableReadConnection implements TableReadConnection {
}
count++;
var returned = lineAcceptor
.accept(node);
var returned = lineAcceptor.accept(node);
localCounter.getAndIncrement();
return returned;

View File

@@ -9,14 +9,12 @@ import io.xpipe.core.source.TableWriteConnection;
public class PreservingTableWriteConnection extends PreservingWriteConnection implements TableWriteConnection {
public PreservingTableWriteConnection(DataSource<?> source, DataSourceConnection connection,
boolean append
) {
public PreservingTableWriteConnection(DataSource<?> source, DataSourceConnection connection, boolean append) {
super(DataSourceType.TABLE, source, append, connection);
}
@Override
public DataStructureNodeAcceptor<TupleNode> writeLinesAcceptor() {
return ((TableWriteConnection)connection).writeLinesAcceptor();
return ((TableWriteConnection) connection).writeLinesAcceptor();
}
}

View File

@@ -7,10 +7,7 @@ import io.xpipe.core.source.TextWriteConnection;
public class PreservingTextWriteConnection extends PreservingWriteConnection implements TextWriteConnection {
public PreservingTextWriteConnection(
DataSource<?> source, DataSourceConnection connection,
boolean append
) {
public PreservingTextWriteConnection(DataSource<?> source, DataSourceConnection connection, boolean append) {
super(DataSourceType.TEXT, source, append, connection);
}

View File

@@ -9,12 +9,13 @@ import java.nio.file.Files;
public class PreservingWriteConnection implements DataSourceConnection {
protected final DataSourceConnection connection;
private final DataSourceType type;
private final DataSource<?> source;
private final boolean append ;
protected final DataSourceConnection connection;
private final boolean append;
public PreservingWriteConnection(DataSourceType type, DataSource<?> source, boolean append, DataSourceConnection connection) {
public PreservingWriteConnection(
DataSourceType type, DataSource<?> source, boolean append, DataSourceConnection connection) {
this.type = type;
this.source = source;
this.append = append;
@@ -26,13 +27,13 @@ public class PreservingWriteConnection implements DataSourceConnection {
var nativeStore = FileStore.local(temp);
var nativeSource = DataSource.createInternalDataSource(type, nativeStore);
if (source.getStore().canOpen()) {
try (var in = source.openReadConnection(); var out = nativeSource.openWriteConnection()) {
try (var in = source.openReadConnection();
var out = nativeSource.openWriteConnection()) {
in.forward(out);
}
;
}
connection.init();
if (source.getStore().canOpen()) {
@@ -45,5 +46,4 @@ public class PreservingWriteConnection implements DataSourceConnection {
public void close() throws Exception {
connection.close();
}
}

View File

@@ -24,7 +24,6 @@ public class TextReadConnection extends StreamReadConnection implements io.xpipe
return bufferedReader.lines();
}
@Override
public void close() throws Exception {
bufferedReader.close();

View File

@@ -14,7 +14,7 @@ import lombok.extern.jackson.Jacksonized;
@JsonTypeName("text")
@SuperBuilder
@Jacksonized
public final class TextSource extends TextDataSource<StreamDataStore> implements Charsettable {
public final class TextSource extends TextDataSource<StreamDataStore> implements Charsettable {
private final StreamCharset charset;
private final NewLine newLine;

View File

@@ -13,6 +13,6 @@ public class XpbsWriteConnection extends StreamWriteConnection implements Struct
@Override
public void write(DataStructureNode node) throws Exception {
GenericDataStreamWriter.writeStructure(outputStream,node);
GenericDataStreamWriter.writeStructure(outputStream, node);
}
}

View File

@@ -21,6 +21,15 @@ import java.util.concurrent.atomic.AtomicReference;
public class XpbtReadConnection implements TableReadConnection {
private final StreamDataStore store;
private TupleType dataType;
private InputStream inputStream;
private TypedDataStreamParser parser;
private boolean empty;
protected XpbtReadConnection(StreamDataStore store) {
this.store = store;
}
@Override
public void init() throws Exception {
this.inputStream = store.openBufferedInput();
@@ -36,8 +45,8 @@ public class XpbtReadConnection implements TableReadConnection {
this.inputStream.skip(headerLength + 1);
List<String> names = JacksonMapper.newMapper()
.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE)
.readerFor(new TypeReference<List<String>>() {
}).readValue(header);
.readerFor(new TypeReference<List<String>>() {})
.readValue(header);
TupleType dataType = TupleType.tableType(names);
this.dataType = dataType;
this.parser = new TypedDataStreamParser(dataType);
@@ -48,16 +57,6 @@ public class XpbtReadConnection implements TableReadConnection {
inputStream.close();
}
private TupleType dataType;
private final StreamDataStore store;
private InputStream inputStream;
private TypedDataStreamParser parser;
private boolean empty;
protected XpbtReadConnection(StreamDataStore store) {
this.store = store;
}
@Override
public TupleType getDataType() {
return dataType;

View File

@@ -13,8 +13,6 @@ import lombok.extern.jackson.Jacksonized;
@Jacksonized
public class XpbtSource extends TableDataSource<StreamDataStore> {
@Override
protected TableWriteConnection newWriteConnection() {
return new XpbtWriteConnection(store);

View File

@@ -58,7 +58,8 @@ public class XpbtWriteConnection implements TableWriteConnection {
try (JsonGenerator g = f.createGenerator(writer)
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
.setPrettyPrinter(new DefaultPrettyPrinter())) {
JacksonMapper.newMapper().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
JacksonMapper.newMapper()
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
.writeValue(g, tupleNode.getKeyNames());
writer.append("\n");
}

View File

@@ -14,9 +14,9 @@ public interface CollectionReadConnection extends DataSourceReadConnection {
try (var tCon = (CollectionWriteConnection) con) {
tCon.init();
listEntries().forEach(s -> {
// try (var subCon = open(s)) {
// ((CollectionWriteConnection) con).write(s, subCon);
// }
// try (var subCon = open(s)) {
// ((CollectionWriteConnection) con).write(s, subCon);
// }
});
}
}

View File

@@ -22,22 +22,23 @@ import java.util.Optional;
* This instance is only valid in combination with its associated data store instance.
*/
@SuperBuilder
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
property = "type"
)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
public abstract class DataSource<DS extends DataStore> extends JacksonizedValue {
protected DS store;
public static DataSource<?> createInternalDataSource(DataSourceType t, DataStore store) {
try {
return switch (t) {
case TABLE -> XpbtSource.builder().store(store.asNeeded()).build();
case TABLE -> XpbtSource.builder().store(store.asNeeded()).build();
case STRUCTURE -> null;
case TEXT -> TextSource.builder().store(store.asNeeded()).newLine(NewLine.LF).charset(
StreamCharset.UTF8).build();
case TEXT -> TextSource.builder()
.store(store.asNeeded())
.newLine(NewLine.LF)
.charset(StreamCharset.UTF8)
.build();
case RAW -> null;
//TODO
// TODO
case COLLECTION -> null;
};
} catch (Exception ex) {
@@ -45,9 +46,6 @@ public abstract class DataSource<DS extends DataStore> extends JacksonizedValue
}
}
protected DS store;
public void test() throws Exception {
store.validate();
}
@@ -68,7 +66,6 @@ public abstract class DataSource<DS extends DataStore> extends JacksonizedValue
return WriteMode.values();
}
public DataFlow getFlow() {
if (store == null) {
return null;

View File

@@ -49,7 +49,8 @@ public class DataSourceId {
throw new IllegalArgumentException("Trimmed collection name is empty");
}
if (collectionName != null && collectionName.contains("" + SEPARATOR)) {
throw new IllegalArgumentException("Separator character " + SEPARATOR + " is not allowed in the collection name");
throw new IllegalArgumentException(
"Separator character " + SEPARATOR + " is not allowed in the collection name");
}
if (entryName == null) {
@@ -59,7 +60,8 @@ public class DataSourceId {
throw new IllegalArgumentException("Trimmed entry name is empty");
}
if (entryName.contains("" + SEPARATOR)) {
throw new IllegalArgumentException("Separator character " + SEPARATOR + " is not allowed in the entry name");
throw new IllegalArgumentException(
"Separator character " + SEPARATOR + " is not allowed in the entry name");
}
return new DataSourceId(collectionName, entryName);

View File

@@ -23,6 +23,61 @@ public abstract class DataSourceInfo {
public abstract DataSourceType getType();
/**
* Casts this instance to a table info.
*/
public Table asTable() {
if (!getType().equals(DataSourceType.TABLE)) {
throw new IllegalStateException("Not a table");
}
return (Table) this;
}
/**
* Casts this instance to a structure info.
*/
public Structure asStructure() {
if (!getType().equals(DataSourceType.STRUCTURE)) {
throw new IllegalStateException("Not a structure");
}
return (Structure) this;
}
/**
* Casts this instance to a text info.
*/
public Text asText() {
if (!getType().equals(DataSourceType.TEXT)) {
throw new IllegalStateException("Not a text");
}
return (Text) this;
}
/**
* Casts this instance to a raw info.
*/
public Raw asRaw() {
if (!getType().equals(DataSourceType.RAW)) {
throw new IllegalStateException("Not raw");
}
return (Raw) this;
}
/**
* Casts this instance to a collection info.
*/
public Collection asCollection() {
if (!getType().equals(DataSourceType.COLLECTION)) {
throw new IllegalStateException("Not a collection");
}
return (Collection) this;
}
@EqualsAndHashCode(callSuper = false)
@Value
@JsonTypeName("table")
@@ -101,7 +156,6 @@ public abstract class DataSourceInfo {
}
}
@EqualsAndHashCode(callSuper = false)
@Value
@JsonTypeName("raw")
@@ -118,59 +172,4 @@ public abstract class DataSourceInfo {
return DataSourceType.RAW;
}
}
/**
* Casts this instance to a table info.
*/
public Table asTable() {
if (!getType().equals(DataSourceType.TABLE)) {
throw new IllegalStateException("Not a table");
}
return (Table) this;
}
/**
* Casts this instance to a structure info.
*/
public Structure asStructure() {
if (!getType().equals(DataSourceType.STRUCTURE)) {
throw new IllegalStateException("Not a structure");
}
return (Structure) this;
}
/**
* Casts this instance to a text info.
*/
public Text asText() {
if (!getType().equals(DataSourceType.TEXT)) {
throw new IllegalStateException("Not a text");
}
return (Text) this;
}
/**
* Casts this instance to a raw info.
*/
public Raw asRaw() {
if (!getType().equals(DataSourceType.RAW)) {
throw new IllegalStateException("Not raw");
}
return (Raw) this;
}
/**
* Casts this instance to a collection info.
*/
public Collection asCollection() {
if (!getType().equals(DataSourceType.COLLECTION)) {
throw new IllegalStateException("Not a collection");
}
return (Collection) this;
}
}

View File

@@ -65,14 +65,10 @@ public interface DataSourceReference {
return new Name(s.trim());
}
enum Type {
ID,
NAME,
LATEST
}
Type getType();
DataSourceId getId();
String getName();
/**
@@ -82,6 +78,12 @@ public interface DataSourceReference {
String toString();
enum Type {
ID,
NAME,
LATEST
}
/**
* A wrapper class for {@link DataSourceId} instances.
*/

View File

@@ -7,7 +7,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* This distinction is necessary as the general workflow differs for each type.
*/
public enum DataSourceType {
@JsonProperty("table")
TABLE,

View File

@@ -4,10 +4,10 @@ import java.io.OutputStream;
public interface RawReadConnection extends DataSourceReadConnection {
byte[] readBytes(int max) throws Exception;
int BUFFER_SIZE = 8192;
byte[] readBytes(int max) throws Exception;
default void forwardBytes(OutputStream out, int maxBytes) throws Exception {
if (maxBytes == 0) {
return;

View File

@@ -9,10 +9,10 @@ import java.io.Reader;
public abstract class StreamReadConnection implements DataSourceReadConnection {
protected final StreamDataStore store;
private final StreamCharset charset;
protected InputStream inputStream;
protected Reader reader;
private final StreamCharset charset;
protected final StreamDataStore store;
public StreamReadConnection(StreamDataStore store, StreamCharset charset) {
this.store = store;

View File

@@ -9,8 +9,8 @@ import java.io.OutputStreamWriter;
public class StreamWriteConnection implements DataSourceConnection {
protected final StreamDataStore store;
protected OutputStream outputStream;
private final StreamCharset charset;
protected OutputStream outputStream;
protected OutputStreamWriter writer;
public StreamWriteConnection(StreamDataStore store, StreamCharset charset) {
@@ -27,8 +27,7 @@ public class StreamWriteConnection implements DataSourceConnection {
outputStream = store.openOutput();
if (charset != null) {
if (charset.hasByteOrderMark()) {
outputStream
.write(charset.getByteOrderMark());
outputStream.write(charset.getByteOrderMark());
}
writer = new OutputStreamWriter(outputStream, charset.getCharset());
}

View File

@@ -1,9 +1,8 @@
package io.xpipe.core.source;
import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.DataStructureNode;
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;

View File

@@ -1,8 +1,8 @@
package io.xpipe.core.source;
import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.DataStructureNodeAcceptor;
import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.TupleNode;
/**

View File

@@ -50,7 +50,6 @@ public abstract class TextDataSource<DS extends DataStore> extends DataSource<DS
return con;
}
@Override
public final TextWriteConnection openPrependingWriteConnection() throws Exception {
var con = newPrependingWriteConnection();
@@ -64,13 +63,9 @@ public abstract class TextDataSource<DS extends DataStore> extends DataSource<DS
return new PreservingTextWriteConnection(this, newWriteConnection(), true);
}
protected TextWriteConnection newPrependingWriteConnection() {
return new PreservingTextWriteConnection(this, newWriteConnection(), false);
}
protected abstract TextReadConnection newReadConnection();
}

View File

@@ -15,8 +15,8 @@ public interface TextReadConnection extends DataSourceReadConnection {
default void forward(DataSourceConnection con) throws Exception {
var tCon = (TextWriteConnection) con;
for (var it = lines().iterator(); it.hasNext(); ) {
tCon.writeLine(it.next());
}
for (var it = lines().iterator(); it.hasNext(); ) {
tCon.writeLine(it.next());
}
}
}

View File

@@ -10,11 +10,6 @@ public enum WriteMode {
@JsonProperty("prepend")
PREPEND(DataSource::openPrependingWriteConnection);
public static interface FailableFunction<T, R, E extends Throwable> {
R apply(T input) throws E;
}
private final FailableFunction<DataSource<?>, DataSourceConnection, Exception> connectionOpener;
WriteMode(FailableFunction<DataSource<?>, DataSourceConnection, Exception> connectionOpener) {
@@ -24,4 +19,8 @@ public enum WriteMode {
public DataSourceConnection open(DataSource<?> source) throws Exception {
return connectionOpener.apply(source);
}
public static interface FailableFunction<T, R, E extends Throwable> {
R apply(T input) throws E;
}
}

View File

@@ -6,7 +6,6 @@ public abstract class CollectionEntryDataStore implements FilenameStore, StreamD
private final String name;
private final DataStore collectionStore;
public CollectionEntryDataStore(boolean directory, String name, DataStore collectionStore) {
this.directory = directory;
this.name = name;

View File

@@ -3,7 +3,6 @@ package io.xpipe.core.store;
import com.fasterxml.jackson.annotation.JsonProperty;
public enum DataFlow {
@JsonProperty("input")
INPUT,
@JsonProperty("output")

View File

@@ -28,7 +28,6 @@ public interface DataStore {
return true;
}
/**
* Indicates whether this data store can only be accessed by the current running application.
* One example are standard in and standard out stores.
@@ -56,17 +55,14 @@ public interface DataStore {
*
* @throws Exception if any part of the validation went wrong
*/
default void validate() throws Exception {
}
default void validate() throws Exception {}
default void checkComplete() throws Exception {
}
default void checkComplete() throws Exception {}
default boolean delete() throws Exception {
return false;
}
/**
* Casts this instance to the required type without checking whether a cast is possible.
*/

View File

@@ -10,7 +10,6 @@ public class DataStoreFormatter {
return input;
}
public static String specialFormatHostName(String input) {
if (input.contains(":")) {
input = input.split(":")[0];

View File

@@ -19,6 +19,14 @@ import java.nio.file.Path;
@Getter
public class FileStore extends JacksonizedValue implements FilenameStore, StreamDataStore {
MachineFileStore machine;
String file;
public FileStore(MachineFileStore machine, String file) {
this.machine = machine;
this.file = file;
}
public static FileStore local(Path p) {
return new FileStore(new LocalStore(), p.toString());
}
@@ -30,14 +38,6 @@ public class FileStore extends JacksonizedValue implements FilenameStore, Stream
return new FileStore(new LocalStore(), p);
}
MachineFileStore machine;
String file;
public FileStore(MachineFileStore machine, String file) {
this.machine = machine;
this.file = file;
}
@Override
public void checkComplete() throws Exception {
if (machine == null) {
@@ -46,7 +46,6 @@ public class FileStore extends JacksonizedValue implements FilenameStore, Stream
if (file == null) {
throw new IllegalStateException("File is missing");
}
}
@Override
@@ -72,5 +71,4 @@ public class FileStore extends JacksonizedValue implements FilenameStore, Stream
}
return split[split.length - 1];
}
}

View File

@@ -15,8 +15,7 @@ public interface FilenameStore extends DataStore {
return Optional.of(i != -1 ? n.substring(0, i) : n);
}
default String getFileExtension() {
default String getFileExtension() {
var split = getFileName().split("[\\\\.]");
if (split.length == 0) {
return "";

View File

@@ -20,7 +20,6 @@ public class InMemoryStore extends JacksonizedValue implements StreamDataStore {
private byte[] value;
@JsonCreator
public InMemoryStore(byte[] value) {
this.value = value;
@@ -38,7 +37,7 @@ public class InMemoryStore extends JacksonizedValue implements StreamDataStore {
@Override
public OutputStream openOutput() throws Exception {
return new ByteArrayOutputStream(){
return new ByteArrayOutputStream() {
@Override
public void close() throws IOException {
super.close();

View File

@@ -39,5 +39,4 @@ public class LocalDirectoryDataStore implements DataStore {
public Path getPath() {
return file;
}
}

View File

@@ -22,7 +22,51 @@ public class LocalStore extends JacksonizedValue implements MachineFileStore, St
return true;
}
class LocalProcessControl extends ProcessControl {
@Override
public boolean exists(String file) {
return Files.exists(Path.of(file));
}
@Override
public void mkdirs(String file) throws Exception {
Files.createDirectories(Path.of(file).getParent());
}
@Override
public NewLine getNewLine() {
return ShellTypes.getDefault().getNewLine();
}
@Override
public InputStream openInput(String file) throws Exception {
var p = Path.of(file);
return Files.newInputStream(p);
}
@Override
public OutputStream openOutput(String file) throws Exception {
mkdirs(file);
var p = Path.of(file);
return Files.newOutputStream(p);
}
@Override
public ProcessControl prepareCommand(List<SecretValue> input, List<String> cmd, Integer timeout) {
return new LocalProcessControl(input, cmd, getEffectiveTimeOut(timeout));
}
@Override
public ProcessControl preparePrivilegedCommand(List<SecretValue> input, List<String> cmd, Integer timeOut)
throws Exception {
return new LocalProcessControl(input, cmd, getEffectiveTimeOut(timeOut));
}
@Override
public ShellType determineType() throws Exception {
return ShellTypes.getDefault();
}
class LocalProcessControl extends ProcessControl {
private final List<SecretValue> input;
private final Integer timeout;
@@ -38,7 +82,8 @@ public class LocalStore extends JacksonizedValue implements MachineFileStore, St
}
private InputStream createInputStream() {
var string = input.stream().map(secret -> secret.getSecretValue()).collect(Collectors.joining("\n")) + "\r\n";
var string =
input.stream().map(secret -> secret.getSecretValue()).collect(Collectors.joining("\n")) + "\r\n";
return new ByteArrayInputStream(string.getBytes(StandardCharsets.US_ASCII));
}
@@ -51,7 +96,7 @@ public class LocalStore extends JacksonizedValue implements MachineFileStore, St
charset = type.determineCharset(LocalStore.this);
var t = new Thread(() -> {
try (var inputStream = createInputStream()){
try (var inputStream = createInputStream()) {
process.getOutputStream().flush();
inputStream.transferTo(process.getOutputStream());
process.getOutputStream().close();
@@ -77,12 +122,12 @@ public class LocalStore extends JacksonizedValue implements MachineFileStore, St
return process.getInputStream();
}
@Override
public OutputStream getStdin() {
return process.getOutputStream();
}
@Override
public OutputStream getStdin() {
return process.getOutputStream();
}
@Override
@Override
public InputStream getStderr() {
return process.getErrorStream();
}
@@ -96,48 +141,4 @@ public class LocalStore extends JacksonizedValue implements MachineFileStore, St
return timeout;
}
}
@Override
public boolean exists(String file) {
return Files.exists(Path.of(file));
}
@Override
public void mkdirs(String file) throws Exception {
Files.createDirectories(Path.of(file).getParent());
}
@Override
public NewLine getNewLine() {
return ShellTypes.getDefault().getNewLine();
}
@Override
public InputStream openInput(String file) throws Exception {
var p = Path.of(file);
return Files.newInputStream(p);
}
@Override
public OutputStream openOutput(String file) throws Exception {
mkdirs(file);
var p = Path.of(file);
return Files.newOutputStream(p);
}
@Override
public ProcessControl prepareCommand(List<SecretValue> input, List<String> cmd, Integer timeout) {
return new LocalProcessControl(input, cmd, getEffectiveTimeOut(timeout));
}
@Override
public ProcessControl preparePrivilegedCommand(List<SecretValue> input, List<String> cmd, Integer timeOut) throws Exception {
return new LocalProcessControl(input, cmd, getEffectiveTimeOut(timeOut));
}
@Override
public ShellType determineType() throws Exception {
return ShellTypes.getDefault();
}
}

View File

@@ -68,6 +68,7 @@ public abstract class ProcessControl {
public abstract int waitFor() throws Exception;
public abstract InputStream getStdout();
public abstract OutputStream getStdin();
public abstract InputStream getStderr();

View File

@@ -1,6 +1,6 @@
package io.xpipe.core.store;
public class ProcessOutputException extends Exception{
public class ProcessOutputException extends Exception {
public ProcessOutputException() {
super();
}
@@ -17,7 +17,8 @@ public class ProcessOutputException extends Exception{
super(cause);
}
protected ProcessOutputException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
protected ProcessOutputException(
String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@@ -62,7 +62,8 @@ public interface ShellStore extends DataStore {
if (ec == 0 && !(read.get().isEmpty() && !readError.get().isEmpty())) {
return read.get().trim();
} else {
throw new ProcessOutputException("Command returned with " + ec + ": " + readError.get().trim());
throw new ProcessOutputException(
"Command returned with " + ec + ": " + readError.get().trim());
}
}

View File

@@ -13,12 +13,17 @@ import java.util.List;
public class ShellTypes {
public static final StandardShellStore.ShellType POWERSHELL = new PowerShell();
public static final StandardShellStore.ShellType CMD = new Cmd();
public static final StandardShellStore.ShellType SH = new Sh();
public static StandardShellStore.ShellType determine(ShellStore store) throws Exception {
var o = store.executeAndCheckOut(List.of(), List.of("echo", "$0"), null).strip();
if (!o.equals("$0")) {
return SH;
} else {
o = store.executeAndCheckOut(List.of(), List.of("(dir 2>&1 *`|echo CMD);&<# rem #>echo PowerShell"), null).trim();
o = store.executeAndCheckOut(List.of(), List.of("(dir 2>&1 *`|echo CMD);&<# rem #>echo PowerShell"), null)
.trim();
if (o.equals("PowerShell")) {
return POWERSHELL;
} else {
@@ -36,13 +41,6 @@ public class ShellTypes {
}
}
public static final StandardShellStore.ShellType POWERSHELL = new PowerShell();
public static final StandardShellStore.ShellType CMD = new Cmd();
public static final StandardShellStore.ShellType SH = new Sh();
public static StandardShellStore.ShellType getDefault() {
if (System.getProperty("os.name").startsWith("Windows")) {
return CMD;
@@ -51,16 +49,12 @@ public class ShellTypes {
}
}
public static StandardShellStore.ShellType[] getWindowsShells() {
return new StandardShellStore.ShellType[]{
CMD,
POWERSHELL
};
return new StandardShellStore.ShellType[] {CMD, POWERSHELL};
}
public static StandardShellStore.ShellType[] getLinuxShells() {
return new StandardShellStore.ShellType[]{SH};
return new StandardShellStore.ShellType[] {SH};
}
@JsonTypeName("cmd")
@@ -85,7 +79,8 @@ public class ShellTypes {
}
@Override
public ProcessControl prepareElevatedCommand(ShellStore st, List<SecretValue> in, List<String> cmd, Integer timeout, String pw) throws Exception {
public ProcessControl prepareElevatedCommand(
ShellStore st, List<SecretValue> in, List<String> cmd, Integer timeout, String pw) throws Exception {
var l = List.of("net", "session", ";", "if", "%errorLevel%", "!=", "0");
return st.prepareCommand(List.of(), l, timeout);
}
@@ -188,7 +183,8 @@ public class ShellTypes {
}
@Override
public ProcessControl prepareElevatedCommand(ShellStore st, List<SecretValue> in, List<String> cmd, Integer timeout, String pw) throws Exception {
public ProcessControl prepareElevatedCommand(
ShellStore st, List<SecretValue> in, List<String> cmd, Integer timeout, String pw) throws Exception {
var l = new ArrayList<>(cmd);
l.add(0, "sudo");
l.add(1, "-S");

View File

@@ -15,12 +15,55 @@ public interface StandardShellStore extends MachineFileStore, ShellStore {
return false;
}
public default NewLine getNewLine() throws Exception {
return determineType().getNewLine();
}
public abstract ShellType determineType() throws Exception;
public default String querySystemName() throws Exception {
var result = executeAndCheckOut(List.of(), determineType().getOperatingSystemNameCommand(), getTimeout());
return result.strip();
}
@Override
public default InputStream openInput(String file) throws Exception {
var type = determineType();
var cmd = type.createFileReadCommand(file);
var p = prepareCommand(List.of(), cmd, null);
p.start();
return p.getStdout();
}
@Override
public default OutputStream openOutput(String file) throws Exception {
return null;
// var type = determineType();
// var cmd = type.createFileWriteCommand(file);
// var p = prepare(cmd).redirectErrorStream(true);
// var proc = p.start();
// return proc.getOutputStream();
}
@Override
public default boolean exists(String file) throws Exception {
var type = determineType();
var cmd = type.createFileExistsCommand(file);
var p = prepareCommand(List.of(), cmd, null);
p.start();
return p.waitFor() == 0;
}
@Override
public default void mkdirs(String file) throws Exception {}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
public static interface ShellType {
List<String> switchTo(List<String> cmd);
default ProcessControl prepareElevatedCommand(ShellStore st, List<SecretValue> in, List<String> cmd, Integer timeout, String pw) throws Exception {
default ProcessControl prepareElevatedCommand(
ShellStore st, List<SecretValue> in, List<String> cmd, Integer timeout, String pw) throws Exception {
return st.prepareCommand(in, cmd, timeout);
}
@@ -40,50 +83,4 @@ public interface StandardShellStore extends MachineFileStore, ShellStore {
List<String> getOperatingSystemNameCommand();
}
public default NewLine getNewLine() throws Exception {
return determineType().getNewLine();
}
public abstract ShellType determineType() throws Exception;
public default String querySystemName() throws Exception {
var result = executeAndCheckOut(List.of(), determineType().getOperatingSystemNameCommand(), getTimeout());
return result.strip();
}
@Override
public default InputStream openInput(String file) throws Exception {
var type = determineType();
var cmd = type.createFileReadCommand(file);
var p = prepareCommand(List.of(), cmd, null);
p.start();
return p.getStdout();
}
@Override
public default OutputStream openOutput(String file) throws Exception {
return null;
// var type = determineType();
// var cmd = type.createFileWriteCommand(file);
// var p = prepare(cmd).redirectErrorStream(true);
// var proc = p.start();
// return proc.getOutputStream();
}
@Override
public default boolean exists(String file) throws Exception {
var type = determineType();
var cmd = type.createFileExistsCommand(file);
var p = prepareCommand(List.of(), cmd, null);
p.start();
return p.waitFor() == 0;
}
@Override
public default void mkdirs(String file) throws Exception {
}
}

View File

@@ -70,8 +70,7 @@ public class StdinDataStore extends JacksonizedValue implements StreamDataStore
}
@Override
public void close() throws IOException {
}
public void close() throws IOException {}
@Override
public synchronized void mark(int readlimit) {

View File

@@ -48,8 +48,7 @@ public class StdoutDataStore extends JacksonizedValue implements StreamDataStore
}
@Override
public void close() throws IOException {
}
public void close() throws IOException {}
};
}
}

View File

@@ -9,7 +9,6 @@ import java.io.OutputStream;
*/
public interface StreamDataStore extends DataStore {
/**
* Opens an input stream that can be used to read its data.
*/

View File

@@ -7,7 +7,6 @@ import lombok.extern.jackson.Jacksonized;
import java.io.InputStream;
import java.net.URL;
@JsonTypeName("url")
@SuperBuilder
@Jacksonized

View File

@@ -38,7 +38,6 @@ public class CoreJacksonModule extends SimpleModule {
context.registerSubtypes(
new NamedType(TextSource.class),
new NamedType(XpbtSource.class),
new NamedType(FileStore.class),
new NamedType(StdinDataStore.class),
new NamedType(StdoutDataStore.class),
@@ -47,27 +46,22 @@ public class CoreJacksonModule extends SimpleModule {
new NamedType(InMemoryStore.class),
new NamedType(LocalStore.class),
new NamedType(NamedStore.class),
new NamedType(ValueType.class),
new NamedType(TupleType.class),
new NamedType(ArrayType.class),
new NamedType(WildcardType.class),
new NamedType(ShellTypes.Cmd.class),
new NamedType(ShellTypes.PowerShell.class),
new NamedType(ShellTypes.Sh.class),
new NamedType(DataSourceInfo.Table.class),
new NamedType(DataSourceInfo.Structure.class),
new NamedType(DataSourceInfo.Text.class),
new NamedType(DataSourceInfo.Collection.class),
new NamedType(DataSourceInfo.Raw.class),
new NamedType(BaseQueryElement.class),
new NamedType(ChoiceElement.class),
new NamedType(BusyElement.class),
new NamedType(HeaderElement.class)
);
new NamedType(HeaderElement.class));
addSerializer(Charset.class, new CharsetSerializer());
addDeserializer(Charset.class, new CharsetDeserializer());
@@ -98,12 +92,6 @@ public class CoreJacksonModule extends SimpleModule {
}
}
public class NullSerializer extends JsonSerializer<Object> {
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeNull();
}
}
public static class NullDeserializer extends JsonDeserializer<DataSource> {
@Override
@@ -112,7 +100,6 @@ public class CoreJacksonModule extends SimpleModule {
}
}
public static class DataSourceReferenceSerializer extends JsonSerializer<DataSourceReference> {
@Override
@@ -133,8 +120,7 @@ public class CoreJacksonModule extends SimpleModule {
public static class CharsetSerializer extends JsonSerializer<Charset> {
@Override
public void serialize(Charset value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(Charset value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeString(value.name());
}
}
@@ -150,8 +136,7 @@ public class CoreJacksonModule extends SimpleModule {
public static class LocalPathSerializer extends JsonSerializer<Path> {
@Override
public void serialize(Path value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(Path value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeString(value.toString());
}
}
@@ -167,8 +152,7 @@ public class CoreJacksonModule extends SimpleModule {
public static class SecretSerializer extends JsonSerializer<SecretValue> {
@Override
public void serialize(SecretValue value, JsonGenerator jgen, SerializerProvider provider)
throws IOException {
public void serialize(SecretValue value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
jgen.writeString(value.getEncryptedValue());
}
}
@@ -184,11 +168,17 @@ public class CoreJacksonModule extends SimpleModule {
@JsonSerialize(as = Throwable.class)
public abstract static class ThrowableTypeMixIn {
@JsonIdentityInfo(generator= ObjectIdGenerators.StringIdGenerator.class, property="$id")
@JsonIdentityInfo(generator = ObjectIdGenerators.StringIdGenerator.class, property = "$id")
private Throwable cause;
}
@JsonSerialize(as = DataSourceReference.class)
public abstract static class DataSourceReferenceTypeMixIn {
public abstract static class DataSourceReferenceTypeMixIn {}
public class NullSerializer extends JsonSerializer<Object> {
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeNull();
}
}
}

View File

@@ -14,8 +14,8 @@ import java.util.function.Consumer;
public class JacksonMapper {
private static final ObjectMapper BASE = new ObjectMapper();
private static ObjectMapper INSTANCE = new ObjectMapper();
private static final ObjectMapper DEFAULT;
private static ObjectMapper INSTANCE = new ObjectMapper();
private static boolean init = false;
static {
@@ -24,12 +24,14 @@ public class JacksonMapper {
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
.withIsGetterVisibility(JsonAutoDetect.Visibility.NONE));
objectMapper.setVisibility(objectMapper
.getSerializationConfig()
.getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
.withIsGetterVisibility(JsonAutoDetect.Visibility.NONE));
var modules = findModules(ModuleLayer.boot());
objectMapper.registerModules(modules);
@@ -54,8 +56,8 @@ public class JacksonMapper {
private static List<Module> findModules(ModuleLayer layer) {
ArrayList<Module> modules = new ArrayList<Module>();
ServiceLoader<Module> loader = layer != null ?
ServiceLoader.load(layer, Module.class) : ServiceLoader.load(Module.class);
ServiceLoader<Module> loader =
layer != null ? ServiceLoader.load(layer, Module.class) : ServiceLoader.load(Module.class);
for (Module module : loader) {
modules.add(module);
}

View File

@@ -6,8 +6,7 @@ import lombok.experimental.SuperBuilder;
@SuperBuilder
public class JacksonizedValue {
public JacksonizedValue() {
}
public JacksonizedValue() {}
@SneakyThrows
public final String toString() {
@@ -34,5 +33,4 @@ public class JacksonizedValue {
var tree = JacksonMapper.newMapper().valueToTree(this);
return tree.hashCode();
}
}

View File

@@ -10,6 +10,8 @@ import java.util.Base64;
@EqualsAndHashCode
public class SecretValue {
String value;
public static SecretValue createForSecretValue(String s) {
if (s == null) {
return null;
@@ -22,8 +24,6 @@ public class SecretValue {
return new SecretValue(Base64.getEncoder().encodeToString(s.getBytes(StandardCharsets.UTF_8)));
}
String value;
public String getDisplay() {
return "*".repeat(value.length());
}

View File

@@ -20,5 +20,7 @@ open module io.xpipe.core {
requires static lombok;
uses com.fasterxml.jackson.databind.Module;
provides com.fasterxml.jackson.databind.Module with CoreJacksonModule;
}
provides com.fasterxml.jackson.databind.Module with
CoreJacksonModule;
}