1 package org.simantics.graph.representation;
3 import java.io.DataInput;
4 import java.io.DataInputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.nio.ByteBuffer;
9 import java.nio.channels.ReadableByteChannel;
10 import java.util.ArrayList;
11 import java.util.List;
13 import org.simantics.databoard.Bindings;
14 import org.simantics.databoard.Datatypes;
15 import org.simantics.databoard.binding.error.RuntimeDatatypeConstructionException;
16 import org.simantics.databoard.binding.mutable.Variant;
17 import org.simantics.databoard.container.DataContainer;
18 import org.simantics.databoard.container.DataContainers;
19 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
20 import org.simantics.databoard.serialization.Serializer;
21 import org.simantics.databoard.type.Datatype;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
27 * It is recommended to use {@link #read(File)} and {@link #read(InputStream)}
28 * for reading to ensure proper resource handling.
30 final public class TransferableGraphFileReader extends ByteFileReader {
32 private static final Logger LOGGER = LoggerFactory.getLogger(TransferableGraphFileReader.class);
34 InputStream in = new InputStream() {
37 public int read() throws IOException {
42 public int read(byte[] b) throws IOException {
43 // FIXME not correctly implemented
44 System.arraycopy(safeBytes(b.length), 0, b, 0, b.length);
49 public int read(byte[] b, int off, int len) throws IOException {
50 // FIXME not correctly implemented
51 System.arraycopy(safeBytes(len), 0, b, off, len);
57 private static boolean init = true;
59 final private static int SIZE = 1<<18;
60 final private static int HEADER = headerSize();
61 final private int header;
64 * Reads a {@link DataContainer} containing a {@link TransferableGraph1}
65 * structure from the specified {@link File}.
67 * @param file the file to read from
68 * @return the TG contained by the file
71 public static TransferableGraph1 read(File file) throws IOException {
72 try (TransferableGraphFileReader reader = new TransferableGraphFileReader(file)) {
73 return reader.readTG();
78 * Reads a {@link DataContainer} containing a {@link TransferableGraph1}
79 * structure from the specified InputStream. Note that this implementation does
80 * not close the specified <code>input</code> stream, it is expected to be
81 * closed by the caller.
83 * @param input the input stream to read from
84 * @return the TG contained by the stream
87 public static TransferableGraph1 read(InputStream input) throws IOException {
88 try (TransferableGraphFileReader reader = new TransferableGraphFileReader(input)) {
89 return reader.readTG();
93 public TransferableGraphFileReader(File file) throws IOException {
97 TransferableGraphFileReader r = new TransferableGraphFileReader(file, 0);
98 for(int i=0;i<40000;i++) r.readTG();
100 this.header = HEADER;
103 public TransferableGraphFileReader(InputStream stream) throws IOException {
104 super(null, new InputChannel(stream), SIZE);
107 TransferableGraphFileReader r = new TransferableGraphFileReader(stream, 0);
108 for(int i=0;i<40000;i++) r.readTG();
113 public TransferableGraphFileReader(ReadableByteChannel channel) throws IOException {
114 super(null, channel, SIZE);
117 TransferableGraphFileReader r = new TransferableGraphFileReader(channel, 0);
118 for(int i=0;i<40000;i++) r.readTG();
123 public TransferableGraphFileReader(ReadableByteChannel channel, int size) throws IOException {
124 super(null, channel, SIZE);
128 public TransferableGraphFileReader(InputStream stream, int size) throws IOException {
129 super(null, new InputChannel(stream), size);
133 public TransferableGraphFileReader(File file, int size) throws IOException {
135 this.header = HEADER;
138 private static int headerSize() {
140 return Bindings.getSerializerUnchecked(Datatype.class).serialize(Datatypes.getDatatypeUnchecked(TransferableGraph1.class)).length;
141 } catch (RuntimeSerializerConstructionException e) {
142 throw new Error("Failed to determine TransferableGraph1 header size. ", e);
143 } catch (RuntimeDatatypeConstructionException e) {
144 throw new Error("Failed to determine TransferableGraph1 header size. ", e);
145 } catch (IOException e) {
146 throw new Error("Failed to determine TransferableGraph1 header size. ", e);
150 public TransferableGraph1 readTG() throws IOException {
152 if(getSize() == 0) return null;
154 // long start = System.nanoTime();
156 final byte[] bytes = getBytes();
158 // byteIndex = header;
160 DataInputStream dis = new DataInputStream(in);
163 DataContainers.readHeader(dis);
165 // Content variant data type
166 Bindings.getSerializerUnchecked(Datatype.class).deserialize((DataInput)dis);
168 int resourceCount = safeInt();
170 List<Object> idcontext = new ArrayList<>();
171 dis = new DataInputStream(in);
172 Extensions extensions = (Extensions)Bindings.getSerializerUnchecked(Extensions.class).deserialize((DataInput)dis, idcontext);
174 int identities = safeInt();
175 Identity[] ids = new Identity[identities];
177 // LOGGER.warn("rc: " + resourceCount);
178 // LOGGER.warn("ids: " + identities);
180 // long duration = System.nanoTime() - start;
181 // LOGGER.warn("start in " + 1e-9*duration + "s.");
182 // start = System.nanoTime();
184 for(int i=0;i<identities;i++) {
186 byte type = bytes[byteIndex++];
190 int parent = safeInt();
191 int nameLen = getDynamicUInt32();
193 if(byteIndex+nameLen < SIZE) {
194 ids[i] = new Identity(rid, new External(parent, utf(bytes, byteIndex, byteIndex + nameLen)));
195 byteIndex += nameLen;
197 ids[i] = new Identity(rid, new External(parent, utf(safeBytes(nameLen), 0, nameLen)));
204 int parent = safeInt();
205 int nameLen = getDynamicUInt32();
206 if(byteIndex+nameLen < SIZE) {
207 ids[i] = new Identity(rid, new Internal(parent, utf(bytes, byteIndex, byteIndex + nameLen)));
208 byteIndex += nameLen;
210 ids[i] = new Identity(rid, new Internal(parent, utf(safeBytes(nameLen), 0, nameLen)));
216 int nameLen = getDynamicUInt32();
217 String name = utf(safeBytes(nameLen), 0, nameLen);
218 int nameLen2 = getDynamicUInt32();
219 String rType = utf(safeBytes(nameLen2), 0, nameLen2);
220 ids[i] = new Identity(rid, new Root(name, rType));
222 } else if(type == 2) {
223 throw new UnsupportedOperationException();
225 throw new IllegalStateException();
230 // for(Identity id : ids) LOGGER.warn("id: " + id);
233 // duration = System.nanoTime() - start;
234 // LOGGER.warn("ids in " + 1e-9*duration + "s.");
235 // start = System.nanoTime();
237 int stmLength = safeInt();
238 // LOGGER.warn("statements: " + stmLength + " (" + byteIndex + ")");
240 int[] statements = new int[stmLength];
242 for(int stmIndex=0;stmIndex<stmLength;) {
244 statements[stmIndex++] = safeInt();
247 int avail = (SIZE-byteIndex) >> 2;
248 int allowed = Math.min(stmLength-stmIndex, avail);
249 for(int index = byteIndex, i=0;i<allowed;i++) {
250 statements[stmIndex++] = ((bytes[index++]&0xff)<<24) | ((bytes[index++]&0xff)<<16) | ((bytes[index++]&0xff)<<8) | ((bytes[index++]&0xff));
252 byteIndex += allowed<<2;
256 // duration = System.nanoTime() - start;
257 // LOGGER.warn("stms in " + 1e-9*duration + "s.");
259 // start = System.nanoTime();
261 int valueLength = safeInt();
262 // LOGGER.warn("values: " + valueLength + " (" + byteIndex + ")");
264 Value[] values = new Value[valueLength];
266 Serializer variantSerializer = Bindings.getSerializerUnchecked(Bindings.VARIANT);
268 dis = new DataInputStream(in);
270 for(int i=0;i<valueLength;i++) {
271 int resource = safeInt();
273 Variant value = (Variant)variantSerializer
274 .deserialize((DataInput)dis, idcontext);
275 values[i] = new Value(resource, value);
277 //LOGGER.warn("read variant[" + resource + "]: " + value.toString().substring(0, Math.min(100, value.toString().length())));
282 // duration = System.nanoTime() - start;
283 // LOGGER.warn("values in " + 1e-9*duration + "s.");
285 return new TransferableGraph1(resourceCount, ids, statements, values, extensions.map);
289 public static void main(String[] args) {
293 File file = new File("c:/users/antti villberg/desktop/test.apros");
294 TransferableGraphFileReader reader = new TransferableGraphFileReader(file, SIZE);
295 reader = new TransferableGraphFileReader(file);
296 long s = System.nanoTime();
298 long d = System.nanoTime() - s;
299 LOGGER.warn("Duration=" + 1e-9*d + "s.");
302 } catch (Throwable t) {