/******************************************************************************* * Copyright (c) 2010- Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.databoard; import java.io.DataInput; import java.io.DataOutput; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.nio.ByteBuffer; import org.simantics.databoard.accessor.error.AccessorException; import org.simantics.databoard.adapter.AdaptException; import org.simantics.databoard.adapter.Adapter; import org.simantics.databoard.adapter.AdapterConstructionException; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.RecordBinding; import org.simantics.databoard.binding.error.BindingException; import org.simantics.databoard.binding.mutable.MutableVariant; import org.simantics.databoard.parser.repository.DataTypeSyntaxError; import org.simantics.databoard.parser.repository.DataValueRepository; import org.simantics.databoard.serialization.RuntimeSerializerConstructionException; import org.simantics.databoard.serialization.Serializer; import org.simantics.databoard.serialization.SerializerConstructionException; import org.simantics.databoard.type.Datatype; import org.simantics.databoard.util.StreamUtil; import org.simantics.databoard.util.binary.BinaryFile; import org.simantics.databoard.util.binary.BinaryReadable; import org.simantics.databoard.util.binary.ByteBufferReadable; import org.simantics.databoard.util.binary.ByteBufferWriteable; import org.simantics.databoard.util.binary.InputStreamReadable; import org.simantics.databoard.util.binary.OutputStreamWriteable; import org.simantics.databoard.util.binary.UTF8; public class Files { /** * Create a text file (.dbv) with a value. The file is UTF-8 encoded. * If old file exists, it is deleted. * * @param file * @param binding * @param value * @throws IOException */ public static void createTextFile(File file, Binding binding, Object value) throws IOException { try { if (file.exists()) file.delete(); file.createNewFile(); String txt = binding.printValueDefinition(value, false); FileOutputStream fos = new FileOutputStream(file, false); try { OutputStreamWriter os = new OutputStreamWriter(fos, UTF8.CHARSET); os.append(txt); os.flush(); os.close(); } finally { fos.close(); } } catch(BindingException e) { throw new IOException(e); } } /** * Create a binary file (.dbb) with a initial value. Binary file is a variant, * there is a filetype in the header of the file. * If old file exists, it is deleted. * * @param file * @param binding * @param value * @throws IOException */ public static void createFile(File file, Binding binding, Object value) throws IOException { if (file.exists()) file.delete(); file.createNewFile(); MutableVariant v = new MutableVariant(binding, value); Serializer s = Bindings.getSerializerUnchecked( Bindings.MUTABLE_VARIANT ); s.serialize(v, file); } /** * Create a new binary file (.dbb) with an empty value. Binary file is a variant, * there is a filetype in the header of the file. * If old file exists, it is deleted. * * @since 0.5 * @param file * @throws IOException * @throws RuntimeSerializerConstructionException */ public static void createFile(File file) throws IOException, RuntimeSerializerConstructionException { if (file.exists()) file.delete(); file.createNewFile(); BinaryFile bf = new BinaryFile(file); try { Binding binding = Bindings.MUTABLE_VARIANT; Object value = new MutableVariant(); Serializer s = Bindings.getSerializerUnchecked( binding ); s.serialize(bf, value); } finally { bf.close(); } } /** * Create a binary file (.dbb) with empty value of given type. Binary file is a variant, * there is a filetype in the header of the file. * If old file exists, it is deleted. * * @param file * @param type * @throws IOException * @throws RuntimeSerializerConstructionException */ public static void createFile(File file, Datatype type) throws IOException, RuntimeSerializerConstructionException { if (file.exists()) file.delete(); file.createNewFile(); BinaryFile bf = new BinaryFile(file); try { Binding binding = Bindings.MUTABLE_VARIANT; Object value = binding.createDefault(); Serializer s = Bindings.getSerializer( binding ); s.serialize(bf, value); } catch (BindingException e) { throw new IOException(e); } catch (SerializerConstructionException e) { throw new IOException(e); } finally { bf.close(); } } /** * Read a text file (.dbv). * * @param file * @param binding * @return value * @throws IOException * @throws BindingException * @throws DataTypeSyntaxError */ public static Object readTextFile(File file, Binding binding) throws IOException, DataTypeSyntaxError, BindingException { FileInputStream fis = new FileInputStream(file); try { byte[] data = StreamUtil.readFully(fis); String txt = new String(data, UTF8.CHARSET); DataValueRepository repo = new DataValueRepository(); repo.setTypeRepository( Datatypes.datatypeRepository ); return binding.parseValue(txt, repo); } finally { fis.close(); } } /** * Read file type of a binary file. * * @param file * @return datatype * @throws IOException */ public static Datatype readFileType(File file) throws IOException { BinaryFile rf = new BinaryFile( file, "r" ); try { Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class ); return (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( rf ); } finally { rf.close(); } } /** * Read a binary file into a java instance. Binary file is a variant, * there is a filetype in the header of the file. * If requested binding is not the exact binding of the file, an adapter is tried. * * @param file file * @param binding content binding * @return instance * @throws IOException */ public static Object readFile(File file, Binding binding) throws IOException { BinaryFile rf = new BinaryFile( file, "r" ); try { Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class ); Datatype type = (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( rf ); if (type.equals(binding.type())) { return Bindings.getSerializerUnchecked( binding ).deserialize(rf); } else { try { Binding fileContentBinding = Bindings.getMutableBinding(type); Adapter adapter = Bindings.getAdapter(fileContentBinding, binding); Object value = Bindings.getSerializerUnchecked( fileContentBinding ).deserialize(rf); return adapter.adapt( value ); } catch (AdapterConstructionException e) { throw new IOException(e); } catch (AdaptException e) { throw new IOException(e); } } } finally { rf.close(); } } /** * Read a file to an object. * * @param file * @param binding * @param dst * @throws IOException */ public static void readFile(File file, RecordBinding binding, Object dst) throws IOException { BinaryFile rf = new BinaryFile( file, "r" ); try { Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class ); Datatype type = (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( rf ); if (type.equals(binding.type())) { Serializer s = Bindings.getSerializerUnchecked( binding ); s.deserializeTo(rf, dst); } else { try { Binding fileContentBinding = Bindings.getMutableBinding(type); Serializer s = Bindings.getSerializerUnchecked( fileContentBinding ); Object tmpObj = s.deserialize( rf ); binding.readFrom(fileContentBinding, tmpObj, dst); } catch (BindingException e) { throw new IOException(e); } } } finally { rf.close(); } } /** * Read input stream into a java instance. Binary file is a variant, * there is a filetype in the header of the file. If requested binding is not the * exact binding of the file, an adapter is tried.

* * The implementation reads the inputstream fully into memory.

* * @param is input stream * @param binding content binding * @return instance * @throws IOException */ public static Object readFile(InputStream is, Binding binding) throws IOException { BinaryReadable readable = InputStreamReadable.readFully( is ); Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class ); Datatype type = (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( readable ); if (!type.equals(binding.type())) { try { Binding fileContentBinding = Bindings.getMutableBinding(type); Adapter adapter = Bindings.getAdapter(fileContentBinding, binding); Object value = Bindings.getSerializerUnchecked( fileContentBinding ).deserialize( readable ); return adapter.adapt( value ); } catch (AdapterConstructionException e) { throw new IOException(e); } catch (AdaptException e) { throw new IOException(e); } } return Bindings.getSerializerUnchecked( binding ).deserialize( readable ); } /** * Read input stream into a java instance. If requested binding is not the * exact binding of the file, an adapter is tried. * * @param is input stream * @param streamLength * @param binding content binding * @return instance * @throws IOException * @throws AccessorException */ public static Object readFile(InputStream is, long streamLength, Binding binding) throws IOException { BinaryReadable readable = new InputStreamReadable( is, streamLength ); Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class ); Datatype type = (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( readable ); if (!type.equals(binding.type())) { try { Binding fileContentBinding = Bindings.getMutableBinding(type); Adapter adapter = Bindings.getAdapter(fileContentBinding, binding); Object value = Bindings.getSerializerUnchecked( fileContentBinding ).deserialize( readable ); return adapter.adapt( value ); } catch (AdapterConstructionException e) { throw new IOException(e); } catch (AdaptException e) { throw new IOException(e); } } return Bindings.getSerializerUnchecked( binding ).deserialize( readable ); } /** * Write value as binary file (.dbb). * * @param file file * @param binding content binding * @param value value * @throws IOException */ public static void writeFile(File file, Binding binding, Object value) throws IOException { BinaryFile rf = new BinaryFile( file ); try { MutableVariant v = new MutableVariant(binding, value); Serializer s = Bindings.getSerializerUnchecked( Bindings.MUTABLE_VARIANT ); s.serialize(rf, v); } finally { rf.close(); } } public static DataInput openInput( InputStream is ) { return new InputStreamReadable(is, Long.MAX_VALUE); } public static DataInput openInput( File file ) throws IOException { return new BinaryFile(file, "r"); } public static DataInput openInput( byte[] data ) { ByteBuffer buffer = ByteBuffer.wrap( data ); return new ByteBufferReadable( buffer ); } public static DataOutput openOutput( OutputStream os ) { return new OutputStreamWriteable( os ); } public static DataOutput openOutput( File file ) throws IOException { return new BinaryFile( file ); } public static DataOutput openOutput( byte[] data ) throws IOException { ByteBuffer buffer = ByteBuffer.wrap( data ); return new ByteBufferWriteable( buffer ); } }