package de.jpaw.bonaparte.core; import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.Map; import de.jpaw.bonaparte.pojos.meta.ObjectReference; import de.jpaw.util.ByteArray; import de.jpaw.util.ByteBuilder; /** * Composer intended for IMDGs. * Goals: * 1) be as efficient as reasonable, to save memory (= allows to cache more objects in same amount of RAM = more speed) * 2) don't allocate temporary objects during serialization (avoid GC overhead), unless absolutely required * * @author Michael Bischoff * */ public class CompactByteArrayComposer extends AbstractCompactComposer implements BufferedMessageComposer<IOException> { private static final int DEFAULT_BUFFER_SIZE = 8000; protected final ByteBuilder out; /** Quick conversion utility method, for use by code generators. (null safe). Treats embedded JSONs differently than marshal(). */ public static byte [] marshal(ObjectReference di, BonaPortable x, boolean useJsonForBonaCustomInElements) { if (x == null) return null; ByteBuilder b = new ByteBuilder(); new CompactByteArrayComposer(b, ObjectReuseStrategy.defaultStrategy, false, useJsonForBonaCustomInElements).addField(di, x); return b.getBytes(); } /** Quick conversion utility method, for use by code generators. (null safe) */ public static byte [] marshal(ObjectReference di, BonaPortable x) { return marshal(di, x, true); } /** Quick conversion utility method, for use by code generators. (null safe, avoids double copying of the result) */ public static ByteArray marshalAsByteArray(ObjectReference di, BonaPortable x, boolean useJsonForBonaCustomInElements) { if (x == null) return null; // consistent with the other methods: f(null) = null // ByteArray.ZERO_BYTE_ARRAY; ByteBuilder b = new ByteBuilder(); new CompactByteArrayComposer(b, ObjectReuseStrategy.defaultStrategy, false, useJsonForBonaCustomInElements).addField(di, x); return new ByteArray(b.getCurrentBuffer(), 0, b.length()); } public static ByteArray marshalAsByteArray(ObjectReference di, BonaPortable x) { return marshalAsByteArray(di, x, true); } /** Quick conversion utility method, for use by code generators. (null safe) */ public static byte [] marshalAsElement(ObjectReference di, Object x, boolean useJsonForBonaCustomInElements) { if (x == null) return null; ByteBuilder b = new ByteBuilder(); try { new CompactByteArrayComposer(b, ObjectReuseStrategy.defaultStrategy, false, useJsonForBonaCustomInElements).addField(di, x); } catch (IOException e) { // NOT POSSIBLE throw new RuntimeException(e); } return b.getBytes(); } public static byte [] marshalAsElement(ObjectReference di, Object x) { return marshalAsElement(di, x, true); } /** Quick conversion utility method, for use by code generators. (null safe) */ public static byte [] marshalAsArray(ObjectReference di, List<Object> x, boolean useJsonForBonaCustomInElements) { if (x == null) return null; ByteBuilder b = new ByteBuilder(); try { new CompactByteArrayComposer(b, ObjectReuseStrategy.defaultStrategy, false, useJsonForBonaCustomInElements).addField(di, x); } catch (IOException e) { // NOT POSSIBLE throw new RuntimeException(e); } return b.getBytes(); } public static byte [] marshalAsArray(ObjectReference di, List<Object> x) { return marshalAsArray(di, x, true); } /** Quick conversion utility method, for use by code generators. (null safe) */ public static byte [] marshalAsJson(ObjectReference di, Map<String, Object> x, boolean useJsonForBonaCustomInElements) { if (x == null) return null; ByteBuilder b = new ByteBuilder(); try { new CompactByteArrayComposer(b, ObjectReuseStrategy.defaultStrategy, false, useJsonForBonaCustomInElements).addField(di, x); } catch (IOException e) { // NOT POSSIBLE throw new RuntimeException(e); } return b.getBytes(); } public static byte [] marshalAsJson(ObjectReference di, Map<String, Object> x) { return marshalAsJson(di, x, true); } public CompactByteArrayComposer() { this(new ByteBuilder(DEFAULT_BUFFER_SIZE, getDefaultCharset()), ObjectReuseStrategy.defaultStrategy, false, true); } public CompactByteArrayComposer(boolean useJsonForBonaCustomInElements) { this(new ByteBuilder(DEFAULT_BUFFER_SIZE, getDefaultCharset()), ObjectReuseStrategy.defaultStrategy, false, useJsonForBonaCustomInElements); } public CompactByteArrayComposer(int bufferSize, boolean recommendIdentifiable) { this(new ByteBuilder(bufferSize, getDefaultCharset()), ObjectReuseStrategy.defaultStrategy, recommendIdentifiable, true); } public CompactByteArrayComposer(ByteBuilder out, boolean recommendIdentifiable) { this(out, ObjectReuseStrategy.defaultStrategy, recommendIdentifiable, true); } /** * Creates a new ByteArrayComposer, using this classes static default * Charset **/ public CompactByteArrayComposer(ByteBuilder out, ObjectReuseStrategy reuseStrategy, boolean recommendIdentifiable) { super(out, reuseStrategy, recommendIdentifiable, true); this.out = out; } /** * Creates a new ByteArrayComposer, using this classes static default * Charset **/ public CompactByteArrayComposer(ByteBuilder out, ObjectReuseStrategy reuseStrategy, boolean recommendIdentifiable, boolean useJsonForBonaCustomInElements) { super(out, reuseStrategy, recommendIdentifiable, useJsonForBonaCustomInElements); this.out = out; } // must be overridden / called if caching / reuse is active! @Override public void reset() { super.reset(); out.setLength(0); } public ByteBuilder getBuilder() { return out; } @Override public byte [] getBuffer() { return out.getCurrentBuffer(); } @Override public int getLength() { return out.length(); } @Override public byte [] getBytes() { return out.getBytes(); } // overwrite some methods in order to eat the checked IOException @Override public void close() { try { super.close(); } catch (IOException e) { // IOException from ByteArray operation??? throw new RuntimeException(e); } } @Override public void addField(ObjectReference di, BonaCustom obj) { try { super.addField(di, obj); } catch (IOException e) { // IOException from ByteArray operation??? throw new RuntimeException(e); } } @Override public void writeRecord(BonaCustom o) { try { super.writeRecord(o); } catch (IOException e) { // IOException from ByteArray operation??? throw new RuntimeException(e); } } @Override public void writeObject(BonaCustom o) { try { super.writeObject(o); } catch (IOException e) { // IOException from ByteArray operation??? throw new RuntimeException(e); } } @Override public void writeTransmission(Iterable<? extends BonaCustom> coll) { try { super.writeTransmission(coll); } catch (IOException e) { // IOException from ByteArray operation??? throw new RuntimeException(e); } } @Override public void writeTransmission(Collection<? extends BonaCustom> coll) { try { super.writeTransmission(coll); } catch (IOException e) { // IOException from ByteArray operation??? throw new RuntimeException(e); } } }