├── .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 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
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 |
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 | [](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 | *
130 | * {@link android.database.sqlite.SQLiteDatabase#CONFLICT_ABORT}
131 | * {@link android.database.sqlite.SQLiteDatabase#CONFLICT_FAIL}
132 | * {@link android.database.sqlite.SQLiteDatabase#CONFLICT_IGNORE}
133 | * {@link android.database.sqlite.SQLiteDatabase#CONFLICT_NONE}
134 | * {@link android.database.sqlite.SQLiteDatabase#CONFLICT_REPLACE}
135 | * {@link android.database.sqlite.SQLiteDatabase#CONFLICT_ROLLBACK}
136 | *
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 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
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 |
--------------------------------------------------------------------------------