package com.circlegate.liban.base;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Parcel;
import com.circlegate.liban.base.ApiBase.ApiCreator;
import com.circlegate.liban.base.ApiBase.ApiInstanceCreator;
import com.circlegate.liban.base.ApiBase.IApiObject;
import com.circlegate.liban.base.ApiBase.IApiParcelable;
import com.circlegate.liban.utils.AppUtils;
import com.google.common.collect.ImmutableList;
import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Duration;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ApiDataIO {
public interface ApiDataInputOutputBase {
int UNKNOWN_DATA_VERSION = 0;
int FLAG_NONE = 0;
int FLAG_PORTABLE = 1;
int getCustomFlags();
}
public interface ApiDataOutput extends ApiDataInputOutputBase {
boolean write(boolean value);
void write(int value);
void write(long value);
void write(float value);
void write(double value);
void write(byte[] value);
void write(int[] value);
void write(String value);
void write(Bitmap value, int flags);
void write(DateTime value);
void write(DateMidnight value);
void write(Duration value);
void write(IApiObject value, int flags);
void writeWithName(IApiParcelable value, int flags);
void writeBooleans(Collection<Boolean> value);
void writeIntegers(Collection<Integer> value);
void writeStrings(Collection<String> value);
void write(Collection<? extends IApiObject> value, int flags);
void writeWithNames(Collection<? extends IApiParcelable> value, int flags);
void writeOpt(byte[] value);
void writeOpt(int[] value);
void writeOpt(String value);
void writeOpt(Bitmap value, int flags);
void writeOpt(DateTime value);
void writeOpt(DateMidnight value);
void writeOpt(Duration value);
void writeOpt(IApiObject value, int flags);
void writeOptWithName(IApiParcelable value, int flags);
void writeOptBooleans(Collection<Boolean> value);
void writeOptIntegers(Collection<Integer> value);
void writeOptStrings(Collection<String> value);
void writeOpt(Collection<? extends IApiObject> value, int flags);
void writeOptWithNames(Collection<? extends IApiParcelable> value, int flags);
}
public interface ApiDataInput extends ApiDataInputOutputBase {
int getDataAppVersionCode(); // version code verze aplikace, ktera puvodne dana data ulozila...
boolean readBoolean();
int readInt();
long readLong();
float readFloat();
double readDouble();
byte[] readBytes();
int[] readIntArray();
String readString();
Bitmap readBitmap();
DateTime readDateTime();
DateMidnight readDateMidnight();
Duration readDuration();
<T extends IApiObject> T readObject(ApiCreator<T> creator);
<T extends IApiParcelable> T readParcelableWithName();
ImmutableList<Boolean> readBooleans();
ImmutableList<String> readStrings();
ImmutableList<Integer> readIntegers();
<T extends IApiObject> ImmutableList<T> readImmutableList(ApiCreator<T> creator);
<T extends IApiParcelable> ImmutableList<T> readImmutableListWithNames();
byte[] readOptBytes();
int[] readOptIntArray();
String readOptString();
Bitmap readOptBitmap();
DateTime readOptDateTime();
DateMidnight readOptDateMidnight();
Duration readOptDuration();
<T extends IApiObject> T readOptObject(ApiCreator<T> creator);
<T extends IApiParcelable> T readOptParcelableWithName();
ImmutableList<Boolean> readOptBooleans();
ImmutableList<String> readOptStrings();
ImmutableList<Integer> readOptIntegers();
<T extends IApiObject> ImmutableList<T> readOptImmutableList(ApiCreator<T> creator);
<T extends IApiParcelable> ImmutableList<T> readOptImmutableListWithNames();
}
public interface ApiDataAppVersionCodeLegacyResolver {
int resolveAppVersionCodeLegacy(int legacyDataVersion);
}
public static abstract class ApiDataOutputBase implements ApiDataOutput {
private final Map<String, Integer> stringMap = new HashMap<String, Integer>();
private final Map<Bitmap, Integer> bmpMap = new HashMap<Bitmap, Integer>();
protected abstract void doWrite(String value);
protected abstract void doWrite(Bitmap value, int flags);
@Override
public final void write(String value) {
Integer index = stringMap.get(value);
if (index == null) {
write(true);
doWrite(value);
stringMap.put(value, stringMap.size());
}
else {
write(false);
write(index);
}
}
@Override
public final void write(Bitmap value, int flags) {
Integer index = bmpMap.get(value);
if (index == null) {
write(true);
doWrite(value, flags);
bmpMap.put(value, bmpMap.size());
}
else {
write(false);
write(index);
}
}
@Override
public final void write(DateTime value) {
write(value.getMillis());
write(value.getZone().getID());
}
@Override
public final void write(DateMidnight dateMidnight) {
write(dateMidnight.getMillis());
write(dateMidnight.getZone().getID());
}
@Override
public final void write(Duration value) {
write(value.getMillis());
}
@Override
public final void writeBooleans(Collection<Boolean> value) {
write(value.size());
for (Boolean item : value) {
write(item);
}
}
@Override
public final void writeIntegers(Collection<Integer> value) {
write(value.size());
for (Integer item : value) {
write(item);
}
}
@Override
public final void writeStrings(Collection<String> value) {
write(value.size());
for (String item : value) {
write(item);
}
}
@Override
public final void write(IApiObject value, int flags) {
value.save(this, flags);
}
@Override
public final void writeWithName(IApiParcelable value, int flags) {
write(value.getClass().getName());
write(value, flags);
}
@Override
public final void write(Collection<? extends IApiObject> value, int flags) {
write(value.size());
for (IApiObject item : value) {
item.save(this, flags);
}
}
@Override
public final void writeWithNames(Collection<? extends IApiParcelable> value, int flags) {
write(value.size());
for (IApiParcelable item : value) {
writeWithName(item, flags);
}
}
@Override
public final void writeOpt(int[] value) {
if (write(value != null))
write(value);
}
@Override
public final void writeOpt(byte[] value) {
if (write(value != null))
write(value);
}
@Override
public final void writeOpt(String value) {
if (write(value != null))
write(value);
}
@Override
public final void writeOpt(Bitmap value, int flags) {
if (write(value != null))
write(value, flags);
}
@Override
public final void writeOpt(DateTime value) {
if (write(value != null))
write(value);
}
@Override
public final void writeOpt(DateMidnight value) {
if (write(value != null))
write(value);
}
@Override
public final void writeOpt(Duration value) {
if (write(value != null))
write(value);
}
@Override
public final void writeOpt(IApiObject value, int flags) {
if (write(value != null))
write(value, flags);
}
@Override
public final void writeOptWithName(IApiParcelable value, int flags) {
if (write(value != null))
writeWithName(value, flags);
}
@Override
public final void writeOptBooleans(Collection<Boolean> value) {
if (write(value != null))
writeBooleans(value);
}
@Override
public final void writeOptIntegers(Collection<Integer> value) {
if (write(value != null))
writeIntegers(value);
}
@Override
public final void writeOptStrings(Collection<String> value) {
if (write(value != null))
writeStrings(value);
}
@Override
public final void writeOpt(Collection<? extends IApiObject> value, int flags) {
if (write(value != null))
write(value, flags);
}
@Override
public final void writeOptWithNames(Collection<? extends IApiParcelable> value, int flags) {
if (write(value != null))
writeWithNames(value, flags);
}
}
public static abstract class ApiDataInputBase implements ApiDataInput {
private final List<String> stringList = new ArrayList<String>();
private final List<Bitmap> bmpList = new ArrayList<Bitmap>();
protected abstract String doReadString();
protected abstract Bitmap doReadBitmap();
@Override
public final String readString() {
if (readBoolean()) {
String ret = doReadString();
stringList.add(ret);
return ret;
}
else {
int index = readInt();
return stringList.get(index);
}
}
@Override
public final Bitmap readBitmap() {
if (readBoolean()) {
Bitmap ret = doReadBitmap();
bmpList.add(ret);
return ret;
}
else {
int index = readInt();
return bmpList.get(index);
}
}
@Override
public final DateTime readDateTime() {
long millis = readLong();
String id = readString();
return new DateTime(millis, DateTimeZone.forID(id));
}
@Override
public final DateMidnight readDateMidnight() {
long millis = readLong();
String id = readString();
return new DateMidnight(millis, DateTimeZone.forID(id));
}
@Override
public final Duration readDuration() {
return new Duration(readLong());
}
@Override
public final ImmutableList<Boolean> readBooleans() {
ImmutableList.Builder<Boolean> b = ImmutableList.builder();
int length = readInt();
for (int i = 0; i < length; i++) {
b.add(readBoolean());
}
return b.build();
}
@Override
public final ImmutableList<String> readStrings() {
ImmutableList.Builder<String> b = ImmutableList.builder();
int length = readInt();
for (int i = 0; i < length; i++) {
b.add(readString());
}
return b.build();
}
@Override
public final ImmutableList<Integer> readIntegers() {
ImmutableList.Builder<Integer> b = ImmutableList.builder();
int length = readInt();
for (int i = 0; i < length; i++) {
b.add(readInt());
}
return b.build();
}
@Override
public final <T extends IApiObject> T readObject(ApiCreator<T> creator) {
return creator.create(this);
}
@Override
public final <T extends IApiParcelable> T readParcelableWithName() {
return ApiInstanceCreator.createInstanceReadClassNameFirst(this);
}
@Override
public final <T extends IApiObject> ImmutableList<T> readImmutableList(ApiCreator<T> creator) {
int length = readInt();
ImmutableList.Builder<T> b = ImmutableList.builder();
for (int i = 0; i < length; i++) {
b.add(creator.create(this));
}
return b.build();
}
@SuppressWarnings("unchecked")
@Override
public final <T extends IApiParcelable> ImmutableList<T> readImmutableListWithNames() {
ImmutableList.Builder<T> b = ImmutableList.builder();
int length = readInt();
for (int i = 0; i < length; i++) {
b.add((T) readParcelableWithName());
}
return b.build();
}
@Override
public final byte[] readOptBytes() {
return readBoolean() ? readBytes() : null;
}
@Override
public final int[] readOptIntArray() {
return readBoolean() ? readIntArray() : null;
}
@Override
public final String readOptString() {
return readBoolean() ? readString() : null;
}
@Override
public final Bitmap readOptBitmap() {
return readBoolean() ? readBitmap() : null;
}
@Override
public final DateTime readOptDateTime() {
return readBoolean() ? readDateTime() : null;
}
@Override
public final DateMidnight readOptDateMidnight() {
return readBoolean() ? readDateMidnight() : null;
}
@Override
public final Duration readOptDuration() {
return readBoolean() ? readDuration() : null;
}
@Override
public final <T extends IApiObject> T readOptObject(ApiCreator<T> creator) {
return readBoolean() ? readObject(creator) : null;
}
@Override
public final <T extends IApiParcelable> T readOptParcelableWithName() {
return readBoolean() ? this.<T>readParcelableWithName() : null;
}
@Override
public final ImmutableList<Boolean> readOptBooleans() {
return readBoolean() ? readBooleans() : null;
}
@Override
public final ImmutableList<String> readOptStrings() {
return readBoolean() ? readStrings() : null;
}
@Override
public final ImmutableList<Integer> readOptIntegers() {
return readBoolean() ? readIntegers() : null;
}
@Override
public final <T extends IApiObject> ImmutableList<T> readOptImmutableList(ApiCreator<T> creator) {
return readBoolean() ? this.<T>readImmutableList(creator) : null;
}
@Override
public final <T extends IApiParcelable> ImmutableList<T> readOptImmutableListWithNames() {
return readBoolean() ? this.<T>readImmutableListWithNames() : null;
}
}
public static class ApiDataOutputStreamWrp extends ApiDataOutputBase {
private final int customFlags;
private final DataOutputStream dataOutputStream;
public ApiDataOutputStreamWrp(DataOutputStream dataOutputStream) {
this(dataOutputStream, FLAG_NONE);
}
public ApiDataOutputStreamWrp(DataOutputStream dataOutputStream, int customFlags) {
this.customFlags = customFlags;
this.dataOutputStream = dataOutputStream;
int dataAppVersionCode = AppUtils.getAppVersionCode() + ApiDataInputStreamWrp.DATA_VERSION_OFFSET;
write(dataAppVersionCode);
}
public DataOutputStream getDataOutputStream() {
return dataOutputStream;
}
public void close() {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public int getCustomFlags() {
return customFlags;
}
@Override
protected final void doWrite(String value) {
try {
dataOutputStream.writeUTF(value);
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
protected void doWrite(Bitmap value, int flags) {
if (value.compress(CompressFormat.PNG, 100, dataOutputStream) == false)
throw new RuntimeException();
}
@Override
public final boolean write(boolean value) {
try {
dataOutputStream.writeBoolean(value);
return value;
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public final void write(int value) {
try {
dataOutputStream.writeInt(value);
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public final void write(long value) {
try {
dataOutputStream.writeLong(value);
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public final void write(float value) {
try {
dataOutputStream.writeFloat(value);
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public final void write(double value) {
try {
dataOutputStream.writeDouble(value);
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public final void write(byte[] value) {
try {
dataOutputStream.writeInt(value.length);
dataOutputStream.write(value);
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public void write(int[] value) {
try {
dataOutputStream.writeInt(value.length);
for (int i = 0; i < value.length; i++)
dataOutputStream.writeInt(value[i]);
}
catch (IOException ex) {
throw new RuntimeException();
}
}
}
public static class ApiDataInputStreamWrp extends ApiDataInputBase {
public static final int DATA_VERSION_OFFSET = 100;
private final DataInputStream dataInputStream;
private final int customFlags;
private final int dataAppVersionCode;
public ApiDataInputStreamWrp(DataInputStream dataInputStream) {
this.dataInputStream = dataInputStream;
this.customFlags = FLAG_NONE;
int dataVersion = readInt();
if (dataVersion < DATA_VERSION_OFFSET) {
this.dataAppVersionCode = AppUtils.getAppVersionCode();
}
else {
this.dataAppVersionCode = dataVersion - DATA_VERSION_OFFSET;
}
}
public ApiDataInputStreamWrp(DataInputStream dataInputStream, int customFlags, ApiDataAppVersionCodeLegacyResolver dataAppVersionCodeResolver) {
this.dataInputStream = dataInputStream;
this.customFlags = customFlags;
int dataVersion = readInt();
if (dataVersion < DATA_VERSION_OFFSET)
this.dataAppVersionCode = dataAppVersionCodeResolver.resolveAppVersionCodeLegacy(dataVersion);
else
this.dataAppVersionCode = dataVersion - DATA_VERSION_OFFSET;
}
@Override
public int getCustomFlags() {
return customFlags;
}
public void close() {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected String doReadString() {
try {
return dataInputStream.readUTF();
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
protected Bitmap doReadBitmap() {
Bitmap ret = BitmapFactory.decodeStream(dataInputStream);
if (ret == null)
throw new RuntimeException();
return ret;
}
@Override
public int getDataAppVersionCode() {
return this.dataAppVersionCode;
}
@Override
public final boolean readBoolean() {
try {
return dataInputStream.readBoolean();
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public final int readInt() {
try {
return dataInputStream.readInt();
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public final long readLong() {
try {
return dataInputStream.readLong();
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public final float readFloat() {
try {
return dataInputStream.readFloat();
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public final double readDouble() {
try {
return dataInputStream.readDouble();
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public final byte[] readBytes() {
try {
byte[] ret;
ret = new byte[dataInputStream.readInt()];
dataInputStream.readFully(ret);
return ret;
} catch (IOException e) {
throw new RuntimeException();
}
}
@Override
public int[] readIntArray() {
try {
int[] ret;
ret = new int[dataInputStream.readInt()];
for (int i = 0; i < ret.length; i++) {
ret[i] = dataInputStream.readInt();
}
return ret;
} catch (IOException e) {
throw new RuntimeException();
}
}
}
public static class ApiParcelOutputWrp extends ApiDataOutputBase {
private final Parcel parcel;
public ApiParcelOutputWrp(Parcel parcel) {
this.parcel = parcel;
}
public Parcel getParcel() {
return parcel;
}
@Override
public int getCustomFlags() {
return FLAG_NONE;
}
@Override
protected void doWrite(String value) {
parcel.writeString(value);
}
@Override
protected void doWrite(Bitmap value, int flags) {
value.writeToParcel(parcel, flags);
}
@Override
public final boolean write(boolean value) {
parcel.writeByte(value ? (byte)1 : (byte)0);
return value;
}
@Override
public final void write(int value) {
parcel.writeInt(value);
}
@Override
public final void write(long value) {
parcel.writeLong(value);
}
@Override
public void write(float value) {
parcel.writeFloat(value);
}
@Override
public final void write(double value) {
parcel.writeDouble(value);
}
@Override
public final void write(byte[] value) {
parcel.writeByteArray(value);
}
@Override
public void write(int[] value) {
parcel.writeIntArray(value);
}
// POZOR! Zamerne zaremovano ! - zaremovana implementace vytvari novy Parcel a to znamena, ze se nepouziji cache stringu a bitmap
// - a pak kvuli tomu treba se neobnovovaly nektere aktivity!!
// @Override
// public final void writeWithName(IApiParcelable value, int flags) {
// parcel.writeParcelable(value, flags);
// }
}
public static class ApiParcelInputWrp extends ApiDataInputBase {
private final Parcel parcel;
public ApiParcelInputWrp(Parcel parcel) {
this.parcel = parcel;
}
public Parcel getParcel() {
return parcel;
}
@Override
public int getDataAppVersionCode() {
return AppUtils.getAppVersionCode();
}
@Override
public int getCustomFlags() {
return FLAG_NONE;
}
@Override
protected String doReadString() {
return parcel.readString();
}
@Override
protected Bitmap doReadBitmap() {
return Bitmap.CREATOR.createFromParcel(parcel);
}
@Override
public final boolean readBoolean() {
return parcel.readByte() != 0;
}
@Override
public final int readInt() {
return parcel.readInt();
}
@Override
public final long readLong() {
return parcel.readLong();
}
@Override
public final float readFloat() {
return parcel.readFloat();
}
@Override
public final double readDouble() {
return parcel.readDouble();
}
@Override
public final byte[] readBytes() {
return parcel.createByteArray();
}
@Override
public int[] readIntArray() {
return parcel.createIntArray();
}
// @Override
// public final <T extends IApiParcelable> T readParcelableWithName() {
// return parcel.readParcelable(getClass().getClassLoader());
// }
}
}