X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=inline;f=bundles%2Forg.simantics.graph%2Fsrc%2Forg%2Fsimantics%2Fgraph%2Frepresentation%2FTransferableGraphFileReader.java;h=c7cc415045c490c7cb2f496a1db7af387a1c8035;hb=d4a7620f4d36d1ab9f285497586e55725e48d219;hp=ae1ec711ce676e9d3932cbbbc10485601cbb2f1d;hpb=1dfeb7d5c49b1391cd9d877e1eddab18995cb151;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphFileReader.java b/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphFileReader.java index ae1ec711c..c7cc41504 100644 --- a/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphFileReader.java +++ b/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphFileReader.java @@ -5,15 +5,16 @@ import java.io.DataInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.util.ArrayList; import java.util.List; import org.simantics.databoard.Bindings; import org.simantics.databoard.Datatypes; +import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.error.RuntimeDatatypeConstructionException; import org.simantics.databoard.binding.mutable.Variant; +import org.simantics.databoard.container.DataContainer; import org.simantics.databoard.container.DataContainers; import org.simantics.databoard.serialization.RuntimeSerializerConstructionException; import org.simantics.databoard.serialization.Serializer; @@ -22,8 +23,48 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * It is recommended to use {@link #read(File)} and {@link #read(InputStream)} + * for reading to ensure proper resource handling. + * + *
+ * It is important to use the correct setting for
+ * {@link #sharedValueContext(boolean)} which depends on how the TG was
+ * serialized to begin with. See {@link #DEFAULT_SHARED_VALUE_CONTEXT} for more
+ * information on this.
+ */
final public class TransferableGraphFileReader extends ByteFileReader {
+ /**
+ * Serializing TransferableGraph1 structures using the default {@link Binding}
+ * will use shared context for serializing the values Variant array. Thus all TG
+ * files produced by the graph compiler use a shared value context which means
+ * this class must be used with {@link #sharedValueContext(boolean)} set to
+ * true. As an example, true
must be used if the corresponding TG
+ * file is written e.g. like this:
+ *
+ * DataContainers.writeFile(location + * new DataContainer(format, + * version, + * metadata, + * new Variant(TransferableGraph1.BINDING, tg))); + *+ * + *
+ * On the other hand, any TG files serialized using more optimized methods like
+ * ModelTransferableGraphSource
do not use a shared value context
+ * when writing the file. This means those files cannot be read safely using
+ * standard {@link Binding} at all, and when using this class,
+ * {@link #sharedValueContext(boolean)} must be set to false to prevent the
+ * import from corrupting datatype values because the referable parts of
+ * datatypes may get bound to the wrong existing types if the data is read using
+ * shared context.
+ *
+ *
+ * true
is the default setting.
+ */
+ public static final boolean DEFAULT_SHARED_VALUE_CONTEXT = true;
+
private static final Logger LOGGER = LoggerFactory.getLogger(TransferableGraphFileReader.class);
InputStream in = new InputStream() {
@@ -48,42 +89,70 @@ final public class TransferableGraphFileReader extends ByteFileReader {
}
};
-
-
- final static class InputChannel implements ReadableByteChannel {
- final private InputStream stream;
-
- public InputChannel(InputStream stream) {
- this.stream = stream;
- }
-
- @Override
- public boolean isOpen() {
- return true;
- }
+ private static boolean init = true;
+
+ final private static int SIZE = 1<<18;
+ final private static int HEADER = headerSize();
+ final private int header;
+ private boolean shareValueContext = true;
+
+ /**
+ * Reads a {@link DataContainer} containing a {@link TransferableGraph1}
+ * structure from the specified {@link File}.
+ *
+ * @param file the file to read from
+ * @return the TG contained by the file
+ * @throws IOException
+ */
+ public static TransferableGraph1 read(File file) throws IOException {
+ return read(file, DEFAULT_SHARED_VALUE_CONTEXT);
+ }
+
+ /**
+ * Reads a {@link DataContainer} containing a {@link TransferableGraph1}
+ * structure from the specified InputStream. Note that this implementation does
+ * not close the specified input
stream, it is expected to be
+ * closed by the caller.
+ *
+ * @param input the input stream to read from
+ * @return the TG contained by the stream
+ * @throws IOException
+ */
+ public static TransferableGraph1 read(InputStream input) throws IOException {
+ return read(input, DEFAULT_SHARED_VALUE_CONTEXT);
+ }
- @Override
- public void close() throws IOException {
+ /**
+ * Reads a {@link DataContainer} containing a {@link TransferableGraph1}
+ * structure from the specified {@link File}.
+ *
+ * @param file the file to read from
+ * @return the TG contained by the file
+ * @throws IOException
+ */
+ public static TransferableGraph1 read(File file, boolean sharedValueContext) throws IOException {
+ try (TransferableGraphFileReader reader = new TransferableGraphFileReader(file)) {
+ return reader.sharedValueContext(sharedValueContext).readTG();
}
+ }
- @Override
- public int read(ByteBuffer dst) throws IOException {
- int pos = dst.position();
- int limit = dst.limit();
- int i=stream.read(dst.array(), pos, limit-pos);
- //LOGGER.warn("Read " + i + " (expected " + dst.array().length + ")");
- return i;
+ /**
+ * Reads a {@link DataContainer} containing a {@link TransferableGraph1}
+ * structure from the specified InputStream. Note that this implementation does
+ * not close the specified input
stream, it is expected to be
+ * closed by the caller.
+ *
+ * @param input the input stream to read from
+ * @return the TG contained by the stream
+ * @throws IOException
+ */
+ public static TransferableGraph1 read(InputStream input, boolean sharedValueContext) throws IOException {
+ try (TransferableGraphFileReader reader = new TransferableGraphFileReader(input)) {
+ return reader.sharedValueContext(sharedValueContext).readTG();
}
-
}
-
- private static boolean init = true;
-
- final private static int SIZE = 1<<18;
- final private static int HEADER = headerSize();
- final private int header;
-
+
public TransferableGraphFileReader(File file) throws IOException {
super(file, SIZE);
if(init) {
@@ -129,6 +198,11 @@ final public class TransferableGraphFileReader extends ByteFileReader {
this.header = HEADER;
}
+ public TransferableGraphFileReader sharedValueContext(boolean share) {
+ this.shareValueContext = share;
+ return this;
+ }
+
private static int headerSize() {
try {
return Bindings.getSerializerUnchecked(Datatype.class).serialize(Datatypes.getDatatypeUnchecked(TransferableGraph1.class)).length;
@@ -140,7 +214,7 @@ final public class TransferableGraphFileReader extends ByteFileReader {
throw new Error("Failed to determine TransferableGraph1 header size. ", e);
}
}
-
+
public TransferableGraph1 readTG() throws IOException {
if(getSize() == 0) return null;
@@ -161,7 +235,7 @@ final public class TransferableGraphFileReader extends ByteFileReader {
int resourceCount = safeInt();
- List