package mightypork.utils.ion; import java.io.Closeable; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; /** * Ion output stream * * @author Ondřej Hruška (MightyPork) */ public class IonOutput implements Closeable { private final DataOutput out; private final OutputStream stream; @SuppressWarnings("resource") public IonOutput(File outFile) throws FileNotFoundException { this(new FileOutputStream(outFile)); } public IonOutput(OutputStream out) { this.stream = out; this.out = new DataOutputStream(out); } public void writeBoolean(boolean a) throws IOException { out.writeBoolean(a); } public void writeByte(int a) throws IOException { out.writeByte(a); } public void writeShort(int a) throws IOException { out.writeShort(a); } public void writeChar(int a) throws IOException { out.writeChar(a); } public void writeInt(int a) throws IOException { out.writeInt(a); } public void writeIntShort(int a) throws IOException { out.writeShort(a); } public void writeIntByte(int a) throws IOException { out.writeByte(a); } public void writeLong(long a) throws IOException { out.writeLong(a); } public void writeFloat(float a) throws IOException { out.writeFloat(a); } public void writeDouble(double a) throws IOException { out.writeDouble(a); } public void writeBytes(String a) throws IOException { out.writeBytes(a); } public void writeString(String a) throws IOException { out.writeUTF(a); } public void writeBooleans(boolean[] arr) throws IOException { writeLength(arr.length); for (final boolean a : arr) { out.writeBoolean(a); } } public void writeBytes(byte[] arr) throws IOException { writeLength(arr.length); for (final byte a : arr) { out.writeByte(a); } } public void writeChars(char[] arr) throws IOException { writeLength(arr.length); for (final char a : arr) { out.writeChar(a); } } public void writeShorts(short[] arr) throws IOException { writeLength(arr.length); for (final short a : arr) { out.writeShort(a); } } public void writeInts(int[] arr) throws IOException { writeLength(arr.length); for (final int a : arr) { out.writeInt(a); } } public void writeLongs(long[] arr) throws IOException { writeLength(arr.length); for (final long a : arr) { out.writeLong(a); } } public void writeFloats(float[] arr) throws IOException { writeLength(arr.length); for (final float a : arr) { out.writeFloat(a); } } public void writeDoubles(double[] arr) throws IOException { writeLength(arr.length); for (final double a : arr) { out.writeDouble(a); } } public void writeStrings(String[] arr) throws IOException { writeLength(arr.length); for (final String a : arr) { out.writeUTF(a); } } /** * Write a bundle without a mark */ public void writeBundle(IonDataBundle bundle) throws IOException { bundle.save(this); } /** * Write array of objects. Works with all that is supported by writeObject() * * @param arr array to write * @throws IOException on IO error or on invalid object type. */ public void writeObjects(Object[] arr) throws IOException { writeLength(arr.length); for (final Object a : arr) { writeObject(a); } } public void writeSequence(Collection sequence) throws IOException { for (final T element : sequence) { startEntry(); writeObject(element); } endSequence(); } public void writeMap(Map map) throws IOException { for (final Entry e : map.entrySet()) { if (e.getValue() == null) { continue; } startEntry(); writeObject(e.getKey()); writeObject(e.getValue()); } endSequence(); } public void endSequence() throws IOException { writeMark(Ion.END); } public void startEntry() throws IOException { writeMark(Ion.ENTRY); } private void writeMark(int mark) throws IOException { writeIntByte(mark); } private void writeLength(int length) throws IOException { writeInt(length); } /** * Write an object. Supported are built-in types and types registered to * Ion. * * @param obj obj to write * @throws IOException on IO error or invalid object type. */ public void writeObject(Object obj) throws IOException { if (obj == null) { writeMark(Ion.NULL); return; } if (obj instanceof IonBinary) { final IonBinary iObj = (IonBinary) obj; writeMark(Ion.getMark(obj)); iObj.save(this); return; } if (obj instanceof IonBundled) { final IonBundled iObj = (IonBundled) obj; writeMark(Ion.getMark(obj)); final IonDataBundle bundle = new IonDataBundle(); iObj.save(bundle); writeBundle(bundle); return; } if (Ion.isObjectIndirectBundled(obj)) { final IonizerBundled ionizer = Ion.getIonizerBundledForClass(obj.getClass()); writeMark(Ion.getMark(obj)); final IonDataBundle bundle = new IonDataBundle(); ionizer._save(obj, bundle); writeBundle(bundle); return; } if (Ion.isObjectIndirectBinary(obj)) { final IonizerBinary ionizer = Ion.getIonizerBinaryForClass(obj.getClass()); writeMark(Ion.getMark(obj)); ionizer._save(obj, this); return; } if (obj instanceof Map) { writeMark(Ion.MAP); writeMap((Map) obj); return; } if (obj instanceof Collection) { writeMark(Ion.SEQUENCE); writeSequence((Collection) obj); return; } if (obj instanceof Boolean) { writeMark(Ion.BOOLEAN); writeBoolean((Boolean) obj); return; } if (obj instanceof Byte) { writeMark(Ion.BYTE); writeByte((Byte) obj); return; } if (obj instanceof Character) { writeMark(Ion.CHAR); writeChar((Character) obj); return; } if (obj instanceof Short) { writeMark(Ion.SHORT); writeShort((Short) obj); return; } if (obj instanceof Integer) { writeMark(Ion.INT); writeInt((Integer) obj); return; } if (obj instanceof Long) { writeMark(Ion.LONG); writeLong((Long) obj); return; } if (obj instanceof Float) { writeMark(Ion.FLOAT); writeFloat((Float) obj); return; } if (obj instanceof Double) { writeMark(Ion.DOUBLE); writeDouble((Double) obj); return; } if (obj instanceof String) { writeMark(Ion.STRING); writeString((String) obj); return; } if (obj instanceof boolean[]) { writeMark(Ion.BOOLEAN_ARRAY); writeBooleans((boolean[]) obj); return; } if (obj instanceof byte[]) { writeMark(Ion.BYTE_ARRAY); writeBytes((byte[]) obj); return; } if (obj instanceof char[]) { writeMark(Ion.CHAR_ARRAY); writeChars((char[]) obj); return; } if (obj instanceof short[]) { writeMark(Ion.SHORT_ARRAY); writeShorts((short[]) obj); return; } if (obj instanceof int[]) { writeMark(Ion.INT_ARRAY); writeInts((int[]) obj); return; } if (obj instanceof long[]) { writeMark(Ion.LONG_ARRAY); writeLongs((long[]) obj); return; } if (obj instanceof float[]) { writeMark(Ion.FLOAT_ARRAY); writeFloats((float[]) obj); return; } if (obj instanceof double[]) { writeMark(Ion.DOUBLE_ARRAY); writeDoubles((double[]) obj); return; } if (obj instanceof String[]) { writeMark(Ion.STRING_ARRAY); writeStrings((String[]) obj); return; } if (obj instanceof Object[]) { writeMark(Ion.OBJECT_ARRAY); writeObjects((Object[]) obj); return; } throw new IOException("Object " + obj + " could not be be written to stream."); } @Override public void close() throws IOException { stream.close(); } }