]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/Files.java
Allow loading databoard serialized files with type adapting
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / Files.java
1 /*******************************************************************************
2  * Copyright (c) 2010- Association for Decentralized Information Management in
3  * Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  * 
9  * Contributors:
10  *    VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard;
13
14 import java.io.DataInput;
15 import java.io.DataOutput;
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.OutputStream;
22 import java.io.OutputStreamWriter;
23 import java.nio.ByteBuffer;
24
25 import org.simantics.databoard.accessor.error.AccessorException;
26 import org.simantics.databoard.adapter.AdaptException;
27 import org.simantics.databoard.adapter.Adapter;
28 import org.simantics.databoard.adapter.AdapterConstructionException;
29 import org.simantics.databoard.binding.Binding;
30 import org.simantics.databoard.binding.RecordBinding;
31 import org.simantics.databoard.binding.error.BindingException;
32 import org.simantics.databoard.binding.mutable.MutableVariant;
33 import org.simantics.databoard.parser.repository.DataTypeSyntaxError;
34 import org.simantics.databoard.parser.repository.DataValueRepository;
35 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
36 import org.simantics.databoard.serialization.Serializer;
37 import org.simantics.databoard.serialization.SerializerConstructionException;
38 import org.simantics.databoard.type.Datatype;
39 import org.simantics.databoard.util.StreamUtil;
40 import org.simantics.databoard.util.binary.BinaryFile;
41 import org.simantics.databoard.util.binary.BinaryReadable;
42 import org.simantics.databoard.util.binary.ByteBufferReadable;
43 import org.simantics.databoard.util.binary.ByteBufferWriteable;
44 import org.simantics.databoard.util.binary.InputStreamReadable;
45 import org.simantics.databoard.util.binary.OutputStreamWriteable;
46 import org.simantics.databoard.util.binary.UTF8;
47
48 public class Files {
49         
50         /**
51          * Create a text file (.dbv) with a value. The file is UTF-8 encoded.  
52          * If old file exists, it is deleted.
53          * 
54          * @param file
55          * @param binding
56          * @param value
57          * @throws IOException 
58          */
59         public static void createTextFile(File file, Binding binding, Object value) 
60         throws IOException
61         {
62                 try {
63                         if (file.exists()) file.delete();
64                         file.createNewFile();
65                         
66                         String txt = binding.printValueDefinition(value, false);
67                         FileOutputStream fos = new FileOutputStream(file, false);
68                         try {
69                                 OutputStreamWriter os = new OutputStreamWriter(fos, UTF8.CHARSET);
70                                 os.append(txt);
71                                 os.flush();
72                                 os.close();
73                         } finally {
74                                 fos.close();
75                         }
76                 } catch(BindingException e) {
77                         throw new IOException(e);
78                 }
79         }
80         
81         /**
82          * Create a binary file (.dbb) with a initial value. Binary file is a variant, 
83          * there is a filetype in the header of the file.
84          * If old file exists, it is deleted.
85          * 
86          * @param file
87          * @param binding
88          * @param value
89          * @throws IOException 
90          */
91         public static void createFile(File file, Binding binding, Object value) 
92         throws IOException 
93         {
94                 if (file.exists()) file.delete();
95                 file.createNewFile();
96                 MutableVariant v = new MutableVariant(binding, value);
97                 Serializer s = Bindings.getSerializerUnchecked( Bindings.MUTABLE_VARIANT );
98                 s.serialize(v, file);
99         }
100
101         /**
102          * Create a new binary file (.dbb) with an empty value. Binary file is a variant, 
103          * there is a filetype in the header of the file.
104          * If old file exists, it is deleted.
105          * 
106          * @since 0.5
107          * @param file
108          * @throws IOException 
109          * @throws RuntimeSerializerConstructionException
110          */
111         public static void createFile(File file) throws IOException, RuntimeSerializerConstructionException  
112         {
113                 if (file.exists()) file.delete();
114                 file.createNewFile();
115                 BinaryFile bf = new BinaryFile(file);
116                 try {
117                         Binding binding = Bindings.MUTABLE_VARIANT;
118                         Object value = new MutableVariant(); 
119                         Serializer s = Bindings.getSerializerUnchecked( binding );
120                         s.serialize(bf, value);
121                 } finally {
122                         bf.close();
123                 }
124         }       
125
126         /**
127          * Create a binary file (.dbb) with empty value of given type. Binary file is a variant, 
128          * there is a filetype in the header of the file.
129          * If old file exists, it is deleted.
130          * 
131          * @param file
132          * @param type
133          * @throws IOException 
134          * @throws RuntimeSerializerConstructionException 
135          */
136         public static void createFile(File file, Datatype type) throws IOException, RuntimeSerializerConstructionException 
137         {
138                 if (file.exists()) file.delete();
139                 file.createNewFile();
140                 BinaryFile bf = new BinaryFile(file);
141                 try {
142                         Binding binding = Bindings.MUTABLE_VARIANT;
143                         Object value = binding.createDefault();
144                         Serializer s = Bindings.getSerializer( binding );
145                         s.serialize(bf, value);
146                 } catch (BindingException e) {
147                         throw new IOException(e);
148                 } catch (SerializerConstructionException e) {
149                         throw new IOException(e);
150                 } finally {
151                         bf.close();
152                 }
153         }
154         
155         
156         /**
157          * Read a text file (.dbv).   
158          * 
159          * @param file
160          * @param binding
161          * @return value
162          * @throws IOException 
163          * @throws BindingException 
164          * @throws DataTypeSyntaxError 
165          */
166         public static Object readTextFile(File file, Binding binding) 
167         throws IOException, DataTypeSyntaxError, BindingException 
168         {
169                 FileInputStream fis = new FileInputStream(file);
170                 try {
171                         byte[] data = StreamUtil.readFully(fis);
172                         String txt = new String(data, UTF8.CHARSET);
173                         DataValueRepository repo = new DataValueRepository();
174                         repo.setTypeRepository( Datatypes.datatypeRepository );
175                         return binding.parseValue(txt, repo);
176                 } finally {
177                         fis.close();
178                 }
179         }
180         
181         /**
182          * Read file type of a binary file. 
183          * 
184          * @param file
185          * @return datatype
186          * @throws IOException 
187          */
188         public static Datatype readFileType(File file) throws IOException {
189                 BinaryFile rf = new BinaryFile( file, "r" );
190                 try {
191                         return (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( rf );
192                 } finally {
193                         rf.close();
194                 }               
195         }
196         
197         /**
198          * Read a binary file into a java instance. Binary file is a variant, 
199          * there is a filetype in the header of the file. 
200          * If requested binding is not the exact binding of the file, an adapter is tried.
201          * 
202          * @param file file
203          * @param binding content binding
204          * @return instance
205          * @throws IOException 
206          */
207         public static Object readFile(File file, Binding binding) throws IOException {
208                 BinaryFile rf = new BinaryFile( file, "r" );
209                 try {
210                         Datatype type = (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( rf );
211                         
212                         if (type.equals(binding.type())) {
213                                 return Bindings.getSerializerUnchecked( binding ).deserialize(rf);
214                         } else {
215                                 try {
216                                         Binding fileContentBinding = Bindings.getMutableBinding(type);
217                                         Adapter adapter = Bindings.getAdapter(fileContentBinding, binding);
218                                         Object value = Bindings.getSerializerUnchecked( fileContentBinding ).deserialize(rf);
219                                         return adapter.adapt( value );
220                                 } catch (AdapterConstructionException e) {
221                                         throw new IOException(e);
222                                 } catch (AdaptException e) {
223                                         throw new IOException(e);
224                                 }
225                         }
226                 } finally {
227                         rf.close();
228                 }
229         }
230         
231         public static Object readFileTypeAdapting(File file, Binding binding) throws IOException {
232         BinaryFile rf = new BinaryFile( file, "r" );
233         try {
234             Datatype type = (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( rf );
235             
236             if (type.equals(binding.type())) {
237                 return Bindings.getSerializerUnchecked( binding ).deserialize(rf);
238             } else {
239                 try {
240                     Binding fileContentBinding = Bindings.getMutableBinding(type);
241                     Adapter adapter = Bindings.getTypeAdapter(fileContentBinding, binding);
242                     Object value = Bindings.getSerializerUnchecked( fileContentBinding ).deserialize(rf);
243                     return adapter.adapt( value );
244                 } catch (AdapterConstructionException e) {
245                     throw new IOException(e);
246                 } catch (AdaptException e) {
247                     throw new IOException(e);
248                 }
249             }
250         } finally {
251             rf.close();
252         }
253     }
254
255         /**
256          * Read a file to an object.
257          * 
258          * @param file
259          * @param binding
260          * @param dst
261          * @throws IOException 
262          */
263         public static void readFile(File file, RecordBinding binding, Object dst) throws IOException {
264                 BinaryFile rf = new BinaryFile( file, "r" );
265                 try {
266                         Datatype type = (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( rf );
267                         
268                         if (type.equals(binding.type())) {
269                                 Serializer s = Bindings.getSerializerUnchecked( binding ); 
270                                 s.deserializeTo(rf, dst);
271                         } else {
272                                 try {
273                                         Binding fileContentBinding = Bindings.getMutableBinding(type);
274                                         Serializer s = Bindings.getSerializerUnchecked( fileContentBinding );
275                                         Object tmpObj = s.deserialize( rf );                                    
276                                         binding.readFrom(fileContentBinding, tmpObj, dst);
277                                 } catch (BindingException e) {
278                                         throw new IOException(e);
279                                 }
280                         }
281                 } finally {
282                         rf.close();
283                 }
284         }
285         
286         /**
287          * Read input stream into a java instance. Binary file is a variant, 
288          * there is a filetype in the header of the file. If requested binding is not the 
289          * exact binding of the file, an adapter is tried.<p>
290          * 
291          * The implementation reads the inputstream fully into memory.<p>
292          * 
293          * @param is input stream
294          * @param binding content binding
295          * @return instance
296          * @throws IOException 
297          */
298         public static Object readFile(InputStream is, Binding binding) throws IOException {
299                 BinaryReadable readable = InputStreamReadable.readFully( is );
300                 Datatype type = (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( readable );
301                         
302                 if (!type.equals(binding.type())) {
303                         try {
304                                 Binding fileContentBinding = Bindings.getMutableBinding(type);
305                                 Adapter adapter = Bindings.getAdapter(fileContentBinding, binding);
306                                 Object value = Bindings.getSerializerUnchecked( fileContentBinding ).deserialize( readable );
307                                 return adapter.adapt( value );
308                         } catch (AdapterConstructionException e) {
309                                 throw new IOException(e);
310                         } catch (AdaptException e) {
311                                 throw new IOException(e);
312                         }
313                 }
314                         
315                 return Bindings.getSerializerUnchecked( binding ).deserialize( readable );
316         }
317         
318         /**
319          * Read input stream into a java instance. If requested binding is not the 
320          * exact binding of the file, an adapter is tried.
321          * 
322          * @param is input stream
323          * @param streamLength
324          * @param binding content binding
325          * @return instance
326          * @throws IOException 
327          * @throws AccessorException 
328          */
329         public static Object readFile(InputStream is, long streamLength, Binding binding) throws IOException {
330                 BinaryReadable readable = new InputStreamReadable( is, streamLength );
331                 Datatype type = (Datatype) Bindings.getSerializerUnchecked( Bindings.DATATYPE ).deserialize( readable );
332                         
333                 if (!type.equals(binding.type())) {
334                         try {
335                                 Binding fileContentBinding = Bindings.getMutableBinding(type);
336                                 Adapter adapter = Bindings.getAdapter(fileContentBinding, binding);
337                                 Object value = Bindings.getSerializerUnchecked( fileContentBinding ).deserialize( readable );
338                                 return adapter.adapt( value );
339                         } catch (AdapterConstructionException e) {
340                                 throw new IOException(e);
341                         } catch (AdaptException e) {
342                                 throw new IOException(e);
343                         }
344                 }
345                         
346                 return Bindings.getSerializerUnchecked( binding ).deserialize( readable );
347         }
348
349         /**
350          * Write value as binary file (.dbb).
351          * 
352          * @param file file
353          * @param binding content binding
354          * @param value value
355          * @throws IOException 
356          */
357         public static void writeFile(File file, Binding binding, Object value) throws IOException {
358                 BinaryFile rf = new BinaryFile( file );
359                 try {
360                         MutableVariant v = new MutableVariant(binding, value);
361                         Serializer s = Bindings.getSerializerUnchecked( Bindings.MUTABLE_VARIANT );
362                         s.serialize(rf, v);
363                 } finally {
364                         rf.close();
365                 }
366         }       
367
368         public static DataInput openInput( InputStream is )
369         {
370                 return new InputStreamReadable(is, Long.MAX_VALUE);
371         }
372         
373         public static DataInput openInput( File file ) throws IOException
374         {
375                 return new BinaryFile(file, "r");
376         }
377         
378         public static DataInput openInput( byte[] data ) 
379         {
380                 ByteBuffer buffer = ByteBuffer.wrap( data );
381                 return new ByteBufferReadable( buffer );
382         }
383         
384         public static DataOutput openOutput( OutputStream os )
385         {
386                 return new OutputStreamWriteable( os );
387         }
388         
389         public static DataOutput openOutput( File file ) throws IOException
390         {
391                 return new BinaryFile( file );
392         }
393         
394         public static DataOutput openOutput( byte[] data ) throws IOException
395         {
396                 ByteBuffer buffer = ByteBuffer.wrap( data );
397                 return new ByteBufferWriteable( buffer );
398         }       
399
400 }
401