Rework types

This commit is contained in:
Christopher Schnick 2021-12-18 12:58:07 +01:00
parent a6bb824bd3
commit df9495e0a3
43 changed files with 466 additions and 444 deletions

View file

@ -1,6 +1,6 @@
package io.xpipe.api; package io.xpipe.api;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
public interface XPipeDataStructureSource { public interface XPipeDataStructureSource {

View file

@ -8,12 +8,14 @@ import io.xpipe.beacon.ConnectorException;
import io.xpipe.beacon.ServerException; import io.xpipe.beacon.ServerException;
import io.xpipe.beacon.exchange.ReadTableDataExchange; import io.xpipe.beacon.exchange.ReadTableDataExchange;
import io.xpipe.beacon.exchange.ReadTableInfoExchange; import io.xpipe.beacon.exchange.ReadTableInfoExchange;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.ArrayNode; import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.TupleNode; import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.type.DataType; import io.xpipe.core.data.type.DataType;
import io.xpipe.core.data.typed.TypedAbstractReader;
import io.xpipe.core.data.typed.TypedDataStreamParser; import io.xpipe.core.data.typed.TypedDataStreamParser;
import io.xpipe.core.data.typed.TypedDataStructureNodeReader; import io.xpipe.core.data.typed.TypedDataStructureNodeReader;
import io.xpipe.core.data.typed.TypedReusableDataStructureNodeReader;
import io.xpipe.core.source.DataSourceId; import io.xpipe.core.source.DataSourceId;
import java.io.IOException; import java.io.IOException;
@ -26,9 +28,11 @@ import java.util.stream.StreamSupport;
public class DataTableImpl implements DataTable { public class DataTableImpl implements DataTable {
public static DataTable get(String s) { public static DataTable get(String s) {
final DataTable[] table = {null}; return get(DataSourceId.fromString(s));
}
var ds = DataSourceId.fromString(s); public static DataTable get(DataSourceId ds) {
final DataTable[] table = {null};
new XPipeApiConnector() { new XPipeApiConnector() {
@Override @Override
protected void handle(BeaconClient sc) throws ClientException, ServerException, ConnectorException { protected void handle(BeaconClient sc) throws ClientException, ServerException, ConnectorException {
@ -95,7 +99,7 @@ public class DataTableImpl implements DataTable {
var req = new ReadTableDataExchange.Request(id, maxToRead); var req = new ReadTableDataExchange.Request(id, maxToRead);
performExchange(sc, req, (ReadTableDataExchange.Response res, InputStream in) -> { performExchange(sc, req, (ReadTableDataExchange.Response res, InputStream in) -> {
var r = new TypedDataStreamParser(dataType); var r = new TypedDataStreamParser(dataType);
r.readStructures(in, new TypedDataStructureNodeReader(dataType), nodes::add); r.parseStructures(in, TypedDataStructureNodeReader.immutable(dataType), nodes::add);
}, false); }, false);
} }
}.execute(); }.execute();
@ -104,28 +108,26 @@ public class DataTableImpl implements DataTable {
@Override @Override
public Iterator<TupleNode> iterator() { public Iterator<TupleNode> iterator() {
return new Iterator<TupleNode>() { return new Iterator<>() {
private InputStream input; private InputStream input;
private int read; private int read;
private final int toRead = size; private final int toRead = size;
private TypedDataStreamParser reader; private final TypedDataStreamParser parser;
private TypedDataStructureNodeReader nodeReader; private final TypedAbstractReader nodeReader;
private TupleNode current;
{ {
new XPipeApiConnector() { new XPipeApiConnector() {
@Override @Override
protected void handle(BeaconClient sc) throws ClientException, ServerException, ConnectorException { protected void handle(BeaconClient sc) throws ClientException, ServerException, ConnectorException {
var req = new ReadTableDataExchange.Request(id, Integer.MAX_VALUE); var req = new ReadTableDataExchange.Request(id, Integer.MAX_VALUE);
performExchange(sc, req, (ReadTableDataExchange.Response res, InputStream in) -> { performExchange(sc, req,
input = in; (ReadTableDataExchange.Response res, InputStream in) -> input = in, false);
}, false);
} }
}.execute(); }.execute();
nodeReader = new TypedDataStructureNodeReader(dataType); nodeReader = TypedReusableDataStructureNodeReader.create(dataType);
reader = new TypedDataStreamParser(dataType); parser = new TypedDataStreamParser(dataType);
} }
private boolean hasKnownSize() { private boolean hasKnownSize() {
@ -143,7 +145,7 @@ public class DataTableImpl implements DataTable {
} }
try { try {
return reader.hasNext(input); return parser.hasNext(input);
} catch (IOException ex) { } catch (IOException ex) {
throw new UncheckedIOException(ex); throw new UncheckedIOException(ex);
} }
@ -151,8 +153,9 @@ public class DataTableImpl implements DataTable {
@Override @Override
public TupleNode next() { public TupleNode next() {
TupleNode current;
try { try {
current = (TupleNode) reader.readStructure(input, nodeReader); current = (TupleNode) parser.parseStructure(input, nodeReader);
} catch (IOException ex) { } catch (IOException ex) {
throw new UncheckedIOException(ex); throw new UncheckedIOException(ex);
} }

View file

@ -1,6 +1,6 @@
package io.xpipe.core.data.generic; package io.xpipe.core.data.generic;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
public interface GenericAbstractReader extends GenericDataStreamCallback { public interface GenericAbstractReader extends GenericDataStreamCallback {

View file

@ -1,6 +1,6 @@
package io.xpipe.core.data.generic; package io.xpipe.core.data.generic;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.ArrayNode; import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.ValueNode; import io.xpipe.core.data.node.ValueNode;

View file

@ -1,7 +1,7 @@
package io.xpipe.core.data.generic; package io.xpipe.core.data.generic;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.DataStructureNodeIO; import io.xpipe.core.data.node.DataStructureNodeIO;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;

View file

@ -1,6 +1,6 @@
package io.xpipe.core.data.generic; package io.xpipe.core.data.generic;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.ArrayNode; import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.TupleNode; import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.node.ValueNode; import io.xpipe.core.data.node.ValueNode;

View file

@ -1,6 +1,6 @@
package io.xpipe.core.data.generic; package io.xpipe.core.data.generic;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.ValueNode; import io.xpipe.core.data.node.ValueNode;
public class GenericDataStructureNodeReader implements GenericDataStreamCallback { public class GenericDataStructureNodeReader implements GenericDataStreamCallback {

View file

@ -1,6 +1,6 @@
package io.xpipe.core.data.generic; package io.xpipe.core.data.generic;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.SimpleTupleNode; import io.xpipe.core.data.node.SimpleTupleNode;
import io.xpipe.core.data.node.TupleNode; import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.node.ValueNode; import io.xpipe.core.data.node.ValueNode;
@ -130,7 +130,7 @@ public class GenericTupleReader implements GenericAbstractReader {
throw new IllegalStateException("Tuple ended but is not full yet"); throw new IllegalStateException("Tuple ended but is not full yet");
} }
created = TupleNode.wrap(names, nodes); created = TupleNode.of(names, nodes);
} }
@Override @Override
@ -162,6 +162,6 @@ public class GenericTupleReader implements GenericAbstractReader {
throw new IllegalStateException(); throw new IllegalStateException();
} }
return SimpleTupleNode.wrap(names, nodes); return SimpleTupleNode.of(names, nodes);
} }
} }

View file

@ -1,6 +1,5 @@
package io.xpipe.core.data.node; package io.xpipe.core.data.node;
import io.xpipe.core.data.DataStructureNode;
import io.xpipe.core.data.type.ArrayType; import io.xpipe.core.data.type.ArrayType;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -70,7 +69,7 @@ public class ArrayNode extends DataStructureNode {
@Override @Override
public ArrayType determineDataType() { public ArrayType determineDataType() {
return ArrayType.of(valueNodes.stream().map(DataStructureNode::determineDataType).toList()); return ArrayType.ofSharedType(valueNodes.stream().map(DataStructureNode::determineDataType).toList());
} }
@Override @Override

View file

@ -1,8 +1,5 @@
package io.xpipe.core.data; package io.xpipe.core.data.node;
import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.node.ValueNode;
import io.xpipe.core.data.type.DataType; import io.xpipe.core.data.type.DataType;
import java.util.Iterator; import java.util.Iterator;

View file

@ -1,4 +1,4 @@
package io.xpipe.core.data; package io.xpipe.core.data.node;
public interface DataStructureNodeAcceptor<T extends DataStructureNode> { public interface DataStructureNodeAcceptor<T extends DataStructureNode> {

View file

@ -1,4 +1,4 @@
package io.xpipe.core.data; package io.xpipe.core.data.node;
public class DataStructureNodeIO { public class DataStructureNodeIO {
@ -8,8 +8,8 @@ public class DataStructureNodeIO {
public static final int GENERIC_VALUE_ID = 3; public static final int GENERIC_VALUE_ID = 3;
public static final int GENERIC_NAME_ID = 4; public static final int GENERIC_NAME_ID = 4;
public static final int TYPED_STRUCTURE_ID = 0; public static final int TYPED_STRUCTURE_ID = 5;
public static final int TYPED_TUPLE_ID = 5; public static final int TYPED_TUPLE_ID = 6;
public static final int TYPED_ARRAY_ID = 6; public static final int TYPED_ARRAY_ID = 7;
public static final int TYPED_VALUE_ID = 7; public static final int TYPED_VALUE_ID = 8;
} }

View file

@ -1,4 +1,4 @@
package io.xpipe.core.data; package io.xpipe.core.data.node;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View file

@ -1,7 +1,5 @@
package io.xpipe.core.data.node; package io.xpipe.core.data.node;
import io.xpipe.core.data.DataStructureNode;
public class ImmutableValueNode extends ValueNode { public class ImmutableValueNode extends ValueNode {
private final byte[] data; private final byte[] data;

View file

@ -1,7 +1,5 @@
package io.xpipe.core.data.node; package io.xpipe.core.data.node;
import io.xpipe.core.data.DataStructureNode;
public class MutableValueNode extends ValueNode { public class MutableValueNode extends ValueNode {
private byte[] data; private byte[] data;

View file

@ -1,6 +1,5 @@
package io.xpipe.core.data.node; package io.xpipe.core.data.node;
import io.xpipe.core.data.DataStructureNode;
import io.xpipe.core.data.type.DataType; import io.xpipe.core.data.type.DataType;
import io.xpipe.core.data.type.TupleType; import io.xpipe.core.data.type.TupleType;

View file

@ -1,6 +1,5 @@
package io.xpipe.core.data.node; package io.xpipe.core.data.node;
import io.xpipe.core.data.DataStructureNode;
import io.xpipe.core.data.type.DataType; import io.xpipe.core.data.type.DataType;
import io.xpipe.core.data.type.TupleType; import io.xpipe.core.data.type.TupleType;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;

View file

@ -1,6 +1,5 @@
package io.xpipe.core.data.node; package io.xpipe.core.data.node;
import io.xpipe.core.data.DataStructureNode;
import lombok.Value; import lombok.Value;
import java.util.ArrayList; import java.util.ArrayList;
@ -14,7 +13,7 @@ public abstract class TupleNode extends DataStructureNode {
return new Builder(); return new Builder();
} }
public static TupleNode wrap(List<DataStructureNode> nodes) { public static TupleNode of(List<DataStructureNode> nodes) {
if (nodes == null) { if (nodes == null) {
throw new IllegalArgumentException("Nodes must be not null"); throw new IllegalArgumentException("Nodes must be not null");
} }
@ -22,11 +21,11 @@ public abstract class TupleNode extends DataStructureNode {
return new NoKeyTupleNode(nodes); return new NoKeyTupleNode(nodes);
} }
public static TupleNode copy(List<DataStructureNode> nodes) { public static TupleNode copyOf(List<DataStructureNode> nodes) {
return TupleNode.wrap(List.copyOf(nodes)); return TupleNode.of(List.copyOf(nodes));
} }
public static TupleNode wrap(List<String> names, List<DataStructureNode> nodes) { public static TupleNode of(List<String> names, List<DataStructureNode> nodes) {
if (names == null) { if (names == null) {
throw new IllegalArgumentException("Names must be not null"); throw new IllegalArgumentException("Names must be not null");
} }
@ -40,7 +39,7 @@ public abstract class TupleNode extends DataStructureNode {
return new SimpleTupleNode(names, nodes); return new SimpleTupleNode(names, nodes);
} }
public static TupleNode wrapRaw(List<String> names, List<DataStructureNode> nodes) { public static TupleNode ofRaw(List<String> names, List<DataStructureNode> nodes) {
if (names == null) { if (names == null) {
throw new IllegalArgumentException("Names must be not null"); throw new IllegalArgumentException("Names must be not null");
} }
@ -50,8 +49,8 @@ public abstract class TupleNode extends DataStructureNode {
return new SimpleTupleNode(names, nodes); return new SimpleTupleNode(names, nodes);
} }
public static TupleNode copy(List<String> names, List<DataStructureNode> nodes) { public static TupleNode copyOf(List<String> names, List<DataStructureNode> nodes) {
return TupleNode.wrap(List.copyOf(names), List.copyOf(nodes)); return TupleNode.of(List.copyOf(names), List.copyOf(nodes));
} }
public final boolean isTuple() { public final boolean isTuple() {
@ -106,10 +105,10 @@ public abstract class TupleNode extends DataStructureNode {
public TupleNode build() { public TupleNode build() {
boolean hasKeys = entries.stream().anyMatch(kv -> kv.key != null); boolean hasKeys = entries.stream().anyMatch(kv -> kv.key != null);
return hasKeys ? TupleNode.wrap( return hasKeys ? TupleNode.of(
entries.stream().map(kv -> kv.key).toList(), entries.stream().map(kv -> kv.key).toList(),
entries.stream().map(kv -> kv.value).toList()) : entries.stream().map(kv -> kv.value).toList()) :
TupleNode.wrap(entries.stream().map(kv -> kv.value).toList()); TupleNode.of(entries.stream().map(kv -> kv.value).toList());
} }
} }
} }

View file

@ -1,6 +1,5 @@
package io.xpipe.core.data.node; package io.xpipe.core.data.node;
import io.xpipe.core.data.DataStructureNode;
import io.xpipe.core.data.type.DataType; import io.xpipe.core.data.type.DataType;
import io.xpipe.core.data.type.ValueType; import io.xpipe.core.data.type.ValueType;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -19,6 +18,10 @@ public abstract class ValueNode extends DataStructureNode {
return new ImmutableValueNode(data); return new ImmutableValueNode(data);
} }
public static ValueNode immutable(Object o) {
return immutable(o.toString().getBytes(StandardCharsets.UTF_8));
}
public static ValueNode mutableNull() { public static ValueNode mutableNull() {
return mutable(NULL); return mutable(NULL);
} }

View file

@ -1,27 +1,38 @@
package io.xpipe.core.data.type; package io.xpipe.core.data.type;
import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.type.callback.DataTypeCallback; import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Value;
import java.util.List; import java.util.List;
/**
* An array type represents an array of {@link DataStructureNode} of a certain shared type.
* The shared type should be the most specific data type possible.
*/
@JsonTypeName("array") @JsonTypeName("array")
@EqualsAndHashCode @EqualsAndHashCode(callSuper = false)
public class ArrayType implements DataType { @AllArgsConstructor(access = AccessLevel.PRIVATE)
@Value
public class ArrayType extends DataType {
private final DataType sharedType; DataType sharedType;
public ArrayType(DataType sharedType) { /**
this.sharedType = sharedType; * Creates a new array type for a given shared data type.
*/
public static ArrayType of(DataType type) {
return new ArrayType(type);
} }
public static ArrayType ofWildcard() { /**
return new ArrayType(WildcardType.of()); * Creates a new array type using either the shared type of {@code types}
} * or a wildcard type if the elements do not share a common type.
*/
public static ArrayType of(List<DataType> types) { public static ArrayType ofSharedType(List<DataType> types) {
if (types.size() == 0) { if (types.size() == 0) {
return new ArrayType(WildcardType.of()); return new ArrayType(WildcardType.of());
} }
@ -31,18 +42,6 @@ public class ArrayType implements DataType {
return new ArrayType(eq ? first : WildcardType.of()); return new ArrayType(eq ? first : WildcardType.of());
} }
public boolean isSimple() {
return hasSharedType() && getSharedType().isValue();
}
public boolean hasSharedType() {
return sharedType != null;
}
public DataType getSharedType() {
return sharedType;
}
@Override @Override
public String getName() { public String getName() {
return "array"; return "array";
@ -50,7 +49,17 @@ public class ArrayType implements DataType {
@Override @Override
public boolean matches(DataStructureNode node) { public boolean matches(DataStructureNode node) {
return node.isArray(); if (!node.isArray()) {
return false;
}
var a = node.asArray();
for (var n : a) {
if (!sharedType.matches(n)) {
return false;
}
}
return true;
} }
@Override @Override
@ -59,7 +68,7 @@ public class ArrayType implements DataType {
} }
@Override @Override
public void traverseType(DataTypeCallback cb) { public void visit(DataTypeVisitor visitor) {
cb.onArray(this); visitor.onArray(this);
} }
} }

View file

@ -1,31 +1,108 @@
package io.xpipe.core.data.type; package io.xpipe.core.data.type;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.type.callback.DataTypeCallback;
/**
* Represents the type of a {@link DataStructureNode} object.
* To check whether a {@link DataStructureNode} instance conforms to the specified type,
* the method {@link #matches(DataStructureNode)} can be used.
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
public interface DataType { public abstract class DataType {
String getName(); /**
* Returns the readable name of this data type that can be used for error messages.
*/
public abstract String getName();
boolean matches(DataStructureNode node); /**
* Checks whether a node conforms to this data type.
*/
public abstract boolean matches(DataStructureNode node);
default boolean isTuple() { /**
* Checks whether this type is a tuple.
*/
public boolean isTuple() {
return false; return false;
} }
default boolean isWildcard() { /**
* Checks whether this type is a wildcard.
*/
public boolean isWildcard() {
return false; return false;
} }
default boolean isArray() { /**
* Checks whether this type is an array.
*/
public boolean isArray() {
return false; return false;
} }
default boolean isValue() { /**
* Checks whether this type is a value.
*/
public boolean isValue() {
return false; return false;
} }
void traverseType(DataTypeCallback cb); /**
* Casts this type to a wildcard type if possible.
*
* @throws UnsupportedOperationException if the type is not a wildcard type
*/
public final WildcardType asWildcard() {
if (!isWildcard()) {
throw new UnsupportedOperationException(getName() + " is not a wildcard type");
}
return (WildcardType) this;
}
/**
* Casts this type to a value type if possible.
*
* @throws UnsupportedOperationException if the type is not a value type
*/
public final ValueType asValue() {
if (!isValue()) {
throw new UnsupportedOperationException(getName() + " is not a value type");
}
return (ValueType) this;
}
/**
* Casts this type to a tuple type if possible.
*
* @throws UnsupportedOperationException if the type is not a tuple type
*/
public final TupleType asTuple() {
if (!isTuple()) {
throw new UnsupportedOperationException(getName() + " is not a tuple type");
}
return (TupleType) this;
}
/**
* Casts this type to an array type if possible.
*
* @throws UnsupportedOperationException if the type is not an array type
*/
public final ArrayType asArray() {
if (!isArray()) {
throw new UnsupportedOperationException(getName() + " is not an array type");
}
return (ArrayType) this;
}
/**
* Visits this type using a {@link DataTypeVisitor} instance.
*/
public abstract void visit(DataTypeVisitor visitor);
} }

View file

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

View file

@ -0,0 +1,106 @@
package io.xpipe.core.data.type;
import io.xpipe.core.data.node.DataStructureNodePointer;
import java.util.Stack;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class DataTypeVisitors {
/**
* Creates a visitor that sequentially visits all subtypes.
*/
public static DataTypeVisitor flatten(Consumer<DataType> typeConsumer) {
return new DataTypeVisitor() {
@Override
public void onValue(ValueType type) {
typeConsumer.accept(type);
}
@Override
public void onTuple(TupleType type) {
typeConsumer.accept(type);
type.getTypes().forEach(t -> t.visit(this));
}
@Override
public void onArray(ArrayType type) {
typeConsumer.accept(type);
}
@Override
public void onWildcard(WildcardType type) {
typeConsumer.accept(type);
}
};
}
/**
* 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) {
return new DataTypeVisitor() {
private final Stack<TupleType> tuples = new Stack<>();
private final Stack<Integer> keyIndices = new Stack<>();
private boolean isOnTopLevel() {
return tuples.size() <= 1;
}
private void onAnyValue() {
var pointer = DataStructureNodePointer.builder();
for (int index : keyIndices) {
pointer.index(index);
}
var p = pointer.build();
newValue.accept(tuples.peek().getNames().get(keyIndices.peek()), p);
moveIndex();
}
private void moveIndex() {
var index = keyIndices.pop();
index++;
keyIndices.push(index);
}
@Override
public void onValue(ValueType type) {
onAnyValue();
}
@Override
public void onWildcard(WildcardType type) {
onAnyValue();
}
@Override
public void onTuple(TupleType tuple) {
if (!isOnTopLevel()) {
moveIndex();
}
tuples.push(tuple);
keyIndices.push(0);
if (!isOnTopLevel()) {
newTuple.accept(tuples.peek().getNames().get(keyIndices.peek()));
}
tuple.getTypes().forEach(t -> t.visit(this));
endTuple.run();
tuples.pop();
keyIndices.pop();
}
@Override
public void onArray(ArrayType type) {
onAnyValue();
}
};
}
}

View file

@ -2,35 +2,51 @@ package io.xpipe.core.data.type;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.type.callback.DataTypeCallback; import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Value;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
/**
* A tuple type in the context of XPipe is defined as an ordered,
* fixed-size sequence of elements that can be optionally assigned a name.
* This permissive design allows for a very flexible usage of the tuple type.
*/
@JsonTypeName("tuple") @JsonTypeName("tuple")
@EqualsAndHashCode @EqualsAndHashCode(callSuper = false)
public class TupleType implements DataType { @AllArgsConstructor(access = AccessLevel.PRIVATE)
@Value
public class TupleType extends DataType {
private final List<String> names; List<String> names;
private final List<DataType> types; List<DataType> types;
@JsonCreator
private TupleType(List<String> names, List<DataType> types) {
this.names = names;
this.types = types;
}
/**
* Creates a new tuple type that contains no entries.
*/
public static TupleType empty() { public static TupleType empty() {
return new TupleType(List.of(), List.of()); return new TupleType(List.of(), List.of());
} }
/**
* Creates a new tuple type for a list of names and types.
* Any entry in {@code names} can be null, while any element in {@code types} must be not null.
*/
@JsonCreator
public static TupleType of(List<String> names, List<DataType> types) { public static TupleType of(List<String> names, List<DataType> types) {
return new TupleType(names, types); return new TupleType(names, types);
} }
public static TupleType wrapWithoutNames(List<DataType> types) { /**
* Creates a new tuple type for a list of types with no names.
* Any element in {@code types} must be not null.
*/
public static TupleType of(List<DataType> types) {
return new TupleType(Collections.nCopies(types.size(), null), types); return new TupleType(Collections.nCopies(types.size(), null), types);
} }
@ -41,7 +57,28 @@ public class TupleType implements DataType {
@Override @Override
public boolean matches(DataStructureNode node) { public boolean matches(DataStructureNode node) {
return node.isTuple(); if (!node.isTuple()) {
return false;
}
var t = node.asTuple();
if (t.size() != getSize()) {
return false;
}
int counter = 0;
for (var kv : t.getKeyValuePairs()) {
if (!Objects.equals(kv.getKey(), names.get(counter))) {
return false;
}
if (!types.get(counter).matches(kv.getValue())) {
return false;
}
counter++;
}
return true;
} }
@Override @Override
@ -50,23 +87,11 @@ public class TupleType implements DataType {
} }
@Override @Override
public void traverseType(DataTypeCallback cb) { public void visit(DataTypeVisitor visitor) {
cb.onTupleBegin(this); visitor.onTuple(this);
for (var t : types) {
t.traverseType(cb);
}
cb.onTupleEnd();
} }
public int getSize() { public int getSize() {
return types.size(); return types.size();
} }
public List<String> getNames() {
return names;
}
public List<DataType> getTypes() {
return types;
}
} }

View file

@ -1,18 +1,24 @@
package io.xpipe.core.data.type; package io.xpipe.core.data.type;
import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.type.callback.DataTypeCallback; import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Value;
/**
* A value type represents any node that holds some atomic value, i.e. it has no subtypes.
*/
@JsonTypeName("value") @JsonTypeName("value")
@EqualsAndHashCode @EqualsAndHashCode(callSuper = false)
public class ValueType implements DataType { @AllArgsConstructor(access = AccessLevel.PRIVATE)
@Value
private ValueType() { public class ValueType extends DataType {
}
/**
* Creates a new instance.
*/
public static ValueType of() { public static ValueType of() {
return new ValueType(); return new ValueType();
} }
@ -33,7 +39,7 @@ public class ValueType implements DataType {
} }
@Override @Override
public void traverseType(DataTypeCallback cb) { public void visit(DataTypeVisitor visitor) {
cb.onValue(); visitor.onValue(this);
} }
} }

View file

@ -1,18 +1,29 @@
package io.xpipe.core.data.type; package io.xpipe.core.data.type;
import io.xpipe.core.data.DataStructureNode; import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.core.data.type.callback.DataTypeCallback; import io.xpipe.core.data.node.DataStructureNode;
import lombok.EqualsAndHashCode;
import lombok.Value;
public class WildcardType implements DataType { /**
* A wildcard type matches any {@link DataStructureNode} instance.
private WildcardType() { * For simplicity reasons it is not possible to further specify a wildcard instance to only match a certain
* subset of {@link DataStructureNode} instance that fullfil a certain property.
} */
@JsonTypeName("wildcard")
@EqualsAndHashCode(callSuper = false)
@Value
public class WildcardType extends DataType {
/**
* Creates a new instance.
*/
public static WildcardType of() { public static WildcardType of() {
return new WildcardType(); return new WildcardType();
} }
private WildcardType() {}
@Override @Override
public String getName() { public String getName() {
return "wildcard"; return "wildcard";
@ -29,7 +40,7 @@ public class WildcardType implements DataType {
} }
@Override @Override
public void traverseType(DataTypeCallback cb) { public void visit(DataTypeVisitor visitor) {
visitor.onWildcard(this);
} }
} }

View file

@ -1,42 +0,0 @@
package io.xpipe.core.data.type.callback;
import io.xpipe.core.data.type.ArrayType;
import io.xpipe.core.data.type.DataType;
import io.xpipe.core.data.type.TupleType;
import io.xpipe.core.data.type.ValueType;
import java.util.function.Consumer;
public interface DataTypeCallback {
static DataTypeCallback flatten(Consumer<DataType> typeConsumer) {
return new DataTypeCallback() {
@Override
public void onValue() {
typeConsumer.accept(ValueType.of());
}
@Override
public void onTupleBegin(TupleType tuple) {
typeConsumer.accept(tuple);
}
@Override
public void onArray(ArrayType type) {
typeConsumer.accept(type);
}
};
}
default void onValue() {
}
default void onTupleBegin(TupleType tuple) {
}
default void onTupleEnd() {
}
default void onArray(ArrayType type) {
}
}

View file

@ -1,61 +0,0 @@
package io.xpipe.core.data.type.callback;
import io.xpipe.core.data.DataStructureNodePointer;
import io.xpipe.core.data.type.ArrayType;
import io.xpipe.core.data.type.TupleType;
import java.util.Stack;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class DataTypeCallbacks {
public static DataTypeCallback visitTuples(Consumer<String> newTuple, Runnable endTuple, BiConsumer<String, DataStructureNodePointer> newValue) {
return new DataTypeCallback() {
private final Stack<String> keyNames = new Stack<>();
private final Stack<DataStructureNodePointer.Builder> builders = new Stack<>();
{
builders.push(DataStructureNodePointer.builder());
}
private boolean isOnTopLevel() {
return keyNames.size() == 0;
}
@Override
public void onTupleBegin(TupleType tuple) {
if (!isOnTopLevel()) {
newTuple.accept(keyNames.peek());
}
tuple.getNames().forEach(n -> {
keyNames.push(n);
builders.push(builders.peek().copy().name(n));
tuple.getTypes().forEach(dt -> dt.traverseType(this));
});
}
@Override
public void onValue() {
newValue.accept(keyNames.peek(), builders.peek().build());
keyNames.pop();
builders.pop();
}
@Override
public void onTupleEnd() {
endTuple.run();
}
@Override
public void onArray(ArrayType type) {
if (!type.isSimple()) {
throw new IllegalStateException();
}
newValue.accept(keyNames.peek(), builders.peek().build());
}
};
}
}

View file

@ -1,63 +0,0 @@
package io.xpipe.core.data.type.callback;
import io.xpipe.core.data.type.TupleType;
public class FlatArrayTypeCallback implements DataTypeCallback {
private final FlatCallback cb;
private int arrayDepth = 0;
public FlatArrayTypeCallback(FlatCallback cb) {
this.cb = cb;
}
private boolean isInArray() {
return arrayDepth > 0;
}
@Override
public void onValue() {
if (isInArray()) {
return;
}
cb.onValue();
}
@Override
public void onTupleBegin(TupleType tuple) {
if (isInArray()) {
throw new IllegalStateException();
}
cb.onTupleBegin(tuple);
}
@Override
public void onTupleEnd() {
cb.onTupleEnd();
}
public void onArray() {
if (isInArray()) {
throw new IllegalStateException();
}
arrayDepth++;
}
public interface FlatCallback {
default void onValue() {
}
default void onTupleBegin(TupleType tuple) {
}
default void onTupleEnd() {
}
default void onFlatArray() {
}
}
}

View file

@ -1,80 +0,0 @@
package io.xpipe.core.data.type.callback;
import io.xpipe.core.data.DataStructureNodePointer;
import io.xpipe.core.data.type.ArrayType;
import io.xpipe.core.data.type.TupleType;
import java.util.Stack;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class TableTypeCallback implements DataTypeCallback {
private final Stack<TupleType> tuples = new Stack<>();
private final Stack<Integer> keyIndices = new Stack<>();
private final Consumer<String> newTuple;
private final Runnable endTuple;
private final BiConsumer<String, DataStructureNodePointer> newValue;
private TableTypeCallback(Consumer<String> newTuple, Runnable endTuple, BiConsumer<String, DataStructureNodePointer> newValue) {
this.newTuple = newTuple;
this.endTuple = endTuple;
this.newValue = newValue;
}
public static DataTypeCallback create(Consumer<String> newTuple, Runnable endTuple, BiConsumer<String, DataStructureNodePointer> newValue) {
return new TableTypeCallback(newTuple, endTuple, newValue);
}
private boolean isOnTopLevel() {
return tuples.size() <= 1;
}
private void onAnyValue() {
var pointer = DataStructureNodePointer.builder();
for (int index : keyIndices) {
pointer.index(index);
}
var p = pointer.build();
newValue.accept(tuples.peek().getNames().get(keyIndices.peek()), p);
moveIndex();
}
private void moveIndex() {
var index = keyIndices.pop();
index++;
keyIndices.push(index);
}
@Override
public void onValue() {
onAnyValue();
}
@Override
public void onTupleBegin(TupleType tuple) {
if (!isOnTopLevel()) {
moveIndex();
}
tuples.push(tuple);
keyIndices.push(0);
if (!isOnTopLevel()) {
newTuple.accept(tuples.peek().getNames().get(keyIndices.peek()));
}
}
@Override
public void onTupleEnd() {
endTuple.run();
tuples.pop();
keyIndices.pop();
}
@Override
public void onArray(ArrayType type) {
onAnyValue();
}
}

View file

@ -1,6 +1,6 @@
package io.xpipe.core.data.typed; package io.xpipe.core.data.typed;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
public interface TypedAbstractReader extends TypedDataStreamCallback { public interface TypedAbstractReader extends TypedDataStreamCallback {

View file

@ -1,6 +1,6 @@
package io.xpipe.core.data.typed; package io.xpipe.core.data.typed;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.type.TupleType; import io.xpipe.core.data.type.TupleType;
import java.io.IOException; import java.io.IOException;

View file

@ -1,7 +1,7 @@
package io.xpipe.core.data.typed; package io.xpipe.core.data.typed;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.DataStructureNodeIO; import io.xpipe.core.data.node.DataStructureNodeIO;
import io.xpipe.core.data.generic.GenericDataStreamParser; import io.xpipe.core.data.generic.GenericDataStreamParser;
import io.xpipe.core.data.generic.GenericDataStructureNodeReader; import io.xpipe.core.data.generic.GenericDataStructureNodeReader;
import io.xpipe.core.data.type.ArrayType; import io.xpipe.core.data.type.ArrayType;
@ -34,27 +34,31 @@ public class TypedDataStreamParser {
return true; return true;
} }
public void readStructures(InputStream in, TypedAbstractReader cb, Consumer<DataStructureNode> consumer) throws IOException { public void parseStructures(InputStream in, TypedAbstractReader cb, Consumer<DataStructureNode> consumer) throws IOException {
while (hasNext(in)) { while (hasNext(in)) {
cb.onNodeBegin(); cb.onNodeBegin();
read(in, cb, dataType); parse(in, cb, dataType);
cb.onNodeEnd(); cb.onNodeEnd();
consumer.accept(cb.create()); consumer.accept(cb.create());
} }
} }
public DataStructureNode readStructure(InputStream in, TypedAbstractReader cb) throws IOException { public DataStructureNode parseStructure(InputStream in, TypedAbstractReader cb) throws IOException {
if (!hasNext(in)) { if (!hasNext(in)) {
throw new IllegalStateException("No structure to read"); throw new IllegalStateException("No structure to read");
} }
cb.onNodeBegin(); cb.onNodeBegin();
read(in, cb, dataType); parse(in, cb, dataType);
cb.onNodeEnd(); cb.onNodeEnd();
return cb.create(); return cb.create();
} }
private void read(InputStream in, TypedDataStreamCallback cb, DataType type) throws IOException { public void parse(InputStream in, TypedDataStreamCallback cb) throws IOException {
parse(in, cb, dataType);
}
private void parse(InputStream in, TypedDataStreamCallback cb, DataType type) throws IOException {
var b = in.read(); var b = in.read();
// Skip // Skip
@ -69,7 +73,7 @@ public class TypedDataStreamParser {
} }
var tt = (TupleType) type; var tt = (TupleType) type;
readTypedTuple(in, cb, tt); parseTypedTuple(in, cb, tt);
} }
case DataStructureNodeIO.TYPED_ARRAY_ID -> { case DataStructureNodeIO.TYPED_ARRAY_ID -> {
if (!type.isArray()) { if (!type.isArray()) {
@ -77,20 +81,23 @@ public class TypedDataStreamParser {
} }
var at = (ArrayType) type; var at = (ArrayType) type;
readTypedArray(in, cb, at); parseTypedArray(in, cb, at);
} }
case DataStructureNodeIO.TYPED_VALUE_ID -> { case DataStructureNodeIO.TYPED_VALUE_ID -> {
if (!type.isValue()) { if (!type.isValue()) {
throw new IllegalStateException("Got value but expected " + type.getName()); throw new IllegalStateException("Got value but expected " + type.getName());
} }
readValue(in, cb); parseValue(in, cb);
}
default -> {
GenericDataStreamParser.
throw new IllegalStateException("Unexpected value: " + b);
} }
default -> throw new IllegalStateException("Unexpected value: " + b);
} }
} }
private void readTypedTuple(InputStream in, TypedDataStreamCallback cb, TupleType type) throws IOException { private void parseTypedTuple(InputStream in, TypedDataStreamCallback cb, TupleType type) throws IOException {
cb.onTupleBegin(type); cb.onTupleBegin(type);
for (int i = 0; i < type.getSize(); i++) { for (int i = 0; i < type.getSize(); i++) {
if (type.getTypes().get(i).isWildcard()) { if (type.getTypes().get(i).isWildcard()) {
@ -99,7 +106,7 @@ public class TypedDataStreamParser {
var node = r.create(); var node = r.create();
cb.onGenericNode(node); cb.onGenericNode(node);
} else { } else {
read(in, cb, type.getTypes().get(i)); parse(in, cb, type.getTypes().get(i));
} }
} }
cb.onTupleEnd(); cb.onTupleEnd();
@ -112,7 +119,7 @@ public class TypedDataStreamParser {
return genericReader; return genericReader;
} }
private void readTypedArray(InputStream in, TypedDataStreamCallback cb, ArrayType type) throws IOException { private void parseTypedArray(InputStream in, TypedDataStreamCallback cb, ArrayType type) throws IOException {
var size = in.read(); var size = in.read();
cb.onArrayBegin(size); cb.onArrayBegin(size);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
@ -122,13 +129,13 @@ public class TypedDataStreamParser {
var node = r.create(); var node = r.create();
cb.onGenericNode(node); cb.onGenericNode(node);
} else { } else {
read(in, cb, type.getSharedType()); parse(in, cb, type.getSharedType());
} }
} }
cb.onArrayEnd(); cb.onArrayEnd();
} }
private void readValue(InputStream in, TypedDataStreamCallback cb) throws IOException { private void parseValue(InputStream in, TypedDataStreamCallback cb) throws IOException {
var size = in.read(); var size = in.read();
var data = in.readNBytes(size); var data = in.readNBytes(size);
cb.onValue(data); cb.onValue(data);

View file

@ -1,7 +1,7 @@
package io.xpipe.core.data.typed; package io.xpipe.core.data.typed;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.DataStructureNodeIO; import io.xpipe.core.data.node.DataStructureNodeIO;
import io.xpipe.core.data.generic.GenericDataStreamWriter; import io.xpipe.core.data.generic.GenericDataStreamWriter;
import io.xpipe.core.data.node.ArrayNode; import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.SimpleTupleNode; import io.xpipe.core.data.node.SimpleTupleNode;
@ -27,8 +27,10 @@ public class TypedDataStreamWriter {
writeArray(out, (ArrayNode) node, (ArrayType) type); writeArray(out, (ArrayNode) node, (ArrayType) type);
} else if (node.isValue() && type.isValue()) { } else if (node.isValue() && type.isValue()) {
writeValue(out, (ValueNode) node); writeValue(out, (ValueNode) node);
} else if (type.isWildcard()) {
GenericDataStreamWriter.write(out, node);
} else { } else {
throw new AssertionError(); throw new IllegalStateException("Incompatible node and type");
} }
} }
@ -45,11 +47,7 @@ public class TypedDataStreamWriter {
out.write(DataStructureNodeIO.TYPED_TUPLE_ID); out.write(DataStructureNodeIO.TYPED_TUPLE_ID);
for (int i = 0; i < tuple.size(); i++) { for (int i = 0; i < tuple.size(); i++) {
if (!type.getTypes().get(i).isWildcard()) {
write(out, tuple.at(i), type.getTypes().get(i)); write(out, tuple.at(i), type.getTypes().get(i));
} else {
GenericDataStreamWriter.write(out, tuple.at(i));
}
} }
} }
@ -57,11 +55,7 @@ public class TypedDataStreamWriter {
out.write(DataStructureNodeIO.TYPED_ARRAY_ID); out.write(DataStructureNodeIO.TYPED_ARRAY_ID);
out.write(array.size()); out.write(array.size());
for (int i = 0; i < array.size(); i++) { for (int i = 0; i < array.size(); i++) {
if (!type.getSharedType().isWildcard()) {
write(out, array.at(i), type.getSharedType()); write(out, array.at(i), type.getSharedType());
} else {
GenericDataStreamWriter.write(out, array.at(i));
}
} }
} }
} }

View file

@ -1,13 +1,13 @@
package io.xpipe.core.data.typed; package io.xpipe.core.data.typed;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.ArrayNode; import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.SimpleTupleNode; import io.xpipe.core.data.node.SimpleTupleNode;
import io.xpipe.core.data.node.TupleNode; import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.node.ValueNode; import io.xpipe.core.data.node.ValueNode;
import io.xpipe.core.data.type.DataType; import io.xpipe.core.data.type.DataType;
import io.xpipe.core.data.type.TupleType; import io.xpipe.core.data.type.TupleType;
import io.xpipe.core.data.type.callback.DataTypeCallback; import io.xpipe.core.data.type.DataTypeVisitors;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -29,7 +29,7 @@ public class TypedDataStructureNodeReader implements TypedAbstractReader {
flattened = new ArrayList<>(); flattened = new ArrayList<>();
children = new Stack<>(); children = new Stack<>();
nodes = new Stack<>(); nodes = new Stack<>();
type.traverseType(DataTypeCallback.flatten(d -> flattened.add(d))); type.visit(DataTypeVisitors.flatten(d -> flattened.add(d)));
this.makeImmutable = makeImmutable; this.makeImmutable = makeImmutable;
} }
@ -114,7 +114,7 @@ public class TypedDataStructureNodeReader implements TypedAbstractReader {
var tupleNames = makeImmutable ? var tupleNames = makeImmutable ?
Collections.unmodifiableList(tupleType.getNames()) : new ArrayList<>(tupleType.getNames()); Collections.unmodifiableList(tupleType.getNames()) : new ArrayList<>(tupleType.getNames());
var tupleNodes = makeImmutable ? Collections.unmodifiableList(l) : l; var tupleNodes = makeImmutable ? Collections.unmodifiableList(l) : l;
var newNode = TupleNode.wrapRaw(tupleNames, tupleNodes); var newNode = TupleNode.ofRaw(tupleNames, tupleNodes);
nodes.push(newNode); nodes.push(newNode);
} }

View file

@ -1,10 +1,10 @@
package io.xpipe.core.data.typed; package io.xpipe.core.data.typed;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.ValueNode; import io.xpipe.core.data.node.ValueNode;
import io.xpipe.core.data.type.DataType; import io.xpipe.core.data.type.DataType;
import io.xpipe.core.data.type.TupleType; import io.xpipe.core.data.type.TupleType;
import io.xpipe.core.data.type.callback.DataTypeCallback; import io.xpipe.core.data.type.DataTypeVisitors;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -13,17 +13,21 @@ import java.util.Stack;
public class TypedReusableDataStructureNodeReader implements TypedAbstractReader { public class TypedReusableDataStructureNodeReader implements TypedAbstractReader {
public static TypedReusableDataStructureNodeReader create(DataType type) {
return new TypedReusableDataStructureNodeReader(type);
}
private final List<DataType> flattened; private final List<DataType> flattened;
private final TypedDataStructureNodeReader initialReader; private final TypedDataStructureNodeReader initialReader;
private DataStructureNode node; private DataStructureNode node;
private final Stack<Integer> indices; private final Stack<Integer> indices;
private int arrayDepth; private int arrayDepth;
public TypedReusableDataStructureNodeReader(DataType type) { private TypedReusableDataStructureNodeReader(DataType type) {
flattened = new ArrayList<>(); flattened = new ArrayList<>();
indices = new Stack<>(); indices = new Stack<>();
initialReader = TypedDataStructureNodeReader.mutable(type); initialReader = TypedDataStructureNodeReader.mutable(type);
type.traverseType(DataTypeCallback.flatten(d -> flattened.add(d))); type.visit(DataTypeVisitors.flatten(d -> flattened.add(d)));
} }
@Override @Override

View file

@ -1,7 +1,7 @@
package io.xpipe.core.source; package io.xpipe.core.source;
import io.xpipe.core.data.DataStructureNodeAcceptor; import io.xpipe.core.data.node.DataStructureNodeAcceptor;
import io.xpipe.core.data.node.ArrayNode; import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.TupleNode; import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.type.TupleType; import io.xpipe.core.data.type.TupleType;

View file

@ -4,9 +4,9 @@ import io.xpipe.core.store.DataStore;
public abstract class TableDataSourceDescriptor<DS extends DataStore> implements DataSourceDescriptor<DS> { public abstract class TableDataSourceDescriptor<DS extends DataStore> implements DataSourceDescriptor<DS> {
public abstract TableDataWriteConnection openWriteConnection(DS store); public abstract TableDataWriteConnection newWriteConnection(DS store);
public abstract TableDataReadConnection openConnection(DS store); public abstract TableDataReadConnection newReadConnection(DS store);
@Override @Override
public DataSourceType getType() { public DataSourceType getType() {

View file

@ -1,12 +1,12 @@
package io.xpipe.core.source; package io.xpipe.core.source;
import io.xpipe.core.data.DataStructureNodeAcceptor; import io.xpipe.core.data.node.DataStructureNodeAcceptor;
import io.xpipe.core.data.node.ArrayNode; import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.SimpleTupleNode; import io.xpipe.core.data.node.TupleNode;
public interface TableDataWriteConnection extends DataSourceConnection { public interface TableDataWriteConnection extends DataSourceConnection {
DataStructureNodeAcceptor<SimpleTupleNode> writeLinesAcceptor(); DataStructureNodeAcceptor<TupleNode> writeLinesAcceptor();
void writeLines(ArrayNode lines) throws Exception; void writeLines(ArrayNode lines) throws Exception;
} }

View file

@ -16,10 +16,6 @@ module io.xpipe.core {
opens io.xpipe.core.source; opens io.xpipe.core.source;
opens io.xpipe.core.data.type; opens io.xpipe.core.data.type;
opens io.xpipe.core.data.generic; opens io.xpipe.core.data.generic;
exports io.xpipe.core.data.type.callback;
opens io.xpipe.core.data.type.callback;
exports io.xpipe.core.data;
opens io.xpipe.core.data;
exports io.xpipe.core.util; exports io.xpipe.core.util;
exports io.xpipe.core.data.node; exports io.xpipe.core.data.node;
opens io.xpipe.core.data.node; opens io.xpipe.core.data.node;

View file

@ -1,6 +1,6 @@
package io.xpipe.core.test; package io.xpipe.core.test;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.generic.GenericDataStreamParser; import io.xpipe.core.data.generic.GenericDataStreamParser;
import io.xpipe.core.data.generic.GenericDataStreamWriter; import io.xpipe.core.data.generic.GenericDataStreamWriter;
import io.xpipe.core.data.generic.GenericDataStructureNodeReader; import io.xpipe.core.data.generic.GenericDataStructureNodeReader;
@ -98,7 +98,7 @@ public class DataStructureTest {
var data = dataOut.toByteArray(); var data = dataOut.toByteArray();
var reader = TypedDataStructureNodeReader.mutable(ds.type); var reader = TypedDataStructureNodeReader.mutable(ds.type);
new TypedDataStreamParser(ds.type).readStructure(new ByteArrayInputStream(data), reader); new TypedDataStreamParser(ds.type).parseStructure(new ByteArrayInputStream(data), reader);
var readNode = reader.create(); var readNode = reader.create();
Assertions.assertEquals(node, readNode); Assertions.assertEquals(node, readNode);
@ -125,7 +125,7 @@ public class DataStructureTest {
var data = dataOut.toByteArray(); var data = dataOut.toByteArray();
var reader = TypedDataStructureNodeReader.immutable(ds.type); var reader = TypedDataStructureNodeReader.immutable(ds.type);
new TypedDataStreamParser(ds.type).readStructure(new ByteArrayInputStream(data), reader); new TypedDataStreamParser(ds.type).parseStructure(new ByteArrayInputStream(data), reader);
var readNode = reader.create(); var readNode = reader.create();
Assertions.assertEquals(node, readNode); Assertions.assertEquals(node, readNode);
@ -153,10 +153,10 @@ public class DataStructureTest {
var data = dataOut.toByteArray(); var data = dataOut.toByteArray();
var in = new ByteArrayInputStream(data); var in = new ByteArrayInputStream(data);
var reader = new TypedReusableDataStructureNodeReader(ds.type); var reader = TypedReusableDataStructureNodeReader.create(ds.type);
for (var node : ds.nodes) { for (var node : ds.nodes) {
new TypedDataStreamParser(ds.type).readStructure(in, reader); new TypedDataStreamParser(ds.type).parseStructure(in, reader);
var readNode = reader.create(); var readNode = reader.create();
Assertions.assertEquals(node, readNode); Assertions.assertEquals(node, readNode);
} }

View file

@ -1,6 +1,6 @@
package io.xpipe.core.test; package io.xpipe.core.test;
import io.xpipe.core.data.DataStructureNode; import io.xpipe.core.data.node.DataStructureNode;
import io.xpipe.core.data.node.ArrayNode; import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.TupleNode; import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.node.ValueNode; import io.xpipe.core.data.node.ValueNode;
@ -32,7 +32,10 @@ public class DataStructureTests {
DATA_5(createTestDataType5(), List.of(createTestData51(), createTestData52(), createTestData53())), DATA_5(createTestDataType5(), List.of(createTestData51(), createTestData52(), createTestData53())),
// Tuple with wildcard type // Tuple with wildcard type
DATA_6(createTestDataType6(), List.of(createTestData61(), createTestData62())); DATA_6(createTestDataType6(), List.of(createTestData61(), createTestData62())),
// Wildcard type
DATA_7(createTestDataType7(), List.of(createTestData71(), createTestData72(), createTestData73()));
public DataType type; public DataType type;
@ -85,7 +88,7 @@ public class DataStructureTests {
} }
public static DataType createTestDataType2() { public static DataType createTestDataType2() {
return ArrayType.ofWildcard(); return ArrayType.of(WildcardType.of());
} }
public static DataStructureNode createTestData31() { public static DataStructureNode createTestData31() {
@ -134,7 +137,7 @@ public class DataStructureTests {
} }
public static DataType createTestDataType5() { public static DataType createTestDataType5() {
return ArrayType.ofWildcard(); return ArrayType.of(WildcardType.of());
} }
public static DataStructureNode createTestData61() { public static DataStructureNode createTestData61() {
@ -157,4 +160,23 @@ public class DataStructureTests {
public static DataType createTestDataType6() { public static DataType createTestDataType6() {
return TupleType.of(List.of("key1", "key2"), List.of(WildcardType.of(), WildcardType.of())); return TupleType.of(List.of("key1", "key2"), List.of(WildcardType.of(), WildcardType.of()));
} }
public static DataStructureNode createTestData71() {
return ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
}
public static DataStructureNode createTestData72() {
var val = ValueNode.of("value2".getBytes(StandardCharsets.UTF_8));
return TupleNode.builder().add("key1", val).build();
}
public static DataStructureNode createTestData73() {
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
var array = ArrayNode.of(List.of(val, ValueNode.nullValue()));
return array;
}
public static DataType createTestDataType7() {
return WildcardType.of();
}
} }

View file

@ -20,7 +20,7 @@ public interface DataSourceGuiProvider {
Region createConfigOptions(DataStore input, Property<? extends DataSourceDescriptor<?>> source); Region createConfigOptions(DataStore input, Property<? extends DataSourceDescriptor<?>> source);
DataSourceDescriptor<?> createDefaultDataSource(DataStore input); DataSourceDescriptor<?> createDefaultDataSource(DataStore input) throws Exception;
String getDisplayName(); String getDisplayName();