package de.jpaw.bonaparte.core; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.UUID; import org.joda.time.Instant; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import org.joda.time.LocalTime; import de.jpaw.bonaparte.enums.BonaNonTokenizableEnum; import de.jpaw.bonaparte.enums.BonaTokenizableEnum; import de.jpaw.bonaparte.pojos.meta.AlphanumericElementaryDataItem; import de.jpaw.bonaparte.pojos.meta.BasicNumericElementaryDataItem; import de.jpaw.bonaparte.pojos.meta.BinaryElementaryDataItem; import de.jpaw.bonaparte.pojos.meta.EnumDataItem; import de.jpaw.bonaparte.pojos.meta.FieldDefinition; import de.jpaw.bonaparte.pojos.meta.MiscElementaryDataItem; import de.jpaw.bonaparte.pojos.meta.NumericElementaryDataItem; import de.jpaw.bonaparte.pojos.meta.ObjectReference; import de.jpaw.bonaparte.pojos.meta.TemporalElementaryDataItem; import de.jpaw.bonaparte.pojos.meta.XEnumDataItem; import de.jpaw.enums.XEnum; import de.jpaw.util.ByteArray; /** Represents composer which does not serialize, but instead appends all objects into a list. * Only the clear() and add() methods of the List interface are used by this implementation. * This implementation is not ideal, since it may unbox/rebox objects of the BonaPortables. * To improve it, the BonaCustom interface would need to be changed. */ public class ListMetaComposer extends NoOpComposer<RuntimeException> implements MessageComposer<RuntimeException> { final protected List<DataAndMeta> storage; final protected boolean doDeepCopies; final protected boolean keepObjects; final protected boolean keepExternals; final protected boolean convertEnums; /** Creates a new ListMetaComposer for a given preallocated external storage. * keepObjects = true replaces the prior ListObjMetaComposer */ public ListMetaComposer(final List<DataAndMeta> storage, boolean doDeepCopies, boolean keepObjects, boolean keepExternals, boolean convertEnums) { this.storage = storage; this.doDeepCopies = doDeepCopies; this.keepObjects = keepObjects; this.keepExternals = keepExternals; this.convertEnums = convertEnums; } /** Creates a new ListMetaComposer for a given preallocated external storage. * keepObjects = true replaces the prior ListObjMetaComposer */ public ListMetaComposer(final List<DataAndMeta> storage, boolean doDeepCopies, boolean keepObjects, boolean keepExternals) { this(storage, doDeepCopies, keepObjects, keepExternals, false); } /** Creates a new ListMetaComposer, creating an own internal storage. */ public ListMetaComposer(boolean doDeepCopies, boolean keepObjects, boolean keepExternals) { this(new ArrayList<DataAndMeta>(), doDeepCopies, keepObjects, keepExternals); } protected void add(FieldDefinition di, Object o) { storage.add(new DataAndMeta(di, o)); } public List<DataAndMeta> getStorage() { return storage; } public boolean getDoDeepCopies() { return doDeepCopies; } public void reset() { storage.clear(); } @Override public void writeNull(FieldDefinition di) { add(di,null); } @Override public void writeNullCollection(FieldDefinition di) { add(di,null); } @Override public void addField(AlphanumericElementaryDataItem di, String s) { add(di, s); } @Override public void addField(MiscElementaryDataItem di, boolean b) { add(di, Boolean.valueOf(b)); } @Override public void addField(MiscElementaryDataItem di, char c) { add(di, Character.valueOf(c)); } @Override public void addField(BasicNumericElementaryDataItem di, double d) { add(di, Double.valueOf(d)); } @Override public void addField(BasicNumericElementaryDataItem di, float f) { add(di, Float.valueOf(f)); } @Override public void addField(BasicNumericElementaryDataItem di, byte n) { add(di, Byte.valueOf(n)); } @Override public void addField(BasicNumericElementaryDataItem di, short n) { add(di, Short.valueOf(n)); } @Override public void addField(BasicNumericElementaryDataItem di, int n) { add(di, Integer.valueOf(n)); } @Override public void addField(BasicNumericElementaryDataItem di, long n) { add(di, Long.valueOf(n)); } @Override public void addField(BasicNumericElementaryDataItem di, BigInteger n) { add(di, n); } @Override public void addField(NumericElementaryDataItem di, BigDecimal n) { add(di, n); } @Override public void addField(MiscElementaryDataItem di, UUID n) { add(di, n); } @Override public void addField(BinaryElementaryDataItem di, ByteArray b) { add(di, b); } @Override public void addField(BinaryElementaryDataItem di, byte[] b) { if (b == null) writeNull(di); else add(di, doDeepCopies ? Arrays.copyOf(b, b.length) : b); } @Override public void addField(TemporalElementaryDataItem di, LocalDate t) { add(di, t); } @Override public void addField(TemporalElementaryDataItem di, LocalDateTime t) { add(di, t); } @Override public void addField(TemporalElementaryDataItem di, LocalTime t) { add(di, t); } @Override public void addField(TemporalElementaryDataItem di, Instant t) { add(di, t); } @Override public void addField(ObjectReference di, BonaCustom obj) { if (obj == null) { writeNull(null); } else { if (keepObjects) { add(di, obj); } else { startObject(di, obj); obj.serializeSub(this); terminateObject(di, obj); } } } @Override public void addEnum(EnumDataItem di, BasicNumericElementaryDataItem ord, BonaNonTokenizableEnum n) { if (convertEnums) add(di, n == null ? null : Integer.valueOf(n.ordinal())); else add(di, n); } @Override public void addEnum(EnumDataItem di, AlphanumericElementaryDataItem token, BonaTokenizableEnum n) { if (convertEnums) add(di, n == null ? null : n.getToken()); else add(di, n); } @Override public void addEnum(XEnumDataItem di, AlphanumericElementaryDataItem token, XEnum<?> n) { if (convertEnums) add(di, n == null ? null : n.getToken()); else add(di, n); } @Override public boolean addExternal(ObjectReference di, Object obj) { if (keepExternals) { add(di, obj); } return keepExternals; } @Override public void addField(ObjectReference di, Map<String, Object> obj) { add(di, obj); } @Override public void addField(ObjectReference di, List<Object> obj) { add(di, obj); } @Override public void addField(ObjectReference di, Object obj) { add(di, obj); } }