├── .gitignore ├── Android-TriOrm.iml ├── README.md ├── build.gradle ├── proguard-rules.pro ├── src └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── hendrix │ │ └── triorm │ │ ├── TriData.java │ │ ├── TriDatabase.java │ │ ├── TriOrm.java │ │ ├── TriTable.java │ │ ├── annotations │ │ └── TriTable.java │ │ ├── exceptions │ │ ├── TableAnnotationException.java │ │ └── TableNotExistException.java │ │ ├── interfaces │ │ └── IId.java │ │ ├── query │ │ └── TriQuery.java │ │ └── utils │ │ ├── SReflection.java │ │ └── SSerialize.java │ └── res │ └── values │ └── strings.xml └── triorm.iml /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Android-TriOrm.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android-TriOrm 2 | a 3d database ORM experiment for Android. (used in two commercial projects). 3 | based around small tables concept and `JVM Serialization`. 4 | 5 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Android--TriOrm-green.svg?style=flat)](https://android-arsenal.com/details/1/2293) 6 | 7 | ## How to use 8 | simply fork or download the project, you can also download and create `.aar` file yourself. 9 | 10 | ### Explanation 11 | `TriOrm` is a very light, simple and efficient `ORM` with partial `SQL` wrapping, with the following theme: 12 | * every Object (`TriData` extension) is serialized and saved in the database. 13 | * you can only query by three fields: `id`, `time_created` and `type`. 14 | * familiar no fuss Builder pattern to construct database. 15 | * easy API to query, save and load typed objects. 16 | * a very small usage of annotation(Optional). 17 | * no learning curve whatsoever, no Boiler-plate code. 18 | * Database is ready to use in less than couple of minutes. 19 | * everything is typed. 20 | * most of the presistent is carried by `JVM Serialization` and minimal small SQL table. 21 | 22 | ### construct your Model/Tables 23 | Simply extend `TriData` with the following annotations(Optional). 24 | ```java 25 | @TriTable(dbName = "myDataBase", tableName = "user") 26 | public class User extends TriData { 27 | public String firstName = "John"; 28 | public String lastName = "Dow"; 29 | 30 | public User() { 31 | } 32 | 33 | public User(String id) { 34 | super(id); 35 | } 36 | } 37 | 38 | @TriTable(dbName = "myDataBase", tableName = "location") 39 | public class Location extends TriData { 40 | public String city = "city"; 41 | public String state = "state"; 42 | 43 | public Location() { 44 | } 45 | 46 | } 47 | 48 | ``` 49 | 50 | every `TriData` has the following indexed/query-able properties with getters/setters: 51 | * `setId(..)` - you can set the id or it will be set automatically for you. 52 | * `setType(..)` - some auxiliary field. 53 | * `setTimeCreated(..)` - also set-up for you by default. 54 | 55 | ### construct your Database 56 | constructing a database takes one line of code 57 | ```java 58 | new TriDatabase.Builder(this).addTable(User.class).addTable(Location.class).build(); 59 | 60 | ``` 61 | 62 | and without annotations: 63 | ```java 64 | new TriDatabase.Builder(this).name("myDataBase").addTable("user", User.class).addTable("location", Location.class).build(); 65 | 66 | ``` 67 | 68 | ### Saving into your Database 69 | Simply invoke the `save()` method on your extended `TriData` object. 70 | ```java 71 | User user = new User(); 72 | 73 | user.setId("theDude"); 74 | user.setType("Java programmer"); 75 | 76 | user.firstName = "Jimi"; 77 | user.lastName = "Hendrix"; 78 | 79 | user.save(); 80 | ``` 81 | 82 | ### loading a single object from your Database 83 | Simply use the `TriOrm.load(..)` Singleton and use your typed object. 84 | ```java 85 | User user = TriOrm.load(User.class, "theDude"); 86 | ``` 87 | 88 | ### querying from your Database 89 | Simply use the `TriOrm.query(..)` builder Singleton and use your typed object. 90 | ```java 91 | ArrayList list_users = TriOrm.query(User.class).timeCreatedFrom(0).timeCreatedTo(100).type("Java programmer").build().query(); 92 | ``` 93 | you can query anything from the three properties: `id`, `timeCreated` and `type`. 94 | 95 | ### getting an instance of a table 96 | 97 | Simply use the `TriOrm.table(..)` Singleton and use your typed object. 98 | With table you can have more options and some sandbox methods. 99 | ```java 100 | TriTable table = TriOrm.table(User.class); 101 | ``` 102 | 103 | ### Important Notes 104 | The presistent layer is built around `JVM Serialization`, therefore 105 | there are important considerations for when evolving your model/tables like any 106 | other database solution, beware of the folowing: 107 | * TriData is based on `JVM Serialization`, therefore: 108 | * adding new fields is compatible. 109 | * deleting/renaming exiting fields is **not compatible**, Therefore you will have 110 | to implement your `writeObject/readObject` and be smart about it. 111 | * adding new methods, altering previous methods is incompatible. 112 | * look here for more info [Durable Java: Serialization](http://macchiato.com/columns/Durable4.html) 113 | * I recommend using primitive types as much as possible when designing the model/table. 114 | * for best performence and compatibility control, you can experiment with `Externalizable` interface for reflection free. 115 | * contributions are most welcome with regards to compatiblity/performence. 116 | 117 | 118 | ### Dependencies 119 | * AOSP 120 | 121 | ### Terms 122 | * completely free source code. [Apache License, Version 2.0.](http://www.apache.org/licenses/LICENSE-2.0) 123 | * if you like it -> star or share it with others 124 | 125 | ### Contact Author 126 | * [tomer.shalev@gmail.com](tomer.shalev@gmail.com) 127 | * [Google+ TomershalevMan](https://plus.google.com/+TomershalevMan/about) 128 | * [Facebook - HendrixString](https://www.facebook.com/HendrixString) 129 | 130 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 15 9 | targetSdkVersion 21 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | compile 'com.android.support:appcompat-v7:21.0.3' 24 | } 25 | -------------------------------------------------------------------------------- /proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:/src_mreshet/android/AndroidStudioProjects/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/TriData.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm; 2 | 3 | import android.database.sqlite.SQLiteDatabase; 4 | 5 | import com.hendrix.triorm.interfaces.IId; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * Base model for 3D database. extend this. 11 | * also, it is recommended to use the {@link com.hendrix.triorm.annotations.TriTable} 12 | * annotation for meta-data embedding. 13 | * 14 | * @see com.hendrix.triorm.annotations.TriTable 15 | * 16 | * @author Tomer Shalev 17 | */ 18 | @SuppressWarnings("UnusedDeclaration") 19 | public abstract class TriData implements Serializable, IId { 20 | private static final long serialVersionUID = 0L; 21 | 22 | transient static TriOrm triOrm = null; 23 | 24 | /** 25 | * the identifier of the data 26 | */ 27 | private String _id = null; 28 | /** 29 | * the type of the data 30 | */ 31 | private String _type = null; 32 | /** 33 | * the created/modified time of the data 34 | */ 35 | private long _time_created = 0L; 36 | /** 37 | * the table name 38 | */ 39 | private String _tableName = null; 40 | 41 | public TriData() { 42 | this(null); 43 | } 44 | 45 | protected TriData(String id) { 46 | _time_created = System.currentTimeMillis(); 47 | _id = (id == null) ? String.valueOf(Math.abs(_time_created / 1000)) : id; 48 | 49 | //System.out.println(_id); 50 | } 51 | 52 | /** 53 | * get the identifier 54 | * 55 | * @return the identifier 56 | */ 57 | public String getId() { return _id; } 58 | 59 | /** 60 | * query identifier existence 61 | * 62 | * @return {@code true/false} if id was set 63 | */ 64 | @Override 65 | public boolean hasId() { 66 | return getId()!=null; 67 | } 68 | 69 | /** 70 | * set the string identifier 71 | * 72 | * @param id the identifier 73 | */ 74 | public void setId(String id) { 75 | _id = id; 76 | } 77 | 78 | /** 79 | * get the type field of the data 80 | * 81 | * @return the type 82 | */ 83 | public String getType() { return _type; } 84 | 85 | /** 86 | * set the type field of the data 87 | * 88 | * @param type the type 89 | */ 90 | public void setType(String type) { 91 | _type = type; 92 | } 93 | 94 | /** 95 | * get the time creation/modification of the data 96 | * 97 | * @return the time 98 | */ 99 | public long getTimeCreated() { return _time_created; } 100 | 101 | /** 102 | * set the time creation/modification of the data 103 | * 104 | * @param time_created the time 105 | */ 106 | public void setTimeCreated(long time_created) { 107 | _time_created = time_created; 108 | } 109 | 110 | /** 111 | * @return a printable representation of this object. 112 | */ 113 | @Override 114 | public String toString() { 115 | return "TriData:: (id->" + getId() + ", type->" + getType() +", time_created->" + getTimeCreated() + ")"; 116 | } 117 | 118 | /** 119 | * save the object into the database. 120 | */ 121 | public void save() { 122 | save(SQLiteDatabase.CONFLICT_REPLACE); 123 | } 124 | 125 | /** 126 | * save with conflict behaviour resolution. 127 | * 128 | * @param conflictAlgorithm choose from 129 | * 137 | */ 138 | public void save(int conflictAlgorithm) { 139 | TriData data = this; 140 | 141 | TriTable table = (TriTable) triOrm.getTable(getClass()); 142 | 143 | table.addDataWithConflict(data, conflictAlgorithm); 144 | } 145 | 146 | /** 147 | * delete the object from the database. 148 | */ 149 | public void delete() { 150 | TriData data = this; 151 | 152 | TriTable table = (TriTable) triOrm.getTable(getClass()); 153 | 154 | table.delete(this); 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/TriDatabase.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm; 2 | 3 | import android.content.Context; 4 | 5 | import com.hendrix.triorm.utils.SReflection; 6 | import com.hendrix.triorm.utils.SReflection.Meta; 7 | 8 | import java.util.HashMap; 9 | 10 | /** 11 | * immutable 3D Database. 12 | * may only be built with {@link com.hendrix.triorm.TriDatabase.Builder}. 13 | * After the {@link TriDatabase} was built, it will be automatically registered 14 | * in the {@link com.hendrix.triorm.TriOrm} master object, for future usage. 15 | * (consult documentation of {@code TriOrm}) 16 | * 17 | *
    18 | *
  • use {@link #getTable(Class)} to get the table by id 19 | *
20 | * 21 | * @see TriDatabase.Builder 22 | * 23 | * @author Tomer Shalev 24 | * 25 | */ 26 | @SuppressWarnings("UnusedDeclaration") 27 | public class TriDatabase 28 | { 29 | /** 30 | * the context 31 | */ 32 | private Context _ctx = null; 33 | /** 34 | * the data base name 35 | */ 36 | private String _dbName = null; 37 | /** 38 | * the version of the database 39 | */ 40 | private int _version = 0; 41 | 42 | private HashMap _mapTables = null; 43 | 44 | private TriDatabase(Builder builder) 45 | { 46 | _version = builder._version; 47 | _ctx = builder._ctx; 48 | _dbName = builder._dbName; 49 | _mapTables = builder._mapTables; 50 | 51 | TriOrm.instance().addTables(_mapTables); 52 | } 53 | 54 | /** 55 | * get a table by it's class type. 56 | * 57 | * @param type the type of Class the table handles 58 | * @param the type of Class the table handles 59 | * 60 | * @return the table 61 | */ 62 | @SuppressWarnings("unchecked") 63 | public TriTable getTable(Class type) 64 | { 65 | String uniqueClassName = type.getName(); 66 | 67 | return (TriTable)_mapTables.get(uniqueClassName); 68 | } 69 | 70 | /** 71 | * @return database name 72 | */ 73 | public String getDatabaseName() { 74 | return _dbName; 75 | } 76 | 77 | /** 78 | * @return database version 79 | */ 80 | public int version() { 81 | return _version; 82 | } 83 | 84 | /** 85 | * builder for immutable controller for {@link TriDatabase} 86 | * 87 | * @author Tomer Shalev 88 | */ 89 | public static class Builder 90 | { 91 | private Context _ctx = null; 92 | private String _dbName = null; 93 | private int _version = 1; 94 | 95 | private HashMap _mapTables = null; 96 | 97 | /** 98 | * @param ctx a context 99 | */ 100 | public Builder(Context ctx) { 101 | _ctx = ctx; 102 | 103 | _mapTables = new HashMap<>(); 104 | } 105 | 106 | /** 107 | * build the database 108 | * 109 | * @return {@link TriDatabase} instance 110 | */ 111 | public TriDatabase build() { 112 | return new TriDatabase(this); 113 | } 114 | 115 | /** 116 | * set another context 117 | * 118 | * @see TriDatabase.Builder 119 | */ 120 | public Builder context(Context ctx) { 121 | _ctx = ctx; 122 | 123 | return this; 124 | } 125 | 126 | /** 127 | * set a version 128 | * 129 | * @see TriDatabase.Builder 130 | */ 131 | public Builder Version(int v) { 132 | _version = v; 133 | 134 | return this; 135 | } 136 | 137 | /** 138 | * set the name of the database. 139 | * this is optional if you are using {@link #addTable(Class)}, which forces the usage of 140 | * {@link com.hendrix.triorm.annotations.TriTable} annotations. 141 | * 142 | * @see TriDatabase.Builder 143 | */ 144 | public Builder name(String name) { 145 | _dbName = name; 146 | 147 | return this; 148 | } 149 | 150 | /** 151 | * add a table to the database if it was not already added in the past 152 | * 153 | * @param tableName the table name 154 | * @param type the Class type of the object to store, must implement {@link java.io.Serializable} 155 | * @param the Class type of the object to store, must implement {@link java.io.Serializable} 156 | * 157 | * @see TriDatabase 158 | * @see TriTable 159 | * @see java.io.Serializable 160 | * @see TriDatabase.Builder 161 | * 162 | * @deprecated not really deprecated, but I advocate using {@link #addTable(Class)} with {@link com.hendrix.triorm.annotations.TriTable} class annotations. 163 | */ 164 | public Builder addTable(String tableName, Class type) 165 | { 166 | if(_mapTables.containsKey(tableName)) 167 | return this; 168 | 169 | String uniqueClassName = type.getName(); 170 | 171 | TriTable triTable = new TriTable<>(_ctx, _dbName, tableName, _version); 172 | 173 | _mapTables.put(uniqueClassName, triTable); 174 | 175 | return this; 176 | } 177 | 178 | /** 179 | * add a table to the database if it was not already added in the past using {@link com.hendrix.triorm.annotations.TriTable} 180 | * annotation. 181 | * 182 | * @param type the Class type of the object to store, must implement {@link java.io.Serializable} 183 | * @param the Class type of the object to store, must implement {@link java.io.Serializable} 184 | * 185 | * @see TriDatabase 186 | * @see TriTable 187 | * @see java.io.Serializable 188 | * @see TriDatabase.Builder 189 | * 190 | * @throws java.lang.RuntimeException if meta database name is different from current database name 191 | */ 192 | public Builder addTable(Class type) 193 | { 194 | SReflection.Meta meta = SReflection.extractMetadata(type); 195 | 196 | // guaranteed uniqueness because of packages 197 | String uniqueClassName = type.getName(); 198 | 199 | if(_mapTables.containsKey(uniqueClassName)) 200 | return this; 201 | 202 | validateDataBaseName(meta); 203 | 204 | TriTable triTable = new TriTable<>(_ctx, meta.getDbName(), meta.getTableName(), _version); 205 | 206 | _mapTables.put(uniqueClassName, triTable); 207 | 208 | return this; 209 | } 210 | 211 | /** 212 | * sets and validate the name of the database 213 | * 214 | * @param meta the {@link com.hendrix.triorm.utils.SReflection.Meta} of the table 215 | * 216 | * @throws java.lang.RuntimeException if meta database name is different from current database name 217 | */ 218 | private void validateDataBaseName(Meta meta) { 219 | if(_dbName == null) { 220 | _dbName = meta.getDbName(); 221 | return; 222 | } 223 | 224 | if(!_dbName.equals(meta.getDbName())) 225 | throw new RuntimeException("Table name " + meta.getDbName() + " is not consistent with current name " + _dbName + "caused by the following class" + meta.getTableType().getName()); 226 | } 227 | 228 | } 229 | 230 | } 231 | -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/TriOrm.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm; 2 | 3 | import android.content.Context; 4 | 5 | import com.hendrix.triorm.exceptions.TableNotExistException; 6 | import com.hendrix.triorm.query.TriQuery; 7 | 8 | import java.util.HashMap; 9 | 10 | /** 11 | * the main singleton for {@code 3D} database access. 12 | * 13 | *
    14 | *
  • use {@link TriOrm#query(Class)} to get {@link com.hendrix.triorm.query.TriQuery.Builder} of a table. 15 | *
  • use {@link TriOrm#load(Class, String)} to get a single Data of a table by identifier. 16 | *
  • use {@link TriOrm#table(Class)} to get {@link com.hendrix.triorm.TriTable} reference of the class type. 17 | *
  • use {@link com.hendrix.triorm.TriOrm#newDatabase()} to get a new {@link com.hendrix.triorm.TriDatabase.Builder} instance. 18 | *
19 | * 20 | * TODO: 21 | * - add a method to get all the tables of a specific database by name. 22 | * 23 | * @author Tomer Shalev 24 | * 25 | */ 26 | @SuppressWarnings("UnusedDeclaration") 27 | public final class TriOrm 28 | { 29 | private static TriOrm _instance = null; 30 | /** 31 | * the context 32 | */ 33 | private Context _ctx = null; 34 | /** 35 | * class names with package to {@link TriTable} map 36 | */ 37 | private HashMap _mapTables = null; 38 | 39 | private TriOrm() { 40 | if(_instance != null) 41 | throw new RuntimeException("TriOrm is a singleton. please use TriOrm.instance() instead"); 42 | 43 | TriData.triOrm = this; 44 | _mapTables = new HashMap<>(); 45 | } 46 | 47 | /** 48 | * get the representing {@link TriTable} 49 | * 50 | * @param type the class type of the table 51 | * @param the type itself 52 | * 53 | * @return {@link TriTable} 54 | */ 55 | public static TriTable table(Class type) { 56 | return instance().getTable(type); 57 | } 58 | 59 | /** 60 | * load data from the table by identifier. 61 | * 62 | * @param type the class type of the table 63 | * @param id the identifier of the data 64 | * @param the type itself 65 | * 66 | * @return the data 67 | */ 68 | public static T load(Class type, String id) { 69 | return table(type).getData(id); 70 | } 71 | 72 | /** 73 | * get the query builder. 74 | * 75 | * @param type the class type of the table 76 | * @param the type itself 77 | * 78 | * @return the {@link com.hendrix.triorm.query.TriQuery.Builder} instance 79 | * 80 | * @see com.hendrix.triorm.query.TriQuery.Builder 81 | */ 82 | public static TriQuery.Builder query(Class type) { 83 | return table(type).getQueryBuilder(); 84 | } 85 | 86 | /** 87 | * get a new Database builder object. you can also use: 88 | * {@code new TriDatabase.Builder(..)} yourself. 89 | * 90 | * @return {@link com.hendrix.triorm.TriDatabase.Builder} 91 | */ 92 | public static TriDatabase.Builder newDatabase() { 93 | return new TriDatabase.Builder(null); 94 | } 95 | 96 | /** 97 | * get the instance. package protected. 98 | * 99 | * @return the only {link TriOrm} instance. 100 | */ 101 | static protected TriOrm instance() { 102 | return (_instance==null) ? _instance = new TriOrm() : _instance; 103 | } 104 | 105 | /** 106 | * add tables to the ORM. this is used by {@link com.hendrix.triorm.TriDatabase} and therefore is protected access. 107 | * 108 | * @param tables a Map Collection between class names into {@link com.hendrix.triorm.TriTable} 109 | */ 110 | protected void addTables(HashMap tables) { 111 | _mapTables.putAll(tables); 112 | } 113 | 114 | /** 115 | * get a table by it's identifier from any database that was loaded. 116 | * table names a are unique, since the class type is used. Therefore, 117 | * client does not have to specify database name. 118 | * 119 | * @param type the type of Class the table handles 120 | * @param the type of Class the table handles 121 | * 122 | * @return the table 123 | * 124 | * @throws com.hendrix.triorm.exceptions.TableNotExistException if the table was not registered. 125 | */ 126 | @SuppressWarnings("unchecked") 127 | protected TriTable getTable(Class type) 128 | { 129 | TriTable triTable = (TriTable)_mapTables.get(type.getName()); 130 | 131 | if(triTable == null) 132 | throw new TableNotExistException(type); 133 | 134 | return triTable; 135 | } 136 | 137 | } -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/TriTable.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Context; 5 | import android.database.Cursor; 6 | import android.database.sqlite.SQLiteDatabase; 7 | import android.database.sqlite.SQLiteOpenHelper; 8 | 9 | import com.hendrix.triorm.query.TriQuery; 10 | import com.hendrix.triorm.query.TriQuery.ORDER; 11 | import com.hendrix.triorm.utils.SSerialize; 12 | 13 | import java.util.ArrayList; 14 | 15 | /** 16 | * simple 3D SQL table carrier with {@code (id, type, data, time_created)} rows, that serializes/deserialize to/from database.
17 | *
    18 | *
  • use {@link #addData(TriData)}, {@link #addDataWithConflict(TriData, int)} to add data. 19 | *
  • use {@link #getData(String)} to get a single data by identifier. 20 | *
  • use {@link #delete(String)}, {@link #delete(TriData)} to delete data. 21 | *
  • use {@link #getQueryBuilder()} to get the query builder. 22 | *
  • there are also other query methods, but all are based on {@link #getQueryBuilder()}. 23 | *
24 | * 25 | * Notes: 26 | * 27 | * the recommended way to access a table is with {@link TriOrm} object. 28 | *
    29 | *
  • use {@link TriOrm#query(Class)} to get {@link #getQueryBuilder()} of a table. 30 | *
  • use {@link TriOrm#load(Class, String)} to get a single Data of a table by identifier. 31 | *
  • use {@link TriOrm#table(Class)} to get {@link com.hendrix.triorm.TriTable} reference of the class type. 32 | *
33 | * 34 | * @param the Class type of the object to store, must implement {@link com.hendrix.triorm.TriData} 35 | * 36 | * @author Tomer Shalev 37 | */ 38 | @SuppressWarnings("UnusedDeclaration") 39 | public class TriTable extends SQLiteOpenHelper 40 | { 41 | private TriQuery.Builder _queryBuilder = null; 42 | 43 | // Database Version 44 | protected int DATABASE_VERSION = 1; 45 | 46 | // Database Name 47 | protected String DATABASE_NAME; 48 | 49 | // Table name 50 | protected String TABLE_NAME; 51 | 52 | /** 53 | * get the query builder 54 | * 55 | * @return the {@link TriQuery.Builder} reference 56 | */ 57 | synchronized public TriQuery.Builder getQueryBuilder() { 58 | return _queryBuilder.reset(); 59 | } 60 | 61 | /** 62 | * get the database name 63 | * 64 | * @return the database name 65 | */ 66 | public String DATABASE_NAME() { 67 | return DATABASE_NAME; 68 | } 69 | 70 | /** 71 | * get the table name 72 | * 73 | * @return the table name 74 | */ 75 | public String TABLE_NAME() { 76 | return TABLE_NAME; 77 | } 78 | 79 | /** 80 | * enum describing the columns of the table 81 | * 82 | * {@code {KEY_ID, KEY_TYPE, KEY_DATA, KEY_CREATED}} 83 | */ 84 | public enum Columns { 85 | KEY_ID("id", 0), KEY_TYPE("type", 1), KEY_DATA("data", 2), KEY_CREATED("time_created", 3); 86 | 87 | private Columns(String key, int index) { 88 | _index = index; 89 | _key = key; 90 | } 91 | 92 | private int _index; 93 | private String _key; 94 | 95 | public int index() { 96 | return _index; 97 | } 98 | 99 | public String key() { 100 | return _key; 101 | } 102 | } 103 | 104 | /** 105 | * A new table 106 | * 107 | * @param context Android's context 108 | * @param databaseName name of the database to be created or loaded 109 | * @param tableName the name of the table to be loaded 110 | * @param version version number 111 | */ 112 | public TriTable(Context context, String databaseName, String tableName, int version) 113 | { 114 | super(context, databaseName, null, version); 115 | 116 | DATABASE_VERSION = version; 117 | 118 | DATABASE_NAME = databaseName; 119 | TABLE_NAME = tableName; 120 | 121 | onCreate(getWritableDatabase()); 122 | } 123 | 124 | @Override 125 | public void onCreate(SQLiteDatabase db) 126 | { 127 | String CREATE_TABLE_COMMAND = "CREATE TABLE IF NOT EXISTS " 128 | + TABLE_NAME + "(" 129 | + Columns.KEY_ID.key() + " TEXT PRIMARY KEY, " 130 | + Columns.KEY_TYPE.key() + " STRING, " 131 | //+ Columns.KEY_DATA.key() + " TEXT, " 132 | + Columns.KEY_DATA.key() + " BLOB, " 133 | + Columns.KEY_CREATED.key() + " INTEGER" + ")"; 134 | 135 | db.execSQL(CREATE_TABLE_COMMAND); 136 | 137 | _queryBuilder = new TriQuery.Builder<>(this); 138 | _queryBuilder.flagCacheQuery = true; 139 | } 140 | 141 | @Override 142 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 143 | { 144 | // Drop older table if existed 145 | db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); 146 | 147 | // Create tables again 148 | onCreate(db); 149 | } 150 | 151 | /** 152 | * add/replace new/older data, or update an older one with the correct conflict algorithm 153 | * 154 | * @param data the data 155 | */ 156 | public void addData(T data) 157 | { 158 | addDataWithConflict(data, SQLiteDatabase.CONFLICT_REPLACE); 159 | } 160 | 161 | /** 162 | * add new data, or update an older one with the correct conflict algorithm 163 | * 164 | * @param data the data 165 | * @param conflictAlgorithm for example SQLiteDatabase.CONFLICT_REPLACE 166 | * 167 | */ 168 | public void addDataWithConflict(T data, int conflictAlgorithm) 169 | { 170 | SQLiteDatabase db = this.getWritableDatabase(); 171 | 172 | ContentValues values = new ContentValues(); 173 | 174 | values.put(Columns.KEY_ID.key(), data.getId()); 175 | values.put(Columns.KEY_TYPE.key(), data.getType()); 176 | //values.put(Columns.KEY_DATA.key(), SSerialize.serialize(data)); 177 | values.put(Columns.KEY_DATA.key(), SSerialize.serializeToByteArray(data)); 178 | values.put(Columns.KEY_CREATED.key(), data.getTimeCreated()); 179 | 180 | if(data.getId() == null) 181 | throw new NullPointerException("data.getId() = null"); 182 | 183 | // Inserting Row 184 | db.insertWithOnConflict(TABLE_NAME, null, values, conflictAlgorithm); 185 | db.close(); 186 | } 187 | 188 | /** 189 | * general get data 190 | * 191 | * @return {@link ArrayList} of data 192 | */ 193 | synchronized public ArrayList getData( String idFrom, String idTo, 194 | String type, long createdFrom, long createdTo) 195 | { 196 | return _queryBuilder.reset().idFrom(idFrom).idTo(idTo).type(type).timeCreatedFrom(createdFrom).timeCreatedTo(createdTo).ORDER(Columns.KEY_CREATED, ORDER.DESC).build().query(); 197 | } 198 | 199 | /** 200 | * Select data by it's identifier 201 | * 202 | * @param id the id of the data 203 | * @return the data 204 | */ 205 | public T getData(String id) 206 | { 207 | SQLiteDatabase db = this.getReadableDatabase(); 208 | 209 | Cursor cursor = db.query(TABLE_NAME, new String[] { Columns.KEY_DATA.key() }, Columns.KEY_ID.key() + "=?", new String[] { String.valueOf(id) }, null, null, null, null); 210 | 211 | if(cursor==null || (cursor.getCount()==0)) 212 | return null; 213 | 214 | cursor.moveToFirst(); 215 | 216 | //T res = SSerialize.deserialize(cursor.getString(0)); ****** 217 | T res = SSerialize.deserialize(cursor.getBlob(0)); 218 | 219 | cursor.close(); 220 | 221 | return res; 222 | } 223 | 224 | /** 225 | * Select data set by it's type 226 | * 227 | * @param type the type of the data 228 | * 229 | * @return {@link ArrayList} of data 230 | */ 231 | public ArrayList getDataByType(String type) 232 | { 233 | return _queryBuilder.reset().type(type).build().query(); 234 | } 235 | 236 | /** 237 | * Select data from a window of identifiers. useful when ids are timestamps. 238 | * requires QA. 239 | * 240 | * @param idFrom starting id 241 | * @param idTo last id 242 | * 243 | * @return {@link ArrayList} of data 244 | */ 245 | public ArrayList getDataBetweenId(String idFrom, String idTo) 246 | { 247 | return _queryBuilder.reset().idFrom(idFrom).idTo(idTo).build().query(); 248 | } 249 | 250 | /** 251 | * Select data from a window of time_created with projected type requires QA. 252 | * 253 | * @param date_from time_created start 254 | * @param date_to time_created end 255 | * @param type the type 256 | * 257 | * @return {@link ArrayList} of data 258 | */ 259 | public ArrayList getDataBetweenDateWithType(long date_from, long date_to, String type) 260 | { 261 | return _queryBuilder.reset().timeCreatedFrom(date_from).timeCreatedTo(date_to).type(type).ORDER(Columns.KEY_CREATED, ORDER.DESC).build().query(); 262 | } 263 | 264 | /** 265 | * Select data from a window of time_created with projected type requires QA. 266 | * 267 | * @param date_from time_created start 268 | * @param date_to time_created end 269 | * 270 | * @return {@link ArrayList} of data 271 | */ 272 | public ArrayList getDataBetweenDate(long date_from, long date_to) 273 | { 274 | return _queryBuilder.reset().timeCreatedFrom(date_from).timeCreatedTo(date_to).ORDER(Columns.KEY_CREATED, ORDER.DESC).build().query(); 275 | } 276 | 277 | /** 278 | * Select data from a window of identifiers with casted type. useful when ids are timestamps. 279 | * 280 | * @param idFrom starting id 281 | * @param idTo last id 282 | * @param type the type 283 | * 284 | * @return {@link ArrayList} of data 285 | */ 286 | public ArrayList getDataBetweenIdWithType(String idFrom, String idTo, String type) 287 | { 288 | return _queryBuilder.reset().idFrom(idFrom).idTo(idTo).type(type).build().query(); 289 | } 290 | 291 | /** 292 | * Select latest data with limit 293 | * 294 | * @param limit the max amount of latest objects 295 | * 296 | * @return {@link ArrayList} of data 297 | */ 298 | public ArrayList getAllData(int limit) 299 | { 300 | return _queryBuilder.reset().ORDER(Columns.KEY_ID, ORDER.DESC).LIMIT(limit).build().query(); 301 | } 302 | 303 | /** 304 | * update an already existing data by identifier 305 | * 306 | * @param id the id of the data 307 | * @param data the updated data 308 | * 309 | * @return the number of rows affected 310 | */ 311 | public int updateData(String id, T data) 312 | { 313 | SQLiteDatabase db = this.getWritableDatabase(); 314 | 315 | ContentValues values = new ContentValues(); 316 | 317 | values.put(Columns.KEY_ID.key(), data.getId()); 318 | values.put(Columns.KEY_TYPE.key(), data.getType()); 319 | values.put(Columns.KEY_DATA.key(), SSerialize.serializeToByteArray(data)); 320 | values.put(Columns.KEY_CREATED.key(), data.getTimeCreated()); 321 | 322 | // updating row 323 | return db.update(TABLE_NAME, values, Columns.KEY_ID.key() + " = ?", new String[] { id }); 324 | } 325 | 326 | /** 327 | * delete data by identifier 328 | * 329 | * @param id the id of the data 330 | */ 331 | public void delete(String id) 332 | { 333 | SQLiteDatabase db = this.getWritableDatabase(); 334 | 335 | db.delete(TABLE_NAME, Columns.KEY_ID.key() + " = ?", new String[] { id }); 336 | db.close(); 337 | } 338 | 339 | /** 340 | * delete data by identifier 341 | * 342 | * @param data the data of the data 343 | */ 344 | public void delete(T data) 345 | { 346 | delete(data.getId()); 347 | } 348 | 349 | /** 350 | * delete all of the data 351 | */ 352 | public void deleteAllData() 353 | { 354 | SQLiteDatabase db = this.getWritableDatabase(); 355 | 356 | db.delete(TABLE_NAME, null, null); 357 | db.close(); 358 | } 359 | 360 | /** 361 | * grab the amount of rows 362 | * 363 | * @return the count 364 | */ 365 | public int getDataCount() 366 | { 367 | String countQuery = "SELECT * FROM " + TABLE_NAME; 368 | SQLiteDatabase db = this.getReadableDatabase(); 369 | Cursor cursor = db.rawQuery(countQuery, null); 370 | 371 | int result = cursor.getCount(); 372 | 373 | cursor.close(); 374 | 375 | // return count 376 | return result; 377 | } 378 | 379 | } -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/annotations/TriTable.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Meta-data annotation for table represented by {@link com.hendrix.triorm.TriData} 10 | * 11 | * @author Tomer Shalev 12 | */ 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target(ElementType.TYPE) 15 | public @interface TriTable { 16 | /** 17 | * 18 | * @return the database name 19 | */ 20 | public String dbName(); 21 | 22 | /** 23 | * 24 | * @return the table name inside the database 25 | */ 26 | public String tableName(); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/exceptions/TableAnnotationException.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm.exceptions; 2 | 3 | /** 4 | * Meta-data extraction exception. 5 | * 6 | * @see com.hendrix.triorm.annotations.TriTable 7 | * 8 | * @author Tomer Shalev 9 | */ 10 | public class TableAnnotationException extends RuntimeException { 11 | public TableAnnotationException() { 12 | super("TriOrm - table annotation problem. make sure the class is annotated, and only once."); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/exceptions/TableNotExistException.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm.exceptions; 2 | 3 | /** 4 | * Exception that is raised when trying to access a table that was not registered. 5 | * 6 | * @author Tomer Shalev 7 | */ 8 | public class TableNotExistException extends RuntimeException { 9 | public TableNotExistException(Class type) { 10 | super("TriOrm - table for type " + type.getName() + " does not exist! add it."); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/interfaces/IId.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm.interfaces; 2 | 3 | @SuppressWarnings("UnusedDeclaration") 4 | public interface IId { 5 | /** 6 | * set the string identifier 7 | * 8 | * @param id the identifier 9 | */ 10 | void setId(String id); 11 | 12 | /** 13 | * get the identifier 14 | * 15 | * @return the identifier 16 | */ 17 | String getId(); 18 | 19 | /** 20 | * query identifier existence 21 | * 22 | * @return {@code true/false} if id was set 23 | */ 24 | boolean hasId(); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/query/TriQuery.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm.query; 2 | 3 | import android.database.Cursor; 4 | import android.database.sqlite.SQLiteDatabase; 5 | 6 | import com.hendrix.triorm.TriData; 7 | import com.hendrix.triorm.TriTable; 8 | import com.hendrix.triorm.TriTable.Columns; 9 | import com.hendrix.triorm.utils.SSerialize; 10 | 11 | import java.util.ArrayList; 12 | 13 | /** 14 | * a {@code SQL} query builder according to the identifier, type, time_created fields of {@link com.hendrix.triorm.TriTable.Columns} 15 | * 16 | * @param the data type 17 | * 18 | * @author Tomer Shalev 19 | */ 20 | @SuppressWarnings("UnusedDeclaration") 21 | public class TriQuery { 22 | 23 | private String _rawQueryString = null; 24 | private TriTable _ssd = null; 25 | /** 26 | * limit 27 | */ 28 | private int _limit = Integer.MAX_VALUE; 29 | /** 30 | * order by column 31 | */ 32 | private Columns _by = null; 33 | /** 34 | * order of results 35 | */ 36 | private ORDER _order = ORDER.NONE; 37 | 38 | /** 39 | * enum for describing order {@code {DESC, ASC, NONE}} 40 | */ 41 | public enum ORDER{DESC, ASC, NONE} 42 | 43 | private TriQuery(Builder builder) { 44 | update(builder); 45 | } 46 | 47 | /** 48 | * update a recycled builder 49 | * 50 | * @param builder the builder that was recycled 51 | */ 52 | private void update(Builder builder) { 53 | _rawQueryString = builder._rawQueryString; 54 | _ssd = builder._ssd; 55 | _limit = builder._limit; 56 | _by = builder._by; 57 | _order = builder._order; 58 | } 59 | 60 | /** 61 | * perform the query 62 | * 63 | * @return {@link java.util.ArrayList} of data 64 | */ 65 | @SuppressWarnings("unchecked") 66 | public ArrayList query() 67 | { 68 | SQLiteDatabase db = _ssd.getReadableDatabase(); 69 | 70 | ArrayList listData = new ArrayList<>(); 71 | 72 | String orderBy = null; 73 | 74 | if(_order != ORDER.NONE && _by!=null) { 75 | orderBy = _by.key() + " " + _order.name(); 76 | } 77 | 78 | String limit = (_limit==Integer.MAX_VALUE) ? null : String.valueOf(_limit); 79 | 80 | Cursor cursor = db.query(_ssd.TABLE_NAME(), new String[] {Columns.KEY_DATA.key() }, _rawQueryString, null, null, null, orderBy, limit); 81 | 82 | int a = cursor.getCount(); 83 | 84 | if(cursor==null || (cursor.getCount()==0)) 85 | return listData; 86 | 87 | if (cursor.moveToFirst()) { 88 | do { 89 | // String data = cursor.getString(0); ***** 90 | byte[] data = cursor.getBlob(0); 91 | 92 | Object dd = SSerialize.deserialize(data); 93 | 94 | listData.add((T) SSerialize.deserialize(data)); 95 | } while (cursor.moveToNext()); 96 | } 97 | 98 | //cursor.close(); 99 | 100 | return listData; 101 | } 102 | 103 | /** 104 | * the builder of the query 105 | * 106 | * @param the data type 107 | * 108 | * @see com.hendrix.triorm.query.TriQuery 109 | * 110 | * @author Tomer Shalev 111 | */ 112 | public static class Builder { 113 | 114 | /** 115 | * recycle the TriQuery object? 116 | */ 117 | public boolean flagCacheQuery = false; 118 | 119 | private String _idFrom = null; 120 | private String _idTo = null; 121 | private String _type = null; 122 | private String _rawQueryString = null; 123 | private long _time_created_from = -1L; 124 | private long _time_created_to = -1L; 125 | 126 | /** 127 | * order by column 128 | */ 129 | private Columns _by = null; 130 | /** 131 | * order of results 132 | */ 133 | private ORDER _order = ORDER.NONE; 134 | /** 135 | * limit of results 136 | */ 137 | private int _limit = Integer.MAX_VALUE; 138 | 139 | /** 140 | * the table on which to perform the query 141 | */ 142 | private TriTable _ssd = null; 143 | /** 144 | * the cached query 145 | * 146 | * @see #flagCacheQuery 147 | */ 148 | private TriQuery _cachedQuery = null; 149 | 150 | /** 151 | * @param ssd the table on which to perform the query 152 | */ 153 | public Builder(TriTable ssd) { 154 | _ssd = ssd; 155 | } 156 | 157 | /** 158 | * build the query 159 | * 160 | * @return a {@link com.hendrix.triorm.query.TriQuery} instance 161 | */ 162 | public TriQuery build(){ 163 | buildString(); 164 | //reset(); 165 | 166 | TriQuery query = (flagCacheQuery) ? (_cachedQuery==null ? _cachedQuery=new TriQuery<>(this) : _cachedQuery) : new TriQuery(this); 167 | 168 | if(flagCacheQuery) 169 | query.update(this); 170 | 171 | return query; 172 | } 173 | 174 | /** 175 | * build the {@code SQL} query string 176 | * 177 | * @return the {@code SQL} string 178 | */ 179 | public String buildString() 180 | { 181 | String id_selection, type_selection, created_selection, query = ""; 182 | boolean isFirst = true; 183 | 184 | if(_idFrom!=null && _idTo!=null) { 185 | id_selection = "(" + Columns.KEY_ID.key() + " BETWEEN '" + _idFrom + "' AND '" + _idTo + "')"; 186 | query = id_selection; 187 | isFirst = false; 188 | } 189 | 190 | if(_type!=null) { 191 | type_selection = "(" + Columns.KEY_TYPE.key() + " = '" + _type + "')"; 192 | query = (!isFirst) ? query + " AND " + type_selection : type_selection; 193 | isFirst = false; 194 | } 195 | 196 | if(_time_created_from>=0 && _time_created_to>=0) { 197 | created_selection = "(" + Columns.KEY_CREATED.key() + " BETWEEN '" + Long.toString(_time_created_from) + "' AND '" + Long.toString(_time_created_to) + "')"; 198 | query = (!isFirst) ? query + " AND " + created_selection : created_selection; 199 | isFirst = false; 200 | } 201 | 202 | if(isFirst) { 203 | // query=null will force SELECT *.. ->from the android api 204 | query = null; 205 | } 206 | 207 | return (_rawQueryString = query); 208 | } 209 | 210 | /** 211 | * @return a printable representation of the {@code SQL} query {@code SELECTION} string 212 | */ 213 | @Override 214 | public String toString() { 215 | return _rawQueryString; 216 | } 217 | 218 | /** 219 | * reset the builder for recycling purposes. always user reset if. 220 | * 221 | * @return the reset recycled builder 222 | * 223 | * @see com.hendrix.triorm.query.TriQuery.Builder 224 | */ 225 | public Builder reset() { 226 | _idFrom = null; 227 | _idTo = null; 228 | _type = null; 229 | _rawQueryString = null; 230 | _by = null; 231 | _order = ORDER.NONE; 232 | _limit = Integer.MAX_VALUE; 233 | _time_created_from = -1L; 234 | _time_created_to = -1L; 235 | 236 | return this; 237 | } 238 | 239 | /** 240 | * set starting id for query 241 | * 242 | * @param from the starting identifier 243 | * 244 | * @return the Builder 245 | * 246 | * @see com.hendrix.triorm.query.TriQuery.Builder 247 | */ 248 | public Builder idFrom(String from) { 249 | _idFrom = from; 250 | 251 | return this; 252 | } 253 | 254 | /** 255 | * set destination id for query 256 | * 257 | * @param to the destination identifier 258 | * 259 | * @return the Builder 260 | * 261 | * @see com.hendrix.triorm.query.TriQuery.Builder 262 | */ 263 | public Builder idTo(String to) { 264 | _idTo = to; 265 | 266 | return this; 267 | } 268 | 269 | /** 270 | * set the type for query 271 | * 272 | * @param type the type 273 | * 274 | * @return the Builder 275 | * 276 | * @see com.hendrix.triorm.query.TriQuery.Builder 277 | */ 278 | public Builder type(String type) { 279 | _type = type; 280 | 281 | return this; 282 | } 283 | 284 | /** 285 | * set the starting creation time for query 286 | * 287 | * @param from the starting creation time 288 | * 289 | * @return the Builder 290 | * 291 | * @see com.hendrix.triorm.query.TriQuery.Builder 292 | */ 293 | public Builder timeCreatedFrom(long from) { 294 | _time_created_from = from; 295 | 296 | return this; 297 | } 298 | 299 | /** 300 | * set the destination creation time for query 301 | * 302 | * @param to the destination creation time 303 | * 304 | * @return the Builder 305 | * 306 | * @see com.hendrix.triorm.query.TriQuery.Builder 307 | */ 308 | public Builder timeCreatedTo(long to) { 309 | _time_created_to = to; 310 | 311 | return this; 312 | } 313 | 314 | /** 315 | * set the order for query 316 | * 317 | * @param by order by which column 318 | * @param order the order 319 | * 320 | * @return the Builder 321 | * 322 | * @see com.hendrix.triorm.query.TriQuery.Builder 323 | */ 324 | public Builder ORDER(Columns by, ORDER order) 325 | { 326 | _by = by; 327 | _order = order; 328 | 329 | return this; 330 | } 331 | 332 | /** 333 | * set the limit of the query result 334 | * 335 | * @param limit the limit of the query 336 | * 337 | * @return the Builder 338 | * 339 | * @see com.hendrix.triorm.query.TriQuery.Builder 340 | */ 341 | public Builder LIMIT(int limit) 342 | { 343 | _limit = limit; 344 | 345 | return this; 346 | } 347 | 348 | } 349 | 350 | } 351 | -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/utils/SReflection.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm.utils; 2 | 3 | import com.hendrix.triorm.TriData; 4 | import com.hendrix.triorm.annotations.TriTable; 5 | import com.hendrix.triorm.exceptions.TableAnnotationException; 6 | 7 | import java.lang.annotation.Annotation; 8 | 9 | /** 10 | * a Helper class for {@code Reflections} utilities 11 | * 12 | * @author Tomer Shalev 13 | */ 14 | @SuppressWarnings("UnusedDeclaration") 15 | public class SReflection { 16 | 17 | private SReflection() { 18 | } 19 | 20 | /** 21 | * extract the {@link com.hendrix.triorm.annotations.TriTable} annotation from a {@link com.hendrix.triorm.TriData} 22 | * 23 | * @param cls the class type of the extended {@link com.hendrix.triorm.TriData} 24 | * @param the type of the extended {@link com.hendrix.triorm.TriData} 25 | * 26 | * @return a {@link com.hendrix.triorm.utils.SReflection.Meta} 27 | * 28 | * @throws com.hendrix.triorm.exceptions.TableAnnotationException if the class is not annotated, or has more than one 29 | * {@link com.hendrix.triorm.annotations.TriTable} annotation 30 | */ 31 | public static Meta extractMetadata(Class cls) { 32 | Annotation[] annotations = cls.getAnnotations(); 33 | Meta meta = null; 34 | 35 | boolean flagCompatibleAnnotationFound = false; 36 | 37 | for(Annotation annotation : annotations){ 38 | if(annotation instanceof TriTable){ 39 | if(flagCompatibleAnnotationFound) 40 | throw new TableAnnotationException(); 41 | 42 | flagCompatibleAnnotationFound = true; 43 | 44 | TriTable triTable = (TriTable) annotation; 45 | 46 | meta = new Meta<>(triTable.dbName(), triTable.tableName(), cls); 47 | } 48 | } 49 | 50 | if(!flagCompatibleAnnotationFound) 51 | throw new TableAnnotationException(); 52 | 53 | return meta; 54 | } 55 | 56 | /** 57 | * a class representing the meta data represented by {@link com.hendrix.triorm.annotations.TriTable} annotation 58 | */ 59 | public static class Meta { 60 | private String db_name = null; 61 | private String table_name = null; 62 | private Class type = null; 63 | 64 | /** 65 | * 66 | * @param db_name the name of the database 67 | * @param table_name the name of the table 68 | * @param type the type of the table 69 | */ 70 | private Meta(String db_name, String table_name, Class type) { 71 | this.db_name = db_name; 72 | this.table_name = table_name; 73 | this.type = type; 74 | } 75 | 76 | 77 | /** 78 | * 79 | * @return the name of the database 80 | */ 81 | public String getDbName() { 82 | return db_name; 83 | } 84 | 85 | /** 86 | * 87 | * @return the name of the table 88 | */ 89 | public String getTableName() { 90 | return table_name; 91 | } 92 | 93 | /** 94 | * 95 | * @return the name of the table 96 | */ 97 | public Class getTableType() { 98 | return type; 99 | } 100 | 101 | } 102 | 103 | public static String logicName(Meta meta){ 104 | return meta.db_name + meta.table_name; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/hendrix/triorm/utils/SSerialize.java: -------------------------------------------------------------------------------- 1 | package com.hendrix.triorm.utils; 2 | 3 | import android.util.Base64; 4 | 5 | import java.io.ByteArrayInputStream; 6 | import java.io.ByteArrayOutputStream; 7 | import java.io.IOException; 8 | import java.io.ObjectInputStream; 9 | import java.io.ObjectOutputStream; 10 | import java.io.Serializable; 11 | 12 | /** 13 | * Helper class utilities for {@code serializing} and {@code deserialize} {@code Typed} objects into/from 14 | * {@code byte arrays} and {@code base64 encoded} strings. 15 | * 16 | * @author Tomer Shalev 17 | */ 18 | @SuppressWarnings("UnusedDeclaration") 19 | public class SSerialize { 20 | 21 | private SSerialize() { 22 | } 23 | 24 | /** 25 | * Serialize a {@link Serializable} object -> {@code byte[]} -> {@code Base64 Encoded string} 26 | * 27 | * @param obj {@link Serializable} object 28 | * @param parameter type that extends {@link Serializable} 29 | * 30 | * @return {@code Base64 Encoded string} 31 | */ 32 | static public String serialize(T obj) 33 | { 34 | return Base64.encodeToString(serializeToByteArray(obj), Base64.DEFAULT ); 35 | } 36 | 37 | /** 38 | * Serialize a {@link Serializable} object -> {@code byte[]} 39 | * 40 | * @param obj {@link Serializable} object 41 | * @param parameter type that extends {@link Serializable} 42 | * 43 | * @return {@code byte array} 44 | */ 45 | static public byte[] serializeToByteArray(T obj) 46 | { 47 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 48 | 49 | try { 50 | ObjectOutputStream oos = new ObjectOutputStream( baos ); 51 | oos.writeObject( obj ); 52 | oos.close(); 53 | } catch (IOException e) { 54 | // TODO: handle exception 55 | } 56 | 57 | return baos.toByteArray(); 58 | } 59 | 60 | /** 61 | * DeSerializes a {@code Base64 Encoded string} -> {@code byte[]} -> {@link Serializable} Typed Object. 62 | * 63 | * @param str {@code Base64 Encoded string} 64 | * @param parameter type that extends {@link Serializable} 65 | * 66 | * @return {@link Serializable} Typed Object. 67 | */ 68 | static public T deserialize(String str) 69 | { 70 | byte[] data = Base64.decode(str, Base64.DEFAULT); 71 | 72 | return deserialize(data); 73 | } 74 | 75 | /** 76 | * De-Serializes a {@code byte[]} -> {@link Serializable} Typed Object. 77 | * 78 | * @param data byte array 79 | * @param parameter type that extends {@link Serializable} 80 | * 81 | * @return {@link Serializable} Typed Object. 82 | */ 83 | @SuppressWarnings("unchecked") 84 | static public T deserialize(byte [] data) 85 | { 86 | ObjectInputStream ois; 87 | T o = null; 88 | 89 | try { 90 | 91 | ois = new ObjectInputStream(new ByteArrayInputStream( data ) ); 92 | o = (T)ois.readObject(); 93 | ois.close(); 94 | 95 | } catch (IOException | ClassNotFoundException e) { 96 | // TODO: handle exception 97 | } 98 | 99 | return o; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | TriOrm 3 | 4 | -------------------------------------------------------------------------------- /triorm.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | --------------------------------------------------------------------------------