diff --git a/LikeOrmCommons/src/main/java/com/github/nrudenko/orm/commons/DbType.java b/LikeOrmCommons/src/main/java/com/github/nrudenko/orm/commons/DbType.java index f73269f..91b8a97 100644 --- a/LikeOrmCommons/src/main/java/com/github/nrudenko/orm/commons/DbType.java +++ b/LikeOrmCommons/src/main/java/com/github/nrudenko/orm/commons/DbType.java @@ -9,7 +9,7 @@ public enum DbType { TEXT_NOT_NULL("TEXT NOT NULL"), TEXT_DEFAULT_EMPTY("TEXT DEFAULT \"\""), BLOB("BLOB"), - SERIALIZED("BLOB"), + SERIALIZED(""), NO_TYPE(""); // just for default annotation value private String sqlRepresentation; diff --git a/LikeOrmExample/build.gradle b/LikeOrmExample/build.gradle index 46b8112..f81536d 100644 --- a/LikeOrmExample/build.gradle +++ b/LikeOrmExample/build.gradle @@ -20,6 +20,7 @@ android { dependencies { compile 'com.android.support:appcompat-v7:20.+' + compile 'com.google.code.gson:gson:2.2.4' compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':LikeOrmLib') } diff --git a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/DatabaseHelper.java b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/DatabaseHelper.java index a959cae..dd5df2e 100644 --- a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/DatabaseHelper.java +++ b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/DatabaseHelper.java @@ -5,6 +5,8 @@ import com.github.nrudenko.orm.LikeOrmSQLiteOpenHelper; import com.github.nrudenko.orm.example.model.Attach; +import com.github.nrudenko.orm.example.model.ExampleModel; +import com.github.nrudenko.orm.example.model.Message; import java.util.List; @@ -30,8 +32,8 @@ public DatabaseHelper(Context context) { @Override protected void appendSchemes(List classes) { -// classes.add(Message.class); -// classes.add(ExampleModel.class); + classes.add(Message.class); + classes.add(ExampleModel.class); classes.add(Attach.class); } diff --git a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/MainActivity.java b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/MainActivity.java index 25fa5f0..fccf3ba 100644 --- a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/MainActivity.java +++ b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/MainActivity.java @@ -9,7 +9,10 @@ import com.github.nrudenko.orm.CursorUtil; import com.github.nrudenko.orm.QueryBuilder; import com.github.nrudenko.orm.example.model.Attach; +import com.github.nrudenko.orm.example.model.Audio; import com.github.nrudenko.orm.example.model.ExampleModel; +import com.github.nrudenko.orm.example.model.Image; +import com.github.nrudenko.orm.example.model.Message; import java.util.Date; @@ -31,6 +34,24 @@ private void insert() { new QueryBuilder(this, SimpleContentProvider.class) .table(ExampleModel.class) .insert(exampleModel); + + Audio audio = new Audio(); + audio.setDate(new Date()); + audio.setPath("audio path"); + + Image image = new Image(); + audio.setDate(new Date()); + audio.setPath("image"); + + Message message = new Message(); + message.setDate(new Date()); + message.setAudio(audio); + message.setImage(image); + message.setText("lucky message"); + + new QueryBuilder(this, SimpleContentProvider.class) + .table(Message.class) + .insert(message); } private void update() { diff --git a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/adapter/StringSerializeAdapter.java b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/adapter/StringSerializeAdapter.java new file mode 100644 index 0000000..7802e00 --- /dev/null +++ b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/adapter/StringSerializeAdapter.java @@ -0,0 +1,22 @@ +package com.github.nrudenko.orm.example.adapter; + +import android.database.Cursor; + +import com.github.nrudenko.orm.adapter.SerializeAdapter; +import com.github.nrudenko.orm.example.utils.GsonWrapper; + +/** + * Serialize adapter for stores data in byte array + */ +public class StringSerializeAdapter implements SerializeAdapter { + @Override + public String serialize(Object object) { + return GsonWrapper.getGson().toJson(object); + } + + @Override + public Object deserialize(Cursor cursor, int columnIndex, Class modelClass) { + String objectString = cursor.getString(columnIndex); + return GsonWrapper.getGson().fromJson(objectString, modelClass); + } +} diff --git a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/model/Audio.java b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/model/Audio.java new file mode 100644 index 0000000..f2e1980 --- /dev/null +++ b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/model/Audio.java @@ -0,0 +1,25 @@ +package com.github.nrudenko.orm.example.model; + +import java.io.Serializable; +import java.util.Date; + +public class Audio implements Serializable { + String path; + Date date; + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/model/Image.java b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/model/Image.java new file mode 100644 index 0000000..86604ce --- /dev/null +++ b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/model/Image.java @@ -0,0 +1,25 @@ +package com.github.nrudenko.orm.example.model; + +import java.io.Serializable; +import java.util.Date; + +public class Image implements Serializable { + String path; + Date date; + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/model/Message.java b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/model/Message.java index 271600f..27d677e 100644 --- a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/model/Message.java +++ b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/model/Message.java @@ -1,6 +1,10 @@ package com.github.nrudenko.orm.example.model; +import com.github.nrudenko.orm.adapter.BLOBAdapter; +import com.github.nrudenko.orm.annotation.DbColumn; import com.github.nrudenko.orm.annotation.Table; +import com.github.nrudenko.orm.commons.DbType; +import com.github.nrudenko.orm.example.adapter.StringSerializeAdapter; import java.util.Date; @@ -9,6 +13,10 @@ public class Message { String text; Date date; + @DbColumn(type = DbType.SERIALIZED, adapter = BLOBAdapter.class) + Audio audio; + @DbColumn(type = DbType.SERIALIZED, adapter = StringSerializeAdapter.class) + Image image; public String getText() { return text; @@ -26,4 +34,19 @@ public void setDate(Date date) { this.date = date; } + public Audio getAudio() { + return audio; + } + + public void setAudio(Audio audio) { + this.audio = audio; + } + + public Image getImage() { + return image; + } + + public void setImage(Image image) { + this.image = image; + } } diff --git a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/utils/DateUtils.java b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/utils/DateUtils.java new file mode 100644 index 0000000..6c97644 --- /dev/null +++ b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/utils/DateUtils.java @@ -0,0 +1,42 @@ +package com.github.nrudenko.orm.example.utils; + +import android.util.Log; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + + +public class DateUtils { + private static final String TAG = DateUtils.class.getSimpleName(); + + public static final String DATABASE_DATE_FORMAT = "yyyy-MM-dd"; + public static final String SHORT_DATE_PATTERN = "yyyy-MM-dd"; + + private static ArrayList dateFormatArrayList = new ArrayList(); + + static { + dateFormatArrayList.add(new SimpleDateFormat(DATABASE_DATE_FORMAT, Locale.getDefault())); + dateFormatArrayList.add(new SimpleDateFormat(SHORT_DATE_PATTERN, Locale.getDefault())); + } + + private DateUtils() { + // not called + } + + public static Date stringToDate(String stringDate) { + Date result = null; + + for (int i = 0; i < dateFormatArrayList.size(); i++) { + DateFormat dateFormat = dateFormatArrayList.get(i); + try { + result = dateFormat.parse(stringDate); + break; + } catch (ParseException e) { + Log.d(TAG, e.getMessage()); + } + } + return result; + } +} diff --git a/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/utils/GsonWrapper.java b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/utils/GsonWrapper.java new file mode 100644 index 0000000..917c8cb --- /dev/null +++ b/LikeOrmExample/src/main/java/com/github/nrudenko/orm/example/utils/GsonWrapper.java @@ -0,0 +1,55 @@ +package com.github.nrudenko.orm.example.utils; + +import com.google.gson.*; + +import java.lang.reflect.Type; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; + +public class GsonWrapper { + private static Gson gson; + + protected GsonWrapper() { + } + + public static Gson getGson() { + if (gson == null) { + gson = new GsonBuilder() + .registerTypeAdapter(Date.class, new DateAdapter()) + .registerTypeAdapter(java.sql.Date.class, new DateAdapter()) + .create(); + } + return gson; + } + + static class DateAdapter implements JsonSerializer, JsonDeserializer { + @Override + public Date deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + Date result = null; + if (jsonElement != null) { + String stringDate = jsonElement.getAsString(); + if (stringDate.matches("[0-9]+")) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date(jsonElement.getAsLong() * 1000)); + result = calendar.getTime(); + } else { + result = DateUtils.stringToDate(stringDate); + } + } + return result; + } + + @Override + public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) { + JsonElement result = null; + if (date != null) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtils.DATABASE_DATE_FORMAT, Locale.getDefault()); + String stringDate = simpleDateFormat.format(date); + result = new JsonPrimitive(stringDate); + } + return result; + } + } +} diff --git a/LikeOrmLib/src/main/java/com/github/nrudenko/orm/CursorUtil.java b/LikeOrmLib/src/main/java/com/github/nrudenko/orm/CursorUtil.java index 6741b0f..cae25cf 100644 --- a/LikeOrmLib/src/main/java/com/github/nrudenko/orm/CursorUtil.java +++ b/LikeOrmLib/src/main/java/com/github/nrudenko/orm/CursorUtil.java @@ -5,17 +5,14 @@ import android.text.TextUtils; import android.util.Log; +import com.github.nrudenko.orm.adapter.BLOBAdapter; +import com.github.nrudenko.orm.adapter.SerializeAdapter; import com.github.nrudenko.orm.annotation.DbColumn; import com.github.nrudenko.orm.annotation.DbSkipField; import com.github.nrudenko.orm.annotation.VirtualColumn; import com.github.nrudenko.orm.commons.DbType; import com.github.nrudenko.orm.commons.FieldType; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Field; import java.util.ArrayList; @@ -109,28 +106,19 @@ private static T buildModel(Class modelClass, Cursor cursor) { field.set(model, cursor.getBlob(columnIndex)); break; case SERIALIZED: - final byte[] byteArray = cursor.getBlob(columnIndex); - if (byteArray == null) { - continue; - } if (Serializable.class.isAssignableFrom(field.getType())) { - ByteArrayInputStream bis = new ByteArrayInputStream(byteArray); - ObjectInputStream ois = null; - try { - ois = new ObjectInputStream(bis); - Object o = ois.readObject(); - field.set(model, o); - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } finally { - try { - bis.close(); - if (ois != null) - ois.close(); - } catch (IOException e) { - e.printStackTrace(); + if (field.isAnnotationPresent(DbColumn.class)) { + Class serializeAdapterClass = field.getAnnotation(DbColumn.class).adapter(); + if (serializeAdapterClass != null) { + try { + SerializeAdapter serializeAdapter = (SerializeAdapter) serializeAdapterClass.newInstance(); + Object object = serializeAdapter.deserialize(cursor, columnIndex, modelClass); + if (object != null) { + field.set(model, object); + } + } catch (InstantiationException e) { + e.printStackTrace(); + } } } } else { @@ -234,23 +222,22 @@ public static ContentValues objectToContentValues(Object model) { break; case SERIALIZED: if (Serializable.class.isAssignableFrom(field.getType())) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = null; - try { - oos = new ObjectOutputStream(bos); - oos.writeObject(value); - oos.flush(); - bos.close(); - contentValues.put(fieldName, bos.toByteArray()); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - bos.close(); - if (oos != null) - oos.close(); - } catch (IOException e) { - e.printStackTrace(); + if (field.isAnnotationPresent(DbColumn.class)) { + Class serializeAdapterClass = field.getAnnotation(DbColumn.class).adapter(); + if (serializeAdapterClass != null) { + try { + SerializeAdapter serializeAdapter = (SerializeAdapter) serializeAdapterClass.newInstance(); + Object object = serializeAdapter.serialize(value); + if (object != null) { + if (serializeAdapter instanceof BLOBAdapter) { + contentValues.put(fieldName, (byte[]) object); + } else { + contentValues.put(fieldName, (String) object); + } + } + } catch (InstantiationException e) { + e.printStackTrace(); + } } } } else { diff --git a/LikeOrmLib/src/main/java/com/github/nrudenko/orm/adapter/BLOBAdapter.java b/LikeOrmLib/src/main/java/com/github/nrudenko/orm/adapter/BLOBAdapter.java new file mode 100644 index 0000000..eb3669a --- /dev/null +++ b/LikeOrmLib/src/main/java/com/github/nrudenko/orm/adapter/BLOBAdapter.java @@ -0,0 +1,66 @@ +package com.github.nrudenko.orm.adapter; + +import android.database.Cursor; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * Serialize adapter for stores data in byte array + */ +public class BLOBAdapter implements SerializeAdapter { + @Override + public byte[] serialize(Object object) { + byte[] byteArray = null; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = null; + try { + oos = new ObjectOutputStream(bos); + oos.writeObject(object); + oos.flush(); + bos.close(); + byteArray = bos.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + bos.close(); + if (oos != null) + oos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return byteArray; + } + + @Override + public Object deserialize(Cursor cursor, int columnIndex, Class modelClass) { + Object object = null; + final byte[] byteArray = cursor.getBlob(columnIndex); + if (byteArray != null) { + ByteArrayInputStream bis = new ByteArrayInputStream(byteArray); + ObjectInputStream ois = null; + try { + ois = new ObjectInputStream(bis); + object = ois.readObject(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } finally { + try { + bis.close(); + if (ois != null) + ois.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return object; + } +} diff --git a/LikeOrmLib/src/main/java/com/github/nrudenko/orm/adapter/SerializeAdapter.java b/LikeOrmLib/src/main/java/com/github/nrudenko/orm/adapter/SerializeAdapter.java new file mode 100644 index 0000000..4006ed5 --- /dev/null +++ b/LikeOrmLib/src/main/java/com/github/nrudenko/orm/adapter/SerializeAdapter.java @@ -0,0 +1,16 @@ +package com.github.nrudenko.orm.adapter; + +import android.database.Cursor; + +import java.io.Serializable; + +/** + *Interface for save in database serialize data + * in special format. Implementation class should store + * data in some type of database types. + * For example: String or byte array. + */ +public interface SerializeAdapter { + public T serialize(Object object); + public Object deserialize(Cursor cursor, int columnIndex, Class modelClass); +} diff --git a/LikeOrmLib/src/main/java/com/github/nrudenko/orm/annotation/DbColumn.java b/LikeOrmLib/src/main/java/com/github/nrudenko/orm/annotation/DbColumn.java index 1feb2a6..e28e3d2 100644 --- a/LikeOrmLib/src/main/java/com/github/nrudenko/orm/annotation/DbColumn.java +++ b/LikeOrmLib/src/main/java/com/github/nrudenko/orm/annotation/DbColumn.java @@ -1,5 +1,6 @@ package com.github.nrudenko.orm.annotation; +import com.github.nrudenko.orm.adapter.BLOBAdapter; import com.github.nrudenko.orm.commons.DbType; import java.lang.annotation.ElementType; @@ -16,4 +17,6 @@ public DbType type() default DbType.NO_TYPE; public String additional() default ""; + + public Class adapter() default BLOBAdapter.class; }