]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphFileReader.java
Remove duplicate InputChannel inner classes
[simantics/platform.git] / bundles / org.simantics.graph / src / org / simantics / graph / representation / TransferableGraphFileReader.java
1 package org.simantics.graph.representation;
2
3 import java.io.DataInput;
4 import java.io.DataInputStream;
5 import java.io.File;
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;
12
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;
24
25
26 /**
27  * It is recommended to use {@link #read(File)} and {@link #read(InputStream)}
28  * for reading to ensure proper resource handling.
29  */
30 final public class TransferableGraphFileReader extends ByteFileReader {
31
32     private static final Logger LOGGER = LoggerFactory.getLogger(TransferableGraphFileReader.class);
33
34         InputStream in = new InputStream() {
35
36         @Override
37         public int read() throws IOException {
38             return getByte();
39         }
40         
41         @Override
42         public int read(byte[] b) throws IOException {
43             // FIXME not correctly implemented                
44             System.arraycopy(safeBytes(b.length), 0, b, 0, b.length);
45             return b.length;
46         }
47         
48         @Override
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);
52             return len;
53         }
54             
55         };
56
57         private static boolean init = true;
58
59         final private static int SIZE = 1<<18;
60         final private static int HEADER = headerSize();
61         final private int header;
62
63         /**
64          * Reads a {@link DataContainer} containing a {@link TransferableGraph1}
65          * structure from the specified {@link File}.
66          * 
67          * @param file the file to read from
68          * @return the TG contained by the file
69          * @throws IOException
70          */
71         public static TransferableGraph1 read(File file) throws IOException {
72                 try (TransferableGraphFileReader reader = new TransferableGraphFileReader(file)) {
73                         return reader.readTG();
74                 }
75         }
76
77         /**
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.
82          * 
83          * @param input the input stream to read from
84          * @return the TG contained by the stream
85          * @throws IOException
86          */
87         public static TransferableGraph1 read(InputStream input) throws IOException {
88                 try (TransferableGraphFileReader reader = new TransferableGraphFileReader(input)) {
89                         return reader.readTG();
90                 }
91         }
92
93         public TransferableGraphFileReader(File file) throws IOException {
94                 super(file, SIZE);
95                 if(init) {
96                         init=false;
97                         TransferableGraphFileReader r = new TransferableGraphFileReader(file, 0);
98                         for(int i=0;i<40000;i++) r.readTG();
99                 }
100                 this.header = HEADER;
101         }
102         
103         public TransferableGraphFileReader(InputStream stream) throws IOException {
104                 super(null, new InputChannel(stream), SIZE);
105                 if(init) {
106                         init=false;
107                         TransferableGraphFileReader r = new TransferableGraphFileReader(stream, 0);
108                         for(int i=0;i<40000;i++) r.readTG();
109                 }
110                 this.header = 0;
111         }
112
113         public TransferableGraphFileReader(ReadableByteChannel channel) throws IOException {
114                 super(null, channel, SIZE);
115                 if(init) {
116                         init=false;
117                         TransferableGraphFileReader r = new TransferableGraphFileReader(channel, 0);
118                         for(int i=0;i<40000;i++) r.readTG();
119                 }
120                 this.header = 0;
121         }
122
123         public TransferableGraphFileReader(ReadableByteChannel channel, int size) throws IOException {
124                 super(null, channel, SIZE);
125                 this.header = 0;
126         }
127
128         public TransferableGraphFileReader(InputStream stream, int size) throws IOException {
129                 super(null, new InputChannel(stream), size);
130                 this.header = 0;
131         }
132
133         public TransferableGraphFileReader(File file, int size) throws IOException {
134                 super(file, size);
135                 this.header = HEADER;
136         }
137
138         private static int headerSize() {
139                 try {
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);
147                 }               
148         }
149         
150         public TransferableGraph1 readTG() throws IOException {
151
152                 if(getSize() == 0) return null;
153                 
154 //              long start = System.nanoTime();
155
156                 final byte[] bytes = getBytes();
157                 
158 //              byteIndex = header;
159
160                 DataInputStream dis = new DataInputStream(in);
161
162                 // Header
163                 DataContainers.readHeader(dis);
164                 
165                 // Content variant data type
166                 Bindings.getSerializerUnchecked(Datatype.class).deserialize((DataInput)dis);
167
168                 int resourceCount = safeInt();
169                 
170                 List<Object> idcontext = new ArrayList<>(); 
171                 dis = new DataInputStream(in);
172                 Extensions extensions = (Extensions)Bindings.getSerializerUnchecked(Extensions.class).deserialize((DataInput)dis, idcontext);
173                 
174                 int identities = safeInt();
175                 Identity[] ids = new Identity[identities];
176
177 //              LOGGER.warn("rc: " + resourceCount);
178 //              LOGGER.warn("ids: " + identities);
179                 
180 //              long duration = System.nanoTime() - start;
181 //              LOGGER.warn("start in " + 1e-9*duration + "s.");
182 //              start = System.nanoTime();
183
184                 for(int i=0;i<identities;i++) {
185                         int rid = safeInt();
186                         byte type = bytes[byteIndex++];
187                         // External
188                         if(type == 1) {
189
190                                 int parent = safeInt();
191                                 int nameLen = getDynamicUInt32();
192
193                                 if(byteIndex+nameLen < SIZE) {
194                                         ids[i] = new Identity(rid, new External(parent, utf(bytes, byteIndex, byteIndex + nameLen)));
195                                         byteIndex += nameLen;
196                                 } else {
197                                         ids[i] = new Identity(rid, new External(parent, utf(safeBytes(nameLen), 0, nameLen)));
198                                 }
199
200                         } 
201                         // Internal
202                         else if(type == 3) {
203
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;
209                                 } else {
210                                         ids[i] = new Identity(rid, new Internal(parent, utf(safeBytes(nameLen), 0, nameLen)));
211                                 }
212                                 
213                         }
214                         // Root
215                         else if(type == 0) {
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));
221
222                         } else if(type == 2) {
223                                 throw new UnsupportedOperationException();
224                         } else {
225                                 throw new IllegalStateException();
226                         }
227
228                 }
229
230 //              for(Identity id : ids) LOGGER.warn("id: " + id);
231
232                 
233 //              duration = System.nanoTime() - start;
234 //              LOGGER.warn("ids in " + 1e-9*duration + "s.");
235 //              start = System.nanoTime();
236
237                 int stmLength = safeInt();
238 //              LOGGER.warn("statements: " + stmLength + " (" + byteIndex + ")");
239                 
240                 int[] statements = new int[stmLength];
241
242                 for(int stmIndex=0;stmIndex<stmLength;) {
243
244                         statements[stmIndex++] = safeInt();
245                         
246                         // Cached bytes 
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));                              
251                         }
252                         byteIndex += allowed<<2;
253                         
254                 }
255
256 //              duration = System.nanoTime() - start;
257 //              LOGGER.warn("stms in " + 1e-9*duration + "s.");
258 //              
259 //              start = System.nanoTime();
260
261                 int valueLength = safeInt();
262 //              LOGGER.warn("values: " + valueLength + " (" + byteIndex + ")");
263
264                 Value[] values = new Value[valueLength]; 
265
266                 Serializer variantSerializer = Bindings.getSerializerUnchecked(Bindings.VARIANT);
267                 
268                 dis = new DataInputStream(in);
269                 
270                 for(int i=0;i<valueLength;i++) {
271                         int resource = safeInt();
272                         //idcontext.clear();
273                         Variant value = (Variant)variantSerializer
274                                 .deserialize((DataInput)dis, idcontext);
275                         values[i] = new Value(resource, value);
276                         
277                         //LOGGER.warn("read variant[" + resource + "]: " + value.toString().substring(0, Math.min(100, value.toString().length())));
278                         
279                 }
280
281                 
282 //              duration = System.nanoTime() - start;
283 //              LOGGER.warn("values in " + 1e-9*duration + "s.");
284                 
285                 return new TransferableGraph1(resourceCount, ids, statements, values, extensions.map);
286
287         }
288         
289         public static void main(String[] args) {
290
291                 try {
292                         
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();
297                         reader.readTG();
298                         long d = System.nanoTime() - s;
299                         LOGGER.warn("Duration=" + 1e-9*d + "s.");
300                         
301                         
302                 } catch (Throwable t) {
303                         t.printStackTrace();
304                 }
305                 
306         }
307
308 }