]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/container/DataContainers.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / container / DataContainers.java
1 package org.simantics.databoard.container;\r
2 \r
3 import java.io.DataInput;\r
4 import java.io.DataInputStream;\r
5 import java.io.DataOutput;\r
6 import java.io.File;\r
7 import java.io.FileInputStream;\r
8 import java.io.IOException;\r
9 import java.io.InputStream;\r
10 import java.util.Map;\r
11 import java.util.TreeMap;\r
12 \r
13 import org.simantics.databoard.Bindings;\r
14 import org.simantics.databoard.binding.Binding;\r
15 import org.simantics.databoard.binding.impl.TreeMapBinding;\r
16 import org.simantics.databoard.binding.mutable.Variant;\r
17 import org.simantics.databoard.serialization.Serializer;\r
18 import org.simantics.databoard.type.Datatype;\r
19 import org.simantics.databoard.util.binary.BinaryFile;\r
20 \r
21 /**\r
22  * An utility class for reading files whose format follows\r
23  * {@link DataContainer}.\r
24  * @author Hannu Niemistö\r
25  */\r
26 public class DataContainers {\r
27 \r
28     private static final Serializer STRING_SERIALIZER = \r
29             Bindings.getSerializerUnchecked(Bindings.STRING);\r
30     private static final Serializer INTEGER_SERIALIZER = \r
31             Bindings.getSerializerUnchecked(Bindings.INTEGER);\r
32     private static final Serializer METADATA_SERIALIZER = \r
33             Bindings.getSerializerUnchecked(new TreeMapBinding(Bindings.STRING, Bindings.VARIANT));\r
34     private static final Serializer DATATYPE_SERIALIZER =\r
35             Bindings.getSerializerUnchecked(Datatype.class);\r
36     private static final Serializer VARIANT_SERIALIZER =\r
37             Bindings.getSerializerUnchecked(Bindings.VARIANT);\r
38     private static final Serializer DATA_CONTAINER_SERIALIZER =\r
39             Bindings.getSerializerUnchecked(DataContainer.class);\r
40 \r
41     /**\r
42      * Binds a format name and a version together to form a format version\r
43      * identifier string.\r
44      * \r
45      * @param formatName\r
46      * @param version\r
47      * @return\r
48      */\r
49     public static String toFormatString(String formatName, int version) {\r
50         return formatName + ":" + version;\r
51     }\r
52 \r
53     /**\r
54      * Reads only the header of the data container. Returns\r
55      * a DataContainer whose content-field is null.\r
56      * @throws IOException \r
57      */\r
58     public static DataContainer readHeader(DataInput input) throws IOException {\r
59         String format = (String)STRING_SERIALIZER.deserialize(input);\r
60         int version = (Integer)INTEGER_SERIALIZER.deserialize(input);\r
61         @SuppressWarnings("unchecked")\r
62                 TreeMap<String,Variant> metadata = (TreeMap<String,Variant>)METADATA_SERIALIZER.deserialize(input); \r
63         return new DataContainer(format, version, metadata, null);\r
64     }\r
65     \r
66     /**\r
67      * Consumes a header from a given stream and checks that the header satisfies the given format and version.\r
68      * Returns the obtained header if the check fails and null on success.\r
69      * @throws IOException \r
70      */\r
71     public static DataContainer requireHeader(DataInput input, String format, int version) {\r
72                 try {\r
73                         DataContainer header = readHeader(input);\r
74                         if(!format.equals(header.format) || version != header.version)\r
75                                 return header;\r
76                         else return null;\r
77                 } catch (Throwable t) {\r
78                         return new DataContainer("unknown", 0, null, null);\r
79                 }\r
80     }\r
81 \r
82     /**\r
83      * Consumes a header from a given stream and checks that the header satisfies the given format and version restrictions.\r
84      * Returns the obtained header if the check fails and null on success.\r
85      * @throws IOException \r
86      */\r
87     public static DataContainer requireHeader(DataInput input, String... requiredFormatStrings) {\r
88         try {\r
89             DataContainer header = readHeader(input);\r
90             String formatString = toFormatString(header.format, header.version);\r
91             for (String requiredFormatString : requiredFormatStrings) {\r
92                 if(formatString.equals(requiredFormatString))\r
93                     return null;\r
94             }\r
95             return header;\r
96         } catch (Throwable t) {\r
97             return new DataContainer("unknown", 0, null, null);\r
98         }\r
99     }\r
100 \r
101     /**\r
102      * Checks that the given file satisfies the given format and version. \r
103      * Returns the obtained header if the check fails and null on success.\r
104      * @throws IOException \r
105      */\r
106     public static DataContainer validateHeader(File file, String format, int version) throws IOException {\r
107 \r
108         InputStream stream = new FileInputStream( file );\r
109         try {\r
110                 return DataContainers.requireHeader(new DataInputStream(stream), format, version);\r
111         } finally {\r
112                 stream.close();\r
113         }\r
114         \r
115     }\r
116 \r
117     /**\r
118      * Checks that the given file satisfies the given format and version. \r
119      * Returns the obtained header if the check fails and null on success.\r
120      * @throws IOException \r
121      */\r
122     public static DataContainer validateHeader(File file, String... allowedFormatStrings) throws IOException {\r
123 \r
124         InputStream stream = new FileInputStream( file );\r
125         try {\r
126             return DataContainers.requireHeader(new DataInputStream(stream), allowedFormatStrings);\r
127         } finally {\r
128             stream.close();\r
129         }\r
130         \r
131     }\r
132 \r
133     /**\r
134      * Reads only the header of the data container. Returns\r
135      * a DataContainer whose content-field is null.\r
136      * @throws IOException \r
137      */\r
138     public static DataContainer readHeader(File input) throws IOException {\r
139         BinaryFile rf = new BinaryFile( input, "r" );\r
140         try {\r
141             return readHeader(rf);\r
142         } finally {\r
143             rf.close();\r
144         }       \r
145     }\r
146     \r
147     /**\r
148      * Reads a data container including the content data.\r
149      * @throws IOException \r
150      */\r
151     public static DataContainer readFile(DataInput input) throws IOException {\r
152         DataContainer result = readHeader(input);\r
153         result.content = (Variant)VARIANT_SERIALIZER.deserialize(input);\r
154         return result;\r
155     }\r
156 \r
157     /**\r
158      * Process a data container using a format handler matching the format and version\r
159      * of the file. \r
160      * @param handlers Map of handlers. Keys are strings of form "format:version".\r
161      */\r
162     public static <T> T readFile(DataInput input, Map<String, FormatHandler<T>> handlers) throws Exception {\r
163         DataContainer result = readHeader(input);\r
164         \r
165         FormatHandler<T> handler = handlers.get(result.format + ":" + result.version);\r
166         if(handler == null)\r
167             throw new DataFormatException("Unknown data format " + result.format + " version " + result.version + ".");\r
168         Binding binding = handler.getBinding();\r
169         \r
170         Datatype contentType = (Datatype)DATATYPE_SERIALIZER.deserialize(input);\r
171         if(!binding.type().equals(contentType))\r
172             throw new DataFormatException("Content type didn't match the type expected for the format " + result.format + " version " + result.version + ".");\r
173         \r
174         Object value = Bindings.getSerializerUnchecked(binding).deserialize(input);\r
175         \r
176         result.content = new Variant(binding, value);\r
177         return handler.process(result);\r
178     }\r
179     \r
180     /**\r
181      * Reads a data container including the content data.\r
182      * @throws IOException \r
183      */\r
184     public static DataContainer readFile(File input) throws IOException {\r
185         BinaryFile rf = new BinaryFile( input, "r" );\r
186         try {\r
187             return readFile(rf);\r
188         } finally {\r
189             rf.close();\r
190         }       \r
191     }\r
192     \r
193     /**\r
194      * Process a data container using a format handler matching the format and version\r
195      * of the file. \r
196      * @param handlers Map of handlers. Keys are strings of form "format:version".\r
197      */\r
198     public static <T> T readFile(File input, Map<String, FormatHandler<T>> handlers) throws Exception {\r
199         BinaryFile rf = new BinaryFile( input, "r" );\r
200         try {\r
201             return readFile(rf, handlers);\r
202         } finally {\r
203             rf.close();\r
204         }       \r
205     }\r
206     \r
207     /**\r
208      * Writes header fields of a container to the given output. Content field is\r
209      * ignored.\r
210      * @throws IOException \r
211      */\r
212     public static void writeHeader(DataOutput output, DataContainer container) throws IOException {\r
213         STRING_SERIALIZER.serialize(output, container.format);\r
214         INTEGER_SERIALIZER.serialize(output, container.version);\r
215         METADATA_SERIALIZER.serialize(output, container.metadata);\r
216     }\r
217     \r
218     /**\r
219      * Writes a data container to the given output.\r
220      * @throws IOException \r
221      */\r
222     public static void writeFile(DataOutput output, DataContainer container) throws IOException {\r
223         writeHeader(output, container);\r
224         VARIANT_SERIALIZER.serialize(output, container.content);\r
225     }\r
226     \r
227     /**\r
228      * Writes a data container to the given file\r
229      * @throws IOException \r
230      */\r
231     public static void writeFile(File output, DataContainer container) throws IOException {\r
232         BinaryFile wf = new BinaryFile( output);\r
233         try {\r
234             writeFile(wf, container);\r
235         } finally {\r
236             wf.close();\r
237         }       \r
238     }\r
239     \r
240     public static byte[] writeFile(DataContainer container) throws IOException {\r
241         return DATA_CONTAINER_SERIALIZER.serialize(container);\r
242     }\r
243 }\r