├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── florent37
│ │ │ └── rxandroidorm
│ │ │ └── sample
│ │ │ ├── DatabaseMigration.java
│ │ │ ├── MainActivity.java
│ │ │ ├── MyApplication.java
│ │ │ └── model
│ │ │ ├── Cat.java
│ │ │ ├── Computer.java
│ │ │ ├── Dog.java
│ │ │ ├── Software.java
│ │ │ └── User.java
│ └── res
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── github
│ └── florent37
│ └── rxandroidorm
│ └── sample
│ ├── CatEntityManagerTest.java
│ ├── CustomRobolectricTestRunner.java
│ ├── RxJavaSchedulersTestRule.java
│ ├── RxUserTest.java
│ ├── UserEntityManagerTest.java
│ └── UserQueryBuilderTest.java
├── build.gradle
├── circle.yml
├── gradle.properties
├── gradle
├── bintray-android-v1.gradle
├── bintray-java-v1.gradle
├── install-v1.gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── publish.sh
├── rxandroidorm-annotations
├── .gitignore
├── build.gradle
└── src
│ └── main
│ └── java
│ └── com
│ └── github
│ └── florent37
│ └── rxandroidorm
│ └── annotations
│ ├── DatabaseName.java
│ ├── Id.java
│ ├── Ignore.java
│ ├── Migration.java
│ └── Model.java
├── rxandroidorm-compiler
├── .gitignore
├── build.gradle
└── src
│ └── main
│ └── java
│ └── com
│ └── github
│ └── florent37
│ └── rxandroidorm
│ ├── Constants.java
│ ├── CursorHelper.java
│ ├── Dependency.java
│ ├── ProcessUtils.java
│ ├── Processor.java
│ └── generator
│ ├── CursorHelperGenerator.java
│ ├── DAOGenerator.java
│ ├── DatabaseHelperGenerator.java
│ ├── EnumColumnGenerator.java
│ ├── ModelEntityProxyGenerator.java
│ ├── ModelORMGenerator.java
│ ├── ModelORMInterfaceGenerator.java
│ ├── PrimitiveCursorHelperGenerator.java
│ ├── QueryBuilderGenerator.java
│ └── QueryLoggerGenerator.java
├── rxandroidorm
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── github
│ └── florent37
│ └── rxandroidorm
│ ├── RxAndroidOrm.java
│ └── migration
│ ├── ColumnType.java
│ ├── DatabaseHelper.java
│ ├── FieldType.java
│ ├── Migrator.java
│ └── TableCreator.java
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # Intellij
36 | *.iml
37 | .idea
38 |
39 | # Keystore files
40 | *.jks
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RxAndroidOrm
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | # Download
10 |
11 |
12 |
13 | [  ](https://bintray.com/florent37/maven/rxandroidorm-compiler/_latestVersion)
14 | ```java
15 | dependencies {
16 | compile 'com.github.florent37:rxandroidorm:1.0.1'
17 | provided 'com.github.florent37:rxandroidorm-annotations:1.0.1'
18 | annotationProcessor 'com.github.florent37:rxandroidorm-compiler:1.0.1'
19 | }
20 | ```
21 |
22 | A simple & fluent Android ORM, how can it be easier ?
23 | And it's compatible with RxJava2 !
24 |
25 | ```java
26 | Observable.fromArray(
27 | new Computer(Computer.WINDOWS, "MasterRace", Arrays.asList(new Software("Photoshop"))),
28 | new Computer(Computer.WINDOWS, "Gamerz"),
29 | new Computer(Computer.LINUX, "MasterRace", Arrays.asList(new Software("Gimp"))))
30 | .flatMap(computerDb::add)
31 | .subscribe();
32 |
33 | Observable.just(new Computer(Computer.MAC, "Mac Mini"))
34 | .flatMap(computerDb::add)
35 | .doOnNext(computer -> computer.getSoftwares().add(new Software("Photoshop")))
36 | .flatMap(computerDb::update)
37 | .subscribe();
38 |
39 | computerDb.select()
40 | .label().equalsTo("MasterRace")
41 | .or()
42 | .softwares(SoftwareDatabase.where().name().equalsTo("Photoshop"))
43 |
44 | .asObservable()
45 | .subscribe(computers -> Log.d(TAG, computers.toString()));
46 | ```
47 |
48 | # First, initialize !
49 |
50 | Don't forget to initialise RxAndroidOrm in your applicarion:
51 |
52 | ```java
53 | public class MyApplicarion extends Applicarion {
54 |
55 | @Override public void onCreate() {
56 | super.onCreate();
57 | RxAndroidOrm.onCreate(this);
58 | }
59 |
60 | }
61 | ```
62 |
63 | # Second, annotate your models
64 |
65 | Use Annotations to mark classes to be persisted:
66 |
67 | ```java
68 | @Model
69 | public class Computer {
70 |
71 | @Id long id;
72 | String name;
73 |
74 | List softwares;
75 | }
76 | ```
77 |
78 | ## Logging
79 |
80 | You can log all SQL queries from entities managers:
81 |
82 | ```java
83 | computerDb.logQueries((query, datas) -> Log.d(TAG, query) }
84 | ```
85 |
86 | # TODO
87 |
88 | - Enum support
89 |
90 | # Credits
91 |
92 | Author: Florent Champigny [http://www.florentchampigny.com/](http://www.florentchampigny.com/)
93 |
94 | Blog : [http://www.tutos-android-france.com/](http://www.www.tutos-android-france.com/)
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
104 |
105 |
106 |
108 |
109 |
110 |
112 |
113 |
114 |
115 | License
116 | --------
117 |
118 | Copyright 2017 Florent37, Inc.
119 |
120 | Licensed under the Apache License, Version 2.0 (the "License");
121 | you may not use this file except in compliance with the License.
122 | You may obtain a copy of the License at
123 |
124 | http://www.apache.org/licenses/LICENSE-2.0
125 |
126 | Unless required by applicable law or agreed to in writing, software
127 | distributed under the License is distributed on an "AS IS" BASIS,
128 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129 | See the License for the specific language governing permissions and
130 | limitations under the License.
131 |
132 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'com.neenbedankt.android-apt'
3 | apply plugin: 'me.tatarka.retrolambda'
4 |
5 | android {
6 | compileSdkVersion project.COMPILE_SDK
7 | buildToolsVersion project.BUILD_TOOL
8 |
9 | defaultConfig {
10 | minSdkVersion project.minSdkVersion
11 | targetSdkVersion project.TARGET_SDK
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 |
22 | lintOptions {
23 | abortOnError false
24 | }
25 |
26 | compileOptions {
27 | sourceCompatibility JavaVersion.VERSION_1_8
28 | targetCompatibility JavaVersion.VERSION_1_8
29 | }
30 | }
31 |
32 | dependencies {
33 | compile fileTree(dir: 'libs', include: ['*.jar'])
34 | compile 'com.android.support:appcompat-v7:25.3.1'
35 |
36 | compile 'io.reactivex.rxjava2:rxjava:2.0.6'
37 |
38 | compile 'com.github.florent37:rxandroidorm:1.0.2'
39 | provided 'com.github.florent37:rxandroidorm-annotations:1.0.2'
40 | apt 'com.github.florent37:rxandroidorm-compiler:1.0.2'
41 |
42 | //compile project(':rxandroidorm')
43 | //provided project(':rxandroidorm-annotations')
44 | //apt project(':rxandroidorm-compiler')
45 |
46 | compile 'com.facebook.stetho:stetho:1.4.2'
47 |
48 | testCompile(
49 | 'junit:junit:4.12',
50 | 'com.android.support:support-annotations:25.3.1',
51 | 'org.mockito:mockito-core:1.10.19',
52 | 'org.assertj:assertj-core:1.7.1',
53 | 'com.google.truth:truth:0.28'
54 | )
55 | testCompile('org.robolectric:robolectric:3.0') {
56 | exclude module: 'support-v4'
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/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 /Users/florentchampigny/Android/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 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/florent37/rxandroidorm/sample/DatabaseMigration.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample;
2 |
3 | import com.github.florent37.rxandroidorm.annotations.DatabaseName;
4 | import com.github.florent37.rxandroidorm.annotations.Migration;
5 | import com.github.florent37.rxandroidorm.migration.Migrator;
6 |
7 | /**
8 | * Created by florentchampigny on 28/01/2016.
9 | */
10 | @DatabaseName("mmm")
11 | public class DatabaseMigration {
12 |
13 | @Migration(2)
14 | public static void migrateTo2(Migrator migrator) {
15 | //migrator.update("User")
16 | // .removeField("age")
17 | // .renameTo("Man");
18 | }
19 |
20 | //@Migration(3)
21 | //public static void migrateTo3(Migrator migrator) {
22 | // migrator.update("Man")
23 | // .addField("birth", ColumnType.Primitive.Int);
24 | //}
25 |
26 | //@Migration(4)
27 | //public static void migrateTo4(Migrator migrator) {
28 | // migrator.update("Man")
29 | // .transform("name").renameTo("myName")
30 | // .addField("lastName", ColumnType.Primitive.String);
31 | //}
32 |
33 | //@Migration(5)
34 | //public static void migrateTo5(Migrator migrator) {
35 | // migrator.addTable(migrator.createModel("Woman")
36 | // .field("name", ColumnType.Primitive.String)
37 | // .build());
38 | //}
39 |
40 | //@Migration(6)
41 | //public static void migrateTo6(Migrator migrator) {
42 | // migrator.update("Woman")
43 | // .addField("mans", ColumnType.collectionOfModel("Man"))
44 | // .addField("age", ColumnType.Primitive.Int);
45 | //}
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/florent37/rxandroidorm/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.util.Log;
6 |
7 | import com.github.florent37.rxandroidorm.sample.model.Computer;
8 | import com.github.florent37.rxandroidorm.sample.model.ComputerDatabase;
9 | import com.github.florent37.rxandroidorm.sample.model.Software;
10 | import com.github.florent37.rxandroidorm.sample.model.SoftwareDatabase;
11 |
12 | import java.util.Arrays;
13 |
14 | import io.reactivex.Observable;
15 |
16 | public class MainActivity extends AppCompatActivity {
17 |
18 | private static final String TAG = "MainActivity";
19 | private ComputerDatabase computerDb;
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | setContentView(R.layout.activity_main);
25 |
26 | computerDb = new ComputerDatabase();
27 |
28 | queries();
29 | }
30 |
31 | protected void queries() {
32 |
33 | Observable.fromArray(
34 | new Computer(Computer.WINDOWS, "MasterRace", Arrays.asList(new Software("Photoshop"))),
35 | new Computer(Computer.WINDOWS, "Gamerz"),
36 | new Computer(Computer.LINUX, "MasterRace", Arrays.asList(new Software("Gimp"))))
37 | .flatMap(computerDb::add)
38 | .subscribe();
39 |
40 | Observable.just(new Computer(Computer.MAC, "Mac Mini"))
41 | .flatMap(computerDb::add)
42 | .doOnNext(computer -> computer.getSoftwares().add(new Software("Photoshop")))
43 | .flatMap(computerDb::update)
44 | .subscribe();
45 |
46 | computerDb.select()
47 | .label().equalsTo("MasterRace")
48 | .or()
49 | .softwares(SoftwareDatabase.where().name().equalsTo("Photoshop"))
50 |
51 | .asObservable()
52 | .subscribe(computers -> Log.d(TAG, computers.toString()));
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/florent37/rxandroidorm/sample/MyApplication.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample;
2 |
3 | import android.app.Application;
4 |
5 | import com.facebook.stetho.Stetho;
6 |
7 | import com.github.florent37.rxandroidorm.RxAndroidOrm;
8 |
9 | /**
10 | * Created by florentchampigny on 07/01/2016.
11 | */
12 | public class MyApplication extends Application {
13 |
14 | @Override public void onCreate() {
15 | super.onCreate();
16 | RxAndroidOrm.onCreate(this);
17 |
18 | Stetho.initializeWithDefaults(this);
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/florent37/rxandroidorm/sample/model/Cat.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample.model;
2 |
3 | import com.github.florent37.rxandroidorm.annotations.Id;
4 | import com.github.florent37.rxandroidorm.annotations.Ignore;
5 | import com.github.florent37.rxandroidorm.annotations.Model;
6 |
7 | import java.util.Date;
8 |
9 | @Model
10 | public class Cat {
11 |
12 | public static final int VISIBLE = 0;
13 |
14 | @Id
15 | long id;
16 |
17 | String shortName;
18 | Date date;
19 |
20 | String notIgnored;
21 | @Ignore
22 | String ignoreThis;
23 |
24 | public Cat() {
25 | }
26 |
27 | public Cat(String shortName) {
28 | this.shortName = shortName;
29 | }
30 |
31 | public Cat(long id, String shortName) {
32 | this.id = id;
33 | this.shortName = shortName;
34 | }
35 |
36 | public Cat(String shortName, Date date) {
37 | this.shortName = shortName;
38 | this.date = date;
39 | }
40 |
41 | public void setShortName(String shortName) {
42 | this.shortName = shortName;
43 | }
44 |
45 | public String getShortName() {
46 | return shortName;
47 | }
48 |
49 | public Date getDate() {
50 | return date;
51 | }
52 |
53 | public long getId() {
54 | return id;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/florent37/rxandroidorm/sample/model/Computer.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample.model;
2 |
3 | import android.support.annotation.IntDef;
4 |
5 | import com.github.florent37.rxandroidorm.annotations.Id;
6 | import com.github.florent37.rxandroidorm.annotations.Model;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * Created by florentchampigny on 08/05/2017.
12 | */
13 |
14 | @Model
15 | public class Computer {
16 |
17 | @Id
18 | long id;
19 |
20 | @OS
21 | int os;
22 |
23 | String label;
24 |
25 | List softwares;
26 |
27 | public Computer() {
28 | }
29 |
30 | public Computer(@OS int os, String label) {
31 | this.os = os;
32 | this.label = label;
33 | }
34 |
35 | public Computer(int os, String name, List softwares) {
36 | this(os, name);
37 | this.softwares = softwares;
38 | }
39 |
40 | public static final int MAC = 1;
41 | public static final int WINDOWS = 2;
42 | public static final int LINUX = 3;
43 |
44 | @IntDef({MAC, WINDOWS, LINUX})
45 | public @interface OS {}
46 |
47 | public long getId() {
48 | return id;
49 | }
50 |
51 | public void setId(long id) {
52 | this.id = id;
53 | }
54 |
55 | public List getSoftwares() {
56 | return softwares;
57 | }
58 |
59 | public void setSoftwares(List softwares) {
60 | this.softwares = softwares;
61 | }
62 |
63 | @OS
64 | public int getOs() {
65 | return os;
66 | }
67 |
68 | public void setOs(@OS int os) {
69 | this.os = os;
70 | }
71 |
72 | public String getLabel() {
73 | return label;
74 | }
75 |
76 | public void setLabel(String label) {
77 | this.label = label;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/florent37/rxandroidorm/sample/model/Dog.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample.model;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | import com.github.florent37.rxandroidorm.annotations.Model;
7 |
8 | @Model
9 | public class Dog implements Parcelable {
10 | public static final Creator CREATOR = new Creator() {
11 | @Override
12 | public Dog createFromParcel(Parcel in) {
13 | return new Dog(in);
14 | }
15 |
16 | @Override
17 | public Dog[] newArray(int size) {
18 | return new Dog[size];
19 | }
20 | };
21 |
22 | String name;
23 |
24 | public Dog(){}
25 |
26 | public Dog(String name) {
27 | this.name = name;
28 | }
29 |
30 | protected Dog(Parcel in) {
31 | name = in.readString();
32 | }
33 |
34 | public String getName() {
35 | return name;
36 | }
37 |
38 | public void setName(String name) {
39 | this.name = name;
40 | }
41 |
42 | @Override
43 | public int describeContents() {
44 | return 0;
45 | }
46 |
47 | @Override
48 | public void writeToParcel(Parcel dest, int flags) {
49 | dest.writeString(name);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/florent37/rxandroidorm/sample/model/Software.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample.model;
2 |
3 | import com.github.florent37.rxandroidorm.annotations.Id;
4 | import com.github.florent37.rxandroidorm.annotations.Model;
5 |
6 | /**
7 | * Created by florentchampigny on 08/05/2017.
8 | */
9 |
10 | @Model
11 | public class Software {
12 |
13 | @Id
14 | long id;
15 |
16 | String name;
17 |
18 | public Software() {
19 | }
20 |
21 | public Software(String name) {
22 | this.name = name;
23 | }
24 |
25 | public long getId() {
26 | return id;
27 | }
28 |
29 | public void setId(long id) {
30 | this.id = id;
31 | }
32 |
33 | public String getName() {
34 | return name;
35 | }
36 |
37 | public void setName(String name) {
38 | this.name = name;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/florent37/rxandroidorm/sample/model/User.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample.model;
2 |
3 | import com.github.florent37.rxandroidorm.annotations.Id;
4 | import com.github.florent37.rxandroidorm.annotations.Model;
5 |
6 | import java.util.List;
7 |
8 | @Model
9 | public class User {
10 |
11 | @Id
12 | long id;
13 |
14 | int age;
15 | String name;
16 | Cat cat;
17 | List dogs;
18 | boolean hacker;
19 |
20 | public User(){}
21 |
22 | public User(int age, String name, Cat cat, List dogs, boolean hacker) {
23 | this.age = age;
24 | this.name = name;
25 | this.cat = cat;
26 | this.dogs = dogs;
27 | this.hacker = hacker;
28 | }
29 |
30 | public User(int age, String name) {
31 | this.age = age;
32 | this.name = name;
33 | }
34 |
35 | @Override public String toString() {
36 | return "User{" +
37 | " name='" + name + '\'' +
38 | '}';
39 | }
40 |
41 | public void setAge(int age) {
42 | this.age = age;
43 | }
44 |
45 | public void setName(String name) {
46 | this.name = name;
47 | }
48 |
49 | public void setCat(Cat cat) {
50 | this.cat = cat;
51 | }
52 |
53 | public void setDogs(List dogs) {
54 | this.dogs = dogs;
55 | }
56 |
57 | public void setHacker(boolean hacker) {
58 | this.hacker = hacker;
59 | }
60 |
61 | public int getAge() {
62 | return age;
63 | }
64 |
65 | public String getName() {
66 | return name;
67 | }
68 |
69 | public Cat getCat() {
70 | return cat;
71 | }
72 |
73 | public List getDogs() {
74 | return dogs;
75 | }
76 |
77 | public boolean isHacker() {
78 | return hacker;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/RxAndroidOrm/169378bb4617fdffcbd383b07a196798fbe2f7fc/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/RxAndroidOrm/169378bb4617fdffcbd383b07a196798fbe2f7fc/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/RxAndroidOrm/169378bb4617fdffcbd383b07a196798fbe2f7fc/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/RxAndroidOrm/169378bb4617fdffcbd383b07a196798fbe2f7fc/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/RxAndroidOrm/169378bb4617fdffcbd383b07a196798fbe2f7fc/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | DAO
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/github/florent37/rxandroidorm/sample/CatEntityManagerTest.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample;
2 |
3 | import com.github.florent37.rxandroidorm.sample.model.Cat;
4 | import com.github.florent37.rxandroidorm.sample.model.CatDatabase;
5 |
6 | import org.junit.Before;
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import java.util.Arrays;
11 | import java.util.Date;
12 | import java.util.List;
13 |
14 | import static com.google.common.truth.Truth.assertThat;
15 | import static org.mockito.Mockito.spy;
16 |
17 | /**
18 | * Created by florentchampigny on 05/02/2016.
19 | */
20 | @RunWith(CustomRobolectricTestRunner.class)
21 | public class CatEntityManagerTest {
22 |
23 | CatDatabase carEntityManager;
24 |
25 | @Before
26 | public void setUp() throws Exception {
27 | carEntityManager = spy(new CatDatabase());
28 | carEntityManager.deleteAll();
29 | }
30 |
31 | @Test
32 | public void shouldAddCatWithDate() {
33 | //given
34 | Date date = new Date(System.currentTimeMillis() - 60 * 1000);
35 | Cat cat = new Cat("Java", date);
36 |
37 | //when
38 | carEntityManager.add(cat).subscribe();
39 |
40 | //then
41 | carEntityManager.count().test().assertValue(1);
42 | assertThat(cat.getId()).isNotEqualTo(0);
43 | }
44 |
45 | @Test
46 | public void shouldAddCats_shouldGenerateIds() {
47 | //given
48 | final Cat java = new Cat("Java");
49 | final Cat bobo = new Cat("Bobo");
50 | final Cat sisi = new Cat("Sisi");
51 | final List cats = Arrays.asList(java, bobo, sisi);
52 |
53 | //when
54 | carEntityManager.add(cats).subscribe();
55 |
56 | //then
57 | carEntityManager.count().test().assertValue(3);
58 | assertThat(java.getId()).isEqualTo(1);
59 | assertThat(bobo.getId()).isEqualTo(2);
60 | assertThat(sisi.getId()).isEqualTo(3);
61 | }
62 |
63 | @Test
64 | public void shouldUpdateCats_becauseAlreadyExists() {
65 | //given
66 | {
67 | final Cat java = new Cat(1, "Java");
68 | final Cat bobo = new Cat(2, "Bobo");
69 | final Cat sisi = new Cat(3, "Sisi");
70 | final List cats = Arrays.asList(java, bobo, sisi);
71 | carEntityManager.add(cats).subscribe();
72 | }
73 |
74 | final Cat java = new Cat(1, "Java_e");
75 |
76 | //when
77 | carEntityManager.add(java).subscribe();
78 |
79 | //then
80 | carEntityManager.count().test().assertValue(3);
81 | final Cat cat = carEntityManager.select().id()
82 | .equalsTo(1l).first()
83 | .blockingFirst();
84 |
85 | assertThat(cat.getId()).isEqualTo(1);
86 | assertThat(cat.getShortName()).isEqualTo("Java_e");
87 | }
88 |
89 | @Test
90 | public void shouldGetCatWithAllFields() {
91 | //given
92 | Date date = new Date(System.currentTimeMillis() - 60 * 1000);
93 | Cat cat = new Cat("Java", date);
94 |
95 | //when
96 | carEntityManager.add(cat).subscribe();
97 | Cat catFromBase = carEntityManager.select()
98 | .first()
99 | .blockingFirst();
100 |
101 | //then
102 | assertThat(catFromBase).isNotNull();
103 | assertThat(catFromBase.getShortName()).isEqualTo("Java");
104 | assertThat(catFromBase.getDate().toString()).isEqualTo(date.toString());
105 | }
106 |
107 | @Test
108 | public void shouldGetCatWithCustomDate_equals() {
109 | //given
110 | Date date = new Date(System.currentTimeMillis() - 60 * 1000);
111 |
112 | Cat cat1 = new Cat("Java", date);
113 | Cat cat2 = new Cat("Blob", new Date(System.currentTimeMillis() + 60 * 1000));
114 |
115 | //when
116 | carEntityManager.add(cat1).subscribe();
117 | carEntityManager.add(cat2).subscribe();
118 |
119 | List cats = carEntityManager.select().date().equalsTo(date).asObservable().blockingFirst();
120 |
121 | //then
122 | assertThat(cats).hasSize(1);
123 | assertThat(cats.get(0).getShortName()).isEqualTo("Java");
124 | }
125 |
126 | @Test
127 | public void shouldGetCatWithCustomDate_notEquals() {
128 | //given
129 | Date date = new Date(System.currentTimeMillis() - 60 * 1000);
130 |
131 | Cat cat1 = new Cat("Java", date);
132 | Cat cat2 = new Cat("Blob", new Date(System.currentTimeMillis() + 60 * 1000));
133 |
134 | //when
135 | carEntityManager.add(cat1).subscribe();
136 | carEntityManager.add(cat2).subscribe();
137 |
138 | List cats = carEntityManager.select().date().notEqualsTo(date).asObservable().blockingFirst();
139 |
140 | //then
141 | assertThat(cats).hasSize(1);
142 | assertThat(cats.get(0).getShortName()).isEqualTo("Blob");
143 | }
144 |
145 | @Test
146 | public void shouldGetCatWithCustomDate_before() {
147 | //given
148 | Date now = new Date(System.currentTimeMillis());
149 |
150 | Cat cat1 = new Cat("Java", new Date(now.getTime() - 60 * 1000 * 1000));
151 | Cat cat2 = new Cat("Blob", new Date(now.getTime() + 60 * 1000 * 1000));
152 |
153 | //when
154 | carEntityManager.add(cat1).subscribe();
155 | carEntityManager.add(cat2).subscribe();
156 |
157 | List cats = carEntityManager.select()
158 | .date()
159 | .before(now)
160 | .asObservable()
161 | .blockingFirst();
162 |
163 | //then
164 | assertThat(cats).hasSize(1);
165 | assertThat(cats.get(0).getShortName()).isEqualTo("Java");
166 | }
167 |
168 | @Test
169 | public void shouldGetCatWithCustomDate_after() {
170 | //given
171 | Date now = new Date(System.currentTimeMillis());
172 |
173 | Cat cat1 = new Cat("Java", new Date(now.getTime() - 60 * 1000 * 1000));
174 | Cat cat2 = new Cat("Blob", new Date(now.getTime() + 60 * 1000 * 1000));
175 |
176 | //when
177 | carEntityManager.add(cat1).subscribe();
178 | carEntityManager.add(cat2).subscribe();
179 |
180 | List cats = carEntityManager.select().date().after(now).asObservable().blockingFirst();
181 |
182 | //then
183 | assertThat(cats).hasSize(1);
184 | assertThat(cats.get(0).getShortName()).isEqualTo("Blob");
185 | }
186 |
187 | @Test
188 | public void shouldGetCatWithCustomDate_between() {
189 | //given
190 | Date now = new Date(System.currentTimeMillis());
191 |
192 | Cat cat1 = new Cat("Java", new Date(now.getTime()));
193 | Cat cat2 = new Cat("Blob", new Date(now.getTime()));
194 | Cat cat3 = new Cat("Baba", new Date(now.getTime() - 120 * 1000 * 1000));
195 | Cat cat4 = new Cat("Cece", new Date(now.getTime() + 120 * 1000 * 1000));
196 |
197 | //when
198 | carEntityManager.add(cat1).subscribe();
199 | carEntityManager.add(cat2).subscribe();
200 | carEntityManager.add(cat3).subscribe();
201 | carEntityManager.add(cat4).subscribe();
202 |
203 | List cats = carEntityManager.select().date().between(new Date(now.getTime() - 60 * 1000 * 1000), new Date(now.getTime() + 60 * 1000 * 1000)).asObservable().blockingFirst();
204 |
205 | //then
206 | assertThat(cats).hasSize(2);
207 | assertThat(cats.get(0).getShortName()).isEqualTo("Java");
208 | assertThat(cats.get(1).getShortName()).isEqualTo("Blob");
209 | }
210 |
211 | @Test
212 | public void testUpdateCat_onlyFields() throws Exception {
213 | //given
214 | Cat cat = new Cat("toto");
215 | carEntityManager.add(cat).subscribe();
216 | carEntityManager.count().test().assertValue(1);
217 |
218 | //when
219 | cat.setShortName("mimi");
220 | carEntityManager.update(cat).subscribe();
221 |
222 | //then
223 | carEntityManager.count().test().assertValue(1);
224 | Cat catFromBase = carEntityManager.select().first().blockingFirst();
225 | assertThat(catFromBase.getShortName()).isEqualTo("mimi");
226 | }
227 |
228 | @Test
229 | public void testDeleteCat() throws Exception {
230 | //given
231 | Cat cat1 = new Cat("toto");
232 | carEntityManager.add(cat1).subscribe();
233 | carEntityManager.count().test().assertValue(1);
234 | assertThat(cat1.getId()).isAtLeast(1l);
235 |
236 | //when
237 | carEntityManager.delete(cat1).subscribe();
238 |
239 | //then
240 | carEntityManager.count().test().assertValue(0);
241 | }
242 |
243 | @Test
244 | public void testDeleteCats() throws Exception {
245 | //given
246 | Cat cat1 = new Cat("toto");
247 | Cat cat2 = new Cat("tata");
248 | carEntityManager.add(Arrays.asList(cat1, cat2)).subscribe();
249 | carEntityManager.count().test().assertValue(2);
250 | assertThat(cat1.getId()).isAtLeast(1l);
251 | assertThat(cat2.getId()).isAtLeast(1l);
252 |
253 | //when
254 | carEntityManager.delete(Arrays.asList(cat1, cat2)).subscribe();
255 |
256 | //then
257 | carEntityManager.count().test().assertValue(0);
258 | }
259 |
260 | }
261 |
--------------------------------------------------------------------------------
/app/src/test/java/com/github/florent37/rxandroidorm/sample/CustomRobolectricTestRunner.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample;
2 |
3 | import android.os.Build;
4 |
5 | import org.junit.runners.model.InitializationError;
6 | import org.robolectric.RobolectricTestRunner;
7 | import org.robolectric.annotation.Config;
8 | import org.robolectric.internal.bytecode.InstrumentationConfiguration;
9 | import org.robolectric.internal.bytecode.ShadowMap;
10 | import org.robolectric.manifest.AndroidManifest;
11 |
12 | import java.io.File;
13 | import java.util.Properties;
14 |
15 | public class CustomRobolectricTestRunner extends RobolectricTestRunner {
16 |
17 | public static final String PATH_ASSET = "../../../../assets/" + BuildConfig.FLAVOR + "/" + BuildConfig.BUILD_TYPE;
18 | public static final String PATH_RESOURCE = "../../../../res/merged/" + BuildConfig.FLAVOR + "/" + BuildConfig.BUILD_TYPE;
19 | public static final String PATH_MANIFEST = "build/intermediates/manifests/full/" + BuildConfig.FLAVOR + "/" + BuildConfig.BUILD_TYPE + "/AndroidManifest.xml";
20 |
21 | public static final String CONFIG_MANIFEST = "manifest";
22 | public static final String CONFIG_ASSET_DIR = "assetDir";
23 | public static final String CONFIG_RESOURCE_DIR = "resourceDir";
24 | public static final String CONFIG_PACKAGE_NAME = "packageName";
25 | public static final String CONFIG_SDK = "sdk";
26 |
27 | public static final String PACKAGE_NAME = "net.ilius.android.resources";
28 |
29 | public static final String PATH_PREFIX = "app/";
30 |
31 | public CustomRobolectricTestRunner(Class> testClass) throws InitializationError {
32 | super(testClass);
33 | }
34 |
35 | @Override
36 | protected AndroidManifest getAppManifest(Config config) {
37 | String path = PATH_MANIFEST;
38 |
39 | // android studio has a different execution root for tests than pure gradle
40 | // so we avoid here manual effort to get them running inside android studio
41 | if (!new File(path).exists()) {
42 | path = PATH_PREFIX + path;
43 | }
44 |
45 | config = overwriteConfig(config, CONFIG_MANIFEST, path);
46 | config = overwriteConfig(config, CONFIG_ASSET_DIR, PATH_ASSET);
47 | config = overwriteConfig(config, CONFIG_RESOURCE_DIR, PATH_RESOURCE);
48 | config = overwriteConfig(config, CONFIG_PACKAGE_NAME, PACKAGE_NAME);
49 |
50 | return super.getAppManifest(config);
51 | }
52 |
53 | @Override
54 | protected int pickSdkVersion(Config config, AndroidManifest manifest) {
55 | config = overwriteConfig(config, CONFIG_SDK, String.valueOf(Build.VERSION_CODES.JELLY_BEAN));
56 | return super.pickSdkVersion(config, manifest);
57 | }
58 |
59 | @Override
60 | public InstrumentationConfiguration createClassLoaderConfig() {
61 | InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder();
62 | return builder.build();
63 | }
64 |
65 | protected Config.Implementation overwriteConfig(Config config, String key, String value) {
66 | Properties properties = new Properties();
67 | properties.setProperty(key, value);
68 | return new Config.Implementation(config, Config.Implementation.fromProperties(properties));
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/test/java/com/github/florent37/rxandroidorm/sample/RxJavaSchedulersTestRule.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample;
2 |
3 | import org.junit.rules.TestRule;
4 | import org.junit.runner.Description;
5 | import org.junit.runners.model.Statement;
6 |
7 | import java.util.concurrent.Callable;
8 |
9 | import io.reactivex.Scheduler;
10 | import io.reactivex.annotations.NonNull;
11 | import io.reactivex.functions.Function;
12 | import io.reactivex.plugins.RxJavaPlugins;
13 | import io.reactivex.schedulers.Schedulers;
14 |
15 | /**
16 | * Created by florentchampigny on 05/05/2017.
17 | */
18 |
19 | public class RxJavaSchedulersTestRule implements TestRule {
20 | @Override
21 | public Statement apply(final Statement base, Description description) {
22 | return new Statement() {
23 | @Override
24 | public void evaluate() throws Throwable {
25 | resetPlugins();
26 |
27 | RxJavaPlugins.setIoSchedulerHandler(new Function() {
28 | @Override
29 | public Scheduler apply(@NonNull Scheduler scheduler) throws Exception {
30 | return Schedulers.trampoline();
31 | }
32 | });
33 |
34 | base.evaluate();
35 |
36 | resetPlugins();
37 | }
38 | };
39 | }
40 |
41 | private void resetPlugins() {
42 | RxJavaPlugins.reset();
43 | }
44 | }
--------------------------------------------------------------------------------
/app/src/test/java/com/github/florent37/rxandroidorm/sample/RxUserTest.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample;
2 |
3 | import android.util.Log;
4 |
5 | import com.github.florent37.rxandroidorm.sample.model.CatDatabase;
6 | import com.github.florent37.rxandroidorm.sample.model.Computer;
7 | import com.github.florent37.rxandroidorm.sample.model.ComputerDatabase;
8 | import com.github.florent37.rxandroidorm.sample.model.DogDatabase;
9 | import com.github.florent37.rxandroidorm.sample.model.Software;
10 | import com.github.florent37.rxandroidorm.sample.model.SoftwareDatabase;
11 | import com.github.florent37.rxandroidorm.sample.model.User;
12 | import com.github.florent37.rxandroidorm.sample.model.UserColumns;
13 | import com.github.florent37.rxandroidorm.sample.model.UserDatabase;
14 |
15 | import org.junit.Before;
16 | import org.junit.Test;
17 | import org.junit.runner.RunWith;
18 |
19 | import java.util.Arrays;
20 | import java.util.List;
21 |
22 | import io.reactivex.Observable;
23 | import io.reactivex.annotations.NonNull;
24 | import io.reactivex.functions.Predicate;
25 |
26 | import static com.google.common.truth.Truth.assertThat;
27 | import static org.mockito.Mockito.spy;
28 |
29 | /**
30 | * Created by florentchampigny on 05/02/2016.
31 | */
32 | @RunWith(CustomRobolectricTestRunner.class)
33 | public class RxUserTest {
34 |
35 | UserDatabase userEntityManager;
36 | ComputerDatabase computerDb;
37 |
38 | @Before
39 | public void setUp() throws Exception {
40 | userEntityManager = spy(new UserDatabase());
41 | userEntityManager.deleteAll().subscribe();
42 |
43 | computerDb = spy(new ComputerDatabase());
44 |
45 | Observable.zip(
46 | userEntityManager.deleteAll(),
47 | computerDb.deleteAll(),
48 | (aBoolean, aBoolean2) -> aBoolean)
49 | .subscribe();
50 | }
51 |
52 | @Test
53 | public void testAdd_one() {
54 | userEntityManager.add(new User(21, "florent"))
55 | .flatMap(user -> userEntityManager.count())
56 | .test()
57 | .assertValue(1);
58 | }
59 |
60 | @Test
61 | public void testAdd_two() {
62 | userEntityManager.add(new User(1, "florent"))
63 | .flatMap(user -> userEntityManager.add(new User(2, "kevin")))
64 | .flatMap(user1 -> userEntityManager.count())
65 | .test()
66 | .assertValue(2);
67 | }
68 |
69 | @Test
70 | public void testAdd_list() {
71 | userEntityManager.add(Arrays.asList(new User(21, "florent"), new User(22, "kevin")))
72 | .flatMap(user -> userEntityManager.count())
73 | .test()
74 | .assertValue(2);
75 | }
76 |
77 | @Test
78 | public void testAdd_then_select() {
79 | userEntityManager.add(Arrays.asList(new User(21, "florent"), new User(22, "kevin")))
80 | .flatMap(user -> userEntityManager.select().age().equalsTo(21).first())
81 | .map(User::getName)
82 | .test()
83 | .assertValue("florent");
84 | }
85 |
86 | @Test
87 | public void testComputer() {
88 | Observable.fromArray(
89 | new Computer(Computer.WINDOWS, "MasterRace", Arrays.asList(new Software("Photoshop"))),
90 | new Computer(Computer.WINDOWS, "Gamerz"),
91 | new Computer(Computer.LINUX, "MasterRace", Arrays.asList(new Software("Gimp"))))
92 | .flatMap(computerDb::add)
93 | .subscribe();
94 |
95 | Observable.just(new Computer(Computer.MAC, "Mac Mini"))
96 | .flatMap(computerDb::add)
97 | .doOnNext(computer -> computer.setSoftwares(Arrays.asList(new Software("Photoshop"))))
98 | .flatMap(computerDb::update)
99 | .subscribe();
100 |
101 | computerDb.select()
102 | .label().equalsTo("MasterRace")
103 | .or()
104 | .softwares(SoftwareDatabase.where().name().equalsTo("Photoshop"))
105 |
106 | .asObservable()
107 | .test()
108 |
109 | .assertValue(new Predicate>() {
110 | @Override
111 | public boolean test(@NonNull List computers) throws Exception {
112 | return computers.size() == 3;
113 | }
114 | });
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/test/java/com/github/florent37/rxandroidorm/sample/UserEntityManagerTest.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample;
2 |
3 | import com.github.florent37.rxandroidorm.sample.model.Cat;
4 | import com.github.florent37.rxandroidorm.sample.model.CatDatabase;
5 | import com.github.florent37.rxandroidorm.sample.model.Dog;
6 | import com.github.florent37.rxandroidorm.sample.model.DogDatabase;
7 | import com.github.florent37.rxandroidorm.sample.model.User;
8 | import com.github.florent37.rxandroidorm.sample.model.UserDatabase;
9 |
10 | import org.junit.Before;
11 | import org.junit.Rule;
12 | import org.junit.Test;
13 | import org.junit.runner.RunWith;
14 |
15 | import java.util.Arrays;
16 | import java.util.List;
17 |
18 | import io.reactivex.ObservableSource;
19 | import io.reactivex.Scheduler;
20 | import io.reactivex.annotations.NonNull;
21 | import io.reactivex.functions.Function;
22 | import io.reactivex.schedulers.Schedulers;
23 |
24 | import static com.google.common.truth.Truth.assertThat;
25 | import static org.mockito.Mockito.spy;
26 |
27 | /**
28 | * Created by florentchampigny on 05/02/2016.
29 | */
30 | @RunWith(CustomRobolectricTestRunner.class)
31 | public class UserEntityManagerTest {
32 |
33 | @Rule
34 | public RxJavaSchedulersTestRule rxJavaSchedulersTestRule = new RxJavaSchedulersTestRule();
35 |
36 | UserDatabase userEntityManager;
37 | CatDatabase CarEntityManager;
38 | DogDatabase dogEntityManager;
39 |
40 | private Scheduler scheduler = Schedulers.trampoline();
41 |
42 | @Before
43 | public void setUp() throws Exception {
44 | userEntityManager = spy(new UserDatabase());
45 | userEntityManager.deleteAll().subscribeOn(scheduler).subscribe();
46 |
47 | CarEntityManager = spy(new CatDatabase());
48 | CarEntityManager.deleteAll().subscribeOn(scheduler).subscribe();
49 |
50 | dogEntityManager = spy(new DogDatabase());
51 | dogEntityManager.deleteAll().subscribeOn(scheduler).subscribe();
52 | }
53 |
54 | @Test
55 | public void shouldAddUser() {
56 | //given
57 | final User user = new User(21, "florent");
58 |
59 | //when
60 | userEntityManager.add(user).subscribe();
61 |
62 | //then
63 | userEntityManager.count().test().assertValue(1);
64 | }
65 |
66 | @Test
67 | public void shouldAddUsers_flatmap() {
68 | //given
69 | final User user = new User(21, "florent");
70 | final User user2 = new User(22, "kevin");
71 |
72 | //when
73 | userEntityManager.add(user)
74 | .flatMap(new Function>() {
75 | @Override
76 | public ObservableSource apply(@NonNull User user) throws Exception {
77 | return userEntityManager.add(user2);
78 | }
79 | })
80 | .subscribe();
81 |
82 | //then
83 | userEntityManager.count().test().assertValue(2);
84 | }
85 |
86 | @Test
87 | public void shouldAddUsers() {
88 | //given
89 | final List users = Arrays.asList(
90 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
91 | new User(30, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
92 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
93 | );
94 |
95 | //when
96 | userEntityManager.add(users).subscribeOn(scheduler).subscribe();
97 |
98 | //then
99 | userEntityManager.count().test().assertValue(3);
100 | CarEntityManager.count().test().assertValue(3);
101 | dogEntityManager.count().test().assertValue(4);
102 |
103 | }
104 |
105 | @Test
106 | public void shouldAddUsers_withCatDogs() {
107 | //given
108 | User user = new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true);
109 |
110 | //when
111 | userEntityManager.add(user)
112 | .subscribeOn(scheduler)
113 | .subscribe();
114 |
115 | User userFromBase = userEntityManager.select().first().blockingFirst();
116 |
117 | //then
118 | assertThat(userFromBase).isNotNull();
119 | assertThat(userFromBase.getAge()).isEqualTo(21);
120 | assertThat(userFromBase.getName()).isEqualTo("florent");
121 | assertThat(userFromBase.isHacker()).isTrue();
122 | assertThat(userFromBase.getCat()).isNotNull();
123 | assertThat(userFromBase.getCat().getShortName()).isEqualTo("Java");
124 | assertThat(userFromBase.getDogs()).hasSize(1);
125 | assertThat(userFromBase.getDogs().get(0).getName()).isEqualTo("Loulou");
126 |
127 | }
128 |
129 | @Test
130 | public void testUpdateUser_onlyFields() throws Exception {
131 | //given
132 | userEntityManager.add(new User(30, "blob", null, null, true)).subscribeOn(scheduler).subscribe();
133 |
134 | //when
135 | User userFromBase = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
136 | userFromBase.setAge(10);
137 | userEntityManager.update(userFromBase).subscribe();
138 |
139 | //then
140 | userEntityManager.count().test().assertValue(1);
141 | User userFromBase2 = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
142 | assertThat(userFromBase2.getAge()).isEqualTo(10);
143 | }
144 |
145 | @Test
146 | public void testUpdateUser_oneToOne_nullToValue() throws Exception {
147 | //given
148 | userEntityManager.add(new User(30, "blob", null, null, true)).subscribeOn(scheduler).subscribe();
149 |
150 | //when
151 | User userFromBase = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
152 | userFromBase.setCat(new Cat("java"));
153 | userEntityManager.update(userFromBase).subscribe();
154 |
155 | //then
156 | userEntityManager.count().test().assertValue(1);
157 | CarEntityManager.count().test().assertValue(1);
158 | User userFromBase2 = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
159 | assertThat(userFromBase2.getCat()).isNotNull();
160 | assertThat(userFromBase2.getCat().getShortName()).isEqualTo("java");
161 | }
162 |
163 | @Test
164 | public void testUpdateUser_oneToOne_valueToNull() throws Exception {
165 | //given
166 | userEntityManager.add(new User(30, "blob", new Cat("java"), null, true)).subscribeOn(scheduler).subscribe();
167 |
168 | //when
169 | User userFromBase = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
170 | userFromBase.setCat(null);
171 | userEntityManager.update(userFromBase).subscribe();
172 |
173 | //then
174 | userEntityManager.count().test().assertValue(1);
175 | CarEntityManager.count().test().assertValue(1);
176 |
177 | User userFromBase2 = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
178 | assertThat(userFromBase2.getCat()).isNull();
179 | }
180 |
181 | @Test
182 | public void testUpdateUser_oneToOne_updateValue() throws Exception {
183 | //given
184 | userEntityManager.add(new User(30, "blob", new Cat("java"), null, true)).subscribeOn(scheduler).subscribe();
185 |
186 | //when
187 | User userFromBase = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
188 | userFromBase.getCat().setShortName("lili");
189 | userEntityManager.update(userFromBase).subscribe();
190 |
191 | //then
192 | userEntityManager.count().test().assertValue(1);
193 | CarEntityManager.count().test().assertValue(1);
194 | User userFromBase2 = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
195 | assertThat(userFromBase2.getCat()).isNotNull();
196 | assertThat(userFromBase2.getCat().getShortName()).isEqualTo("lili");
197 | }
198 |
199 | @Test
200 | public void testUpdateUser_oneToMany_nullToValue() throws Exception {
201 | //given
202 | userEntityManager.add(new User(30, "blob", null, null, true))
203 | .subscribeOn(scheduler)
204 | .subscribe();
205 |
206 | //when
207 | User userFromBase = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
208 | userFromBase.setDogs(Arrays.asList(new Dog("a"), new Dog("b")));
209 | userEntityManager.update(userFromBase).subscribe();
210 |
211 | //then
212 | userEntityManager.count().test().assertValue(1);
213 | dogEntityManager.count().test().assertValue(2);
214 | User userFromBase2 = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
215 | assertThat(userFromBase2.getDogs()).hasSize(2);
216 | assertThat(userFromBase2.getDogs().get(0).getName()).isEqualTo("a");
217 | assertThat(userFromBase2.getDogs().get(1).getName()).isEqualTo("b");
218 | }
219 |
220 | @Test
221 | public void testUpdateUser_oneToMany_valueToNull() throws Exception {
222 | //given
223 | userEntityManager.add(new User(30, "blob", null, Arrays.asList(new Dog("a"), new Dog("b")), true))
224 | .subscribeOn(scheduler)
225 | .subscribe();
226 |
227 | //when
228 | User userFromBase = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
229 | assertThat(userFromBase.getDogs()).hasSize(2);
230 | userFromBase.setDogs(null);
231 | userEntityManager.update(userFromBase).subscribe();
232 |
233 | //then
234 | userEntityManager.count().test().assertValue(1);
235 | dogEntityManager.count().test().assertValue(2); //TODO
236 | User userFromBase2 = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
237 | assertThat(userFromBase2.getDogs()).isNull();
238 | }
239 |
240 | @Test
241 | public void testUpdateUser_oneToMany_valueAdded() throws Exception {
242 | //given
243 | userEntityManager.add(new User(30, "blob", null, Arrays.asList(new Dog("a"), new Dog("b")), true))
244 | .subscribeOn(scheduler)
245 | .subscribe();
246 |
247 | //when
248 | User userFromBase = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
249 | assertThat(userFromBase.getDogs()).hasSize(2);
250 | userFromBase.getDogs().add(new Dog("c"));
251 | userEntityManager.update(userFromBase).subscribe();
252 |
253 | //then
254 | userEntityManager.count().test().assertValue(1);
255 | //TODO assertThat(dogEntityManager.count()).isEqualTo(2);
256 | User userFromBase2 = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
257 | assertThat(userFromBase2.getDogs()).hasSize(3);
258 | }
259 |
260 | @Test
261 | public void testUpdateUser_oneToMany_valueRemoved() throws Exception {
262 | //given
263 | userEntityManager.add(new User(30, "blob", null, Arrays.asList(new Dog("a"), new Dog("b")), true))
264 | .subscribeOn(scheduler)
265 | .subscribe();
266 |
267 | //when
268 | User userFromBase = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
269 | assertThat(userFromBase.getDogs()).hasSize(2);
270 | userFromBase.getDogs().remove(0);
271 | userEntityManager.update(userFromBase).subscribe();
272 |
273 | //then
274 | userEntityManager.count().test().assertValue(1);
275 | dogEntityManager.count().test().assertValue(2); //TODO
276 | User userFromBase2 = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
277 | assertThat(userFromBase2.getDogs()).hasSize(1);
278 | }
279 |
280 | @Test
281 | public void testUpdateUser_oneToMany_valueUpdated() throws Exception {
282 | //given
283 | userEntityManager.add(new User(30, "blob", null, Arrays.asList(new Dog("a"), new Dog("b")), true))
284 | .subscribeOn(scheduler)
285 | .subscribe();
286 |
287 | //when
288 | User userFromBase = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
289 | assertThat(userFromBase.getDogs()).hasSize(2);
290 | userFromBase.getDogs().get(0).setName("ddd");
291 | userEntityManager.update(userFromBase).subscribe();
292 |
293 | //then
294 | userEntityManager.count().test().assertValue(1);
295 | dogEntityManager.count().test().assertValue(2);
296 | User userFromBase2 = userEntityManager.select().name().equalsTo("blob").first().blockingFirst();
297 | assertThat(userFromBase2.getDogs()).hasSize(2);
298 | assertThat(userFromBase2.getDogs().get(0).getName()).isEqualTo("ddd");
299 | assertThat(userFromBase2.getDogs().get(1).getName()).isEqualTo("b");
300 | }
301 | }
302 |
--------------------------------------------------------------------------------
/app/src/test/java/com/github/florent37/rxandroidorm/sample/UserQueryBuilderTest.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.sample;
2 |
3 | import com.github.florent37.rxandroidorm.sample.model.Cat;
4 | import com.github.florent37.rxandroidorm.sample.model.CatDatabase;
5 | import com.github.florent37.rxandroidorm.sample.model.Dog;
6 | import com.github.florent37.rxandroidorm.sample.model.DogDatabase;
7 | import com.github.florent37.rxandroidorm.sample.model.User;
8 | import com.github.florent37.rxandroidorm.sample.model.UserColumns;
9 | import com.github.florent37.rxandroidorm.sample.model.UserDatabase;
10 |
11 | import org.junit.Before;
12 | import org.junit.Test;
13 | import org.junit.runner.RunWith;
14 |
15 | import java.util.Arrays;
16 | import java.util.List;
17 | import java.util.concurrent.atomic.AtomicInteger;
18 |
19 | import io.reactivex.functions.Consumer;
20 |
21 | import static com.google.common.truth.Truth.assertThat;
22 | import static org.mockito.Mockito.spy;
23 |
24 | /**
25 | * Created by florentchampigny on 05/02/2016.
26 | */
27 | @RunWith(CustomRobolectricTestRunner.class)
28 | public class UserQueryBuilderTest {
29 |
30 | UserDatabase userEntityManager;
31 | CatDatabase catEntityManager;
32 | DogDatabase dogEntityManager;
33 |
34 | @Before
35 | public void setUp() throws Exception {
36 | userEntityManager = spy(new UserDatabase());
37 | userEntityManager.deleteAll().subscribe();
38 |
39 | catEntityManager = spy(new CatDatabase());
40 | catEntityManager.deleteAll().subscribe();
41 |
42 | dogEntityManager = spy(new DogDatabase());
43 | dogEntityManager.deleteAll().subscribe();
44 | }
45 |
46 | @Test
47 | public void testSelectUserFromAge() {
48 | //given
49 | List users = Arrays.asList(
50 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
51 | new User(30, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
52 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
53 | );
54 |
55 | //when
56 | userEntityManager.add(users).subscribe();
57 |
58 | User userFromBase = userEntityManager.select().age().equalsTo(21).first().blockingFirst();
59 |
60 | //then
61 | assertThat(userFromBase).isNotNull();
62 | assertThat(userFromBase.getName()).isEqualTo("florent");
63 | }
64 |
65 | @Test
66 | public void testSelectUsersFromAge_equals() {
67 | //given
68 | List users = Arrays.asList(
69 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
70 | new User(21, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
71 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
72 | );
73 |
74 | //when
75 | userEntityManager.add(users).subscribe();
76 |
77 | List usersFromBase = userEntityManager.select().age().equalsTo(21).asObservable().blockingFirst();
78 |
79 | //then
80 | assertThat(usersFromBase).isNotNull();
81 | assertThat(usersFromBase).hasSize(2);
82 | }
83 |
84 | @Test
85 | public void testSelectUsersFromAge_notEquals() {
86 | //given
87 | List users = Arrays.asList(
88 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
89 | new User(21, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
90 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
91 | );
92 |
93 | //when
94 | userEntityManager.add(users).subscribe();
95 |
96 | List usersFromBase = userEntityManager.select().age().notEqualsTo(21).asObservable().blockingFirst();
97 |
98 | //then
99 | assertThat(usersFromBase).isNotNull();
100 | assertThat(usersFromBase).hasSize(1);
101 | assertThat(usersFromBase.get(0).getName()).isEqualTo("alex");
102 | }
103 |
104 | @Test
105 | public void testSelectUsersFromAge_greather() {
106 | //given
107 | List users = Arrays.asList(
108 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
109 | new User(21, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
110 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
111 | );
112 |
113 | //when
114 | userEntityManager.add(users).subscribe();
115 |
116 | List usersFromBase = userEntityManager.select().age().greatherThan(10).asObservable().blockingFirst();
117 |
118 | //then
119 | assertThat(usersFromBase).isNotNull();
120 | assertThat(usersFromBase).hasSize(2);
121 | }
122 |
123 | @Test
124 | public void testSelectUsersFromAge_less() {
125 | //given
126 | List users = Arrays.asList(
127 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
128 | new User(21, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
129 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
130 | );
131 |
132 | //when
133 | userEntityManager.add(users).subscribe();
134 |
135 | List usersFromBase = userEntityManager.select().age().lessThan(20).asObservable().blockingFirst();
136 |
137 | //then
138 | assertThat(usersFromBase).isNotNull();
139 | assertThat(usersFromBase).hasSize(1);
140 | }
141 |
142 | @Test
143 | public void testSelectUsersFromAge_between() {
144 | //given
145 | List users = Arrays.asList(
146 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
147 | new User(21, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
148 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
149 | );
150 |
151 | //when
152 | userEntityManager.add(users).subscribe();
153 |
154 | List usersFromBase = userEntityManager.select().age().between(9, 20).asObservable().blockingFirst();
155 |
156 | //then
157 | assertThat(usersFromBase).isNotNull();
158 | assertThat(usersFromBase).hasSize(1);
159 | }
160 |
161 | @Test
162 | public void testSelectUsersFromAge_in() {
163 | //given
164 | List users = Arrays.asList(
165 | new User(1, "a"),
166 | new User(3, "b"),
167 | new User(5, "c"),
168 | new User(1, "d"),
169 | new User(10, "e"),
170 | new User(11, "f")
171 | );
172 |
173 | //when
174 | userEntityManager.add(users).subscribe();
175 |
176 | List usersFromBase = userEntityManager.select().age().in(1, 10).asObservable().blockingFirst();
177 |
178 | //then
179 | assertThat(usersFromBase).isNotNull();
180 | assertThat(usersFromBase).hasSize(3);
181 | }
182 |
183 | @Test
184 | public void testSelectUsersFromName_in() {
185 | //given
186 | List users = Arrays.asList(
187 | new User(1, "a"),
188 | new User(3, "b"),
189 | new User(5, "a"),
190 | new User(1, "e"),
191 | new User(10, "e"),
192 | new User(11, "f")
193 | );
194 |
195 | //when
196 | userEntityManager.add(users).subscribe();
197 |
198 | List usersFromBase = userEntityManager.select().name().in("a", "e").asObservable().blockingFirst();
199 |
200 | //then
201 | assertThat(usersFromBase).isNotNull();
202 | assertThat(usersFromBase).hasSize(4);
203 | }
204 |
205 | @Test
206 | public void testSelectUserFromBoolean_equalsTrue() {
207 | //given
208 | List users = Arrays.asList(
209 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
210 | new User(30, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
211 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
212 | );
213 |
214 | //when
215 | userEntityManager.add(users).subscribe();
216 |
217 | User userFromBase = userEntityManager.select().hacker()
218 | .equalsTo(true)
219 | .first()
220 | .blockingFirst();
221 |
222 | //then
223 | assertThat(userFromBase).isNotNull();
224 | assertThat(userFromBase.getName()).isEqualTo("florent");
225 | }
226 |
227 | @Test
228 | public void testSelectUser_or() {
229 | //given
230 | List users = Arrays.asList(
231 | new User(21, "florent", null, null, false),
232 | new User(30, "kevin", null, null, true),
233 | new User(10, "alex", null, null, false)
234 | );
235 |
236 | //when
237 | userEntityManager.add(users).subscribe();
238 |
239 | List userFromBase = userEntityManager.select()
240 | .name().equalsTo("florent")
241 | .or()
242 | .hacker().isTrue()
243 | .asObservable().blockingFirst();
244 |
245 | //then
246 | assertThat(userFromBase).isNotNull();
247 | assertThat(userFromBase).hasSize(2);
248 | }
249 |
250 | @Test
251 | public void testSelectUser_group() {
252 | //given
253 | List users = Arrays.asList(
254 | new User(10, "florent", null, null, false),
255 | new User(30, "kevin", null, null, true),
256 | new User(20, "mimi", null, null, true),
257 | new User(10, "alex", null, null, false)
258 | );
259 |
260 | //when
261 | userEntityManager.add(users).subscribe();
262 |
263 | List userFromBase = userEntityManager.select()
264 | .beginGroup()
265 | .name().equalsTo("florent")
266 | .or()
267 | .hacker().isTrue()
268 | .endGroup()
269 | .and()
270 | .age().equalsTo(20)
271 | .asObservable().blockingFirst();
272 |
273 | //then
274 | assertThat(userFromBase).isNotNull();
275 | assertThat(userFromBase).hasSize(1);
276 | assertThat(userFromBase.get(0).getName()).isEqualTo("mimi");
277 | }
278 |
279 | @Test
280 | public void testSelectUser_orderAgeASC() {
281 | //given
282 | List users = Arrays.asList(
283 | new User(21, "florent", null, null, false),
284 | new User(30, "kevin", null, null, true),
285 | new User(10, "alex", null, null, false)
286 | );
287 |
288 | //when
289 | userEntityManager.add(users).subscribe();
290 |
291 | List userFromBase = userEntityManager.select()
292 | .sortAsc(UserColumns.age)
293 | .asObservable().blockingFirst();
294 |
295 | //then
296 | assertThat(userFromBase).isNotNull();
297 | assertThat(userFromBase.get(0).getName()).isEqualTo("alex");
298 | assertThat(userFromBase.get(1).getName()).isEqualTo("florent");
299 | assertThat(userFromBase.get(2).getName()).isEqualTo("kevin");
300 | }
301 |
302 | @Test
303 | public void testSelectUser_orderAgeDESC() {
304 | //given
305 | List users = Arrays.asList(
306 | new User(21, "florent", null, null, false),
307 | new User(30, "kevin", null, null, true),
308 | new User(10, "alex", null, null, false)
309 | );
310 |
311 | //when
312 | userEntityManager.add(users).subscribe();
313 | List userFromBase = userEntityManager.select()
314 | .sortDesc(UserColumns.age)
315 | .asObservable().blockingFirst();
316 |
317 | //then
318 | assertThat(userFromBase).isNotNull();
319 | assertThat(userFromBase.get(0).getName()).isEqualTo("kevin");
320 | assertThat(userFromBase.get(1).getName()).isEqualTo("florent");
321 | assertThat(userFromBase.get(2).getName()).isEqualTo("alex");
322 | }
323 |
324 | @Test
325 | public void testSelectUserFromBoolean_isTrue() {
326 | //given
327 | List users = Arrays.asList(
328 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
329 | new User(30, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
330 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
331 | );
332 |
333 | //when
334 | userEntityManager.add(users).subscribe();
335 |
336 | User userFromBase = userEntityManager.select()
337 | .hacker().isTrue()
338 | .first()
339 | .blockingFirst();
340 |
341 | //then
342 | assertThat(userFromBase).isNotNull();
343 | assertThat(userFromBase.getName()).isEqualTo("florent");
344 | }
345 |
346 | @Test
347 | public void testSelectUserFromBoolean_equalsFalse() {
348 | //given
349 | List users = Arrays.asList(
350 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
351 | new User(30, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
352 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
353 | );
354 |
355 | //when
356 | userEntityManager.add(users).subscribe();
357 |
358 | User userFromBase = userEntityManager.select()
359 | .hacker().equalsTo(false)
360 | .first().blockingFirst();
361 |
362 | //then
363 | assertThat(userFromBase).isNotNull();
364 | assertThat(userFromBase.getName()).isEqualTo("alex");
365 | }
366 |
367 | @Test
368 | public void testSelectUserFromBoolean_isFalse() {
369 | //given
370 | List users = Arrays.asList(
371 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
372 | new User(30, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
373 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
374 | );
375 |
376 | //when
377 | userEntityManager.add(users).subscribe();
378 |
379 | User userFromBase = userEntityManager.select()
380 | .hacker().isFalse()
381 | .first()
382 | .blockingFirst();
383 |
384 | //then
385 | assertThat(userFromBase).isNotNull();
386 | assertThat(userFromBase.getName()).isEqualTo("alex");
387 | }
388 |
389 | @Test
390 | public void testSelectUsersFromCat_stringEquals() {
391 | //given
392 | List users = Arrays.asList(
393 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
394 | new User(21, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
395 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
396 | );
397 |
398 | //when
399 | userEntityManager.add(users).subscribe();
400 |
401 | List usersFromBase = userEntityManager.select().cat(CatDatabase.where().shortName().equalsTo("Java")).asObservable().blockingFirst();
402 |
403 | //then
404 | assertThat(usersFromBase).isNotNull();
405 | assertThat(usersFromBase).hasSize(1);
406 | assertThat(usersFromBase.get(0).getName()).isEqualTo("florent");
407 | }
408 |
409 | @Test
410 | public void testSelectUsersFromCat_stringNotEquals() {
411 | //given
412 | List users = Arrays.asList(
413 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
414 | new User(21, "kevin", new Cat("Futé"), Arrays.asList(new Dog("Darty")), true),
415 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
416 | );
417 |
418 | //when
419 | userEntityManager.add(users).subscribe();
420 |
421 | List usersFromBase = userEntityManager.select().cat(CatDatabase.where().shortName().notEqualsTo("Java")).asObservable().blockingFirst();
422 |
423 | //then
424 | assertThat(usersFromBase).isNotNull();
425 | assertThat(usersFromBase).hasSize(2);
426 | }
427 |
428 | @Test
429 | public void testSelectUsersFromCat_stringContains() {
430 | //given
431 | List users = Arrays.asList(
432 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
433 | new User(21, "kevin", new Cat("Jorris"), Arrays.asList(new Dog("Darty")), true),
434 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
435 | );
436 |
437 | //when
438 | userEntityManager.add(users).subscribe();
439 |
440 | List usersFromBase = userEntityManager.select().cat(CatDatabase.where().shortName().contains("J")).asObservable().blockingFirst();
441 |
442 | //then
443 | assertThat(usersFromBase).isNotNull();
444 | assertThat(usersFromBase).hasSize(2);
445 | assertThat(usersFromBase.get(0).getName()).isEqualTo("florent");
446 | assertThat(usersFromBase.get(1).getName()).isEqualTo("kevin");
447 | }
448 |
449 | @Test
450 | public void testSelectUsersFromCat_stringLike() {
451 | //given
452 | List users = Arrays.asList(
453 | new User(21, "florent", new Cat("Java"), Arrays.asList(new Dog("Loulou")), true),
454 | new User(21, "kevin", new Cat("Lava"), Arrays.asList(new Dog("Darty")), true),
455 | new User(10, "alex", new Cat("Yellow"), Arrays.asList(new Dog("Darty"), new Dog("Sasha")), false)
456 | );
457 |
458 | //when
459 | userEntityManager.add(users).subscribe();
460 |
461 | List usersFromBase = userEntityManager.select().cat(CatDatabase.where().shortName().contains("%av%")).asObservable().blockingFirst();
462 |
463 | //then
464 | assertThat(usersFromBase).isNotNull();
465 | assertThat(usersFromBase).hasSize(2);
466 | assertThat(usersFromBase.get(0).getName()).isEqualTo("florent");
467 | assertThat(usersFromBase.get(1).getName()).isEqualTo("kevin");
468 | }
469 |
470 | @Test
471 | public void testSelectUsers_withoutAgeColumns() {
472 | //given
473 | List users = Arrays.asList(
474 | new User(21, "florent", null, null, true),
475 | new User(21, "kevin", null, null, true),
476 | new User(10, "alex", null, null, false)
477 | );
478 | userEntityManager.add(users).subscribe();
479 |
480 | //when
481 | List usersFromBase = userEntityManager
482 | .select()
483 | .fields(UserColumns.name, UserColumns.cat, UserColumns.dogs, UserColumns.hacker)
484 | .asObservable().blockingFirst();
485 |
486 | //then
487 | assertThat(usersFromBase).isNotNull();
488 | assertThat(usersFromBase).hasSize(3);
489 | assertThat(usersFromBase.get(0).getName()).isEqualTo("florent");
490 | assertThat(usersFromBase.get(0).getAge()).isEqualTo(0);
491 | assertThat(usersFromBase.get(1).getName()).isEqualTo("kevin");
492 | assertThat(usersFromBase.get(1).getAge()).isEqualTo(0);
493 | assertThat(usersFromBase.get(2).getName()).isEqualTo("alex");
494 | assertThat(usersFromBase.get(2).getAge()).isEqualTo(0);
495 | }
496 |
497 | @Test
498 | public void testSelectUsers_withoutNameCollumns() {
499 | //given
500 | List users = Arrays.asList(
501 | new User(21, "florent", new Cat("nnn"), Arrays.asList(new Dog("a"), new Dog("b")), true),
502 | new User(21, "kevin", null, null, true),
503 | new User(10, "alex", null, null, false)
504 | );
505 | userEntityManager.add(users).subscribe();
506 |
507 | //when
508 | List usersFromBase = userEntityManager
509 | .select()
510 | .fieldsWithout(UserColumns.name)
511 | .asObservable().blockingFirst();
512 |
513 | //then
514 | assertThat(usersFromBase).isNotNull();
515 | assertThat(usersFromBase).hasSize(3);
516 | assertThat(usersFromBase.get(0).getName()).isNull();
517 | assertThat(usersFromBase.get(0).getAge()).isNotNull();
518 | assertThat(usersFromBase.get(0).getCat()).isNotNull();
519 | assertThat(usersFromBase.get(0).getDogs()).isNotNull();
520 |
521 | assertThat(usersFromBase.get(1).getName()).isNull();
522 | assertThat(usersFromBase.get(2).getName()).isNull();
523 | }
524 |
525 | @Test
526 | public void testSelectUsers_asObservable() {
527 | //given
528 | List users = Arrays.asList(
529 | new User(21, "florent", new Cat("nnn"), Arrays.asList(new Dog("a"), new Dog("b")), true),
530 | new User(21, "kevin", null, null, true),
531 | new User(10, "alex", null, null, false)
532 | );
533 | userEntityManager.add(users).subscribe();
534 |
535 | final AtomicInteger numberOfUsers = new AtomicInteger();
536 |
537 | //when
538 | userEntityManager
539 | .select()
540 | .asObservable()
541 | .subscribe(new Consumer>() {
542 | @Override
543 | public void accept(List users) {
544 | numberOfUsers.set(users.size());
545 | }
546 | });
547 |
548 | //then
549 | assertThat(numberOfUsers.get()).isEqualTo(3);
550 | }
551 |
552 | @Test
553 | public void testSelectUsers_limit() {
554 | //given
555 | List users = Arrays.asList(
556 | new User(21, "a", null, null, true),
557 | new User(21, "b", null, null, true),
558 | new User(21, "c", null, null, true),
559 | new User(21, "d", null, null, true),
560 | new User(21, "e", null, null, true),//4
561 | new User(21, "f", null, null, true),
562 | new User(21, "g", null, null, true),
563 | new User(21, "h", null, null, true),
564 | new User(21, "i", null, null, true),
565 | new User(21, "j", null, null, true),
566 | new User(21, "k", null, null, true),
567 | new User(21, "l", null, null, true),
568 | new User(21, "m", null, null, true)
569 | );
570 | userEntityManager.add(users).subscribe();
571 |
572 | //when
573 | List usersFromBase = userEntityManager
574 | .select()
575 | .limit(4,5)
576 | .asObservable().blockingFirst();
577 |
578 | //then
579 | assertThat(usersFromBase.size()).isEqualTo(5);
580 | assertThat(usersFromBase.get(0).getName()).isEqualTo("e");
581 | }
582 |
583 | }
584 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | mavenCentral()
7 | }
8 | dependencies {
9 |
10 | classpath 'com.android.tools.build:gradle:2.3.1'
11 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
12 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
13 |
14 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
15 | classpath 'me.tatarka:gradle-retrolambda:3.6.1'
16 | // NOTE: Do not place your application dependencies here; they belong
17 | // in the individual module build.gradle files
18 | }
19 | }
20 |
21 | ext{
22 | COMPILE_SDK=25
23 | TARGET_SDK=25
24 | BUILD_TOOL = "25.0.0"
25 | minSdkVersion = 14
26 | sourceCompatibilityVersion = JavaVersion.VERSION_1_7
27 | targetCompatibilityVersion = JavaVersion.VERSION_1_7
28 |
29 | libraryVersion = "1.0.2"
30 | }
31 |
32 | allprojects {
33 | repositories {
34 | jcenter()
35 | mavenCentral()
36 | }
37 | }
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | deployment:
2 | release:
3 | tag: /v.*/
4 | commands:
5 | - ./gradlew assembleDebug install :rxAndroidOrm:bintrayUpload :rxAndroidOrm-annotations:bintrayUpload :rxAndroidOrm-compiler:bintrayUpload
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | #org.gradle.jvmargs=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1999
--------------------------------------------------------------------------------
/gradle/bintray-android-v1.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.jfrog.bintray'
2 |
3 | version = libraryVersion
4 |
5 | task sourcesJar(type: Jar) {
6 | from android.sourceSets.main.java.srcDirs
7 | classifier = 'sources'
8 | }
9 |
10 | task javadoc(type: Javadoc) {
11 | source = android.sourceSets.main.java.srcDirs
12 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
13 | }
14 |
15 | task javadocJar(type: Jar, dependsOn: javadoc) {
16 | classifier = 'javadoc'
17 | from javadoc.destinationDir
18 | }
19 | artifacts {
20 | archives javadocJar
21 | archives sourcesJar
22 | }
23 |
24 | def _user = System.getenv("BINTRAY_USER")
25 | def _key = System.getenv("BINTRAY_API_KEY")
26 | def _passphrase = System.getenv("BINTRAY_PASSPHRASE")
27 |
28 | if(project.rootProject.file('local.properties').exists() && (_user == null || _user.isEmpty())){
29 | Properties properties = new Properties()
30 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
31 |
32 | _user = properties.getProperty("bintray.user")
33 | _key = properties.getProperty("bintray.apikey");
34 | _passphrase = properties.getProperty("bintray.gpg.password")
35 | }
36 |
37 | // Bintray
38 |
39 | bintray {
40 | user = _user
41 | key = _key
42 | override = true
43 | configurations = ['archives']
44 | pkg {
45 | repo = bintrayRepo
46 | name = bintrayName
47 | desc = libraryDescription
48 | userOrg = orgName
49 | websiteUrl = siteUrl
50 | vcsUrl = gitUrl
51 | licenses = allLicenses
52 | publish = true
53 | publicDownloadNumbers = true
54 | version {
55 | desc = libraryDescription
56 | gpg {
57 | sign = true //Determines whether to GPG sign the files. The default is false
58 | passphrase = _passphrase
59 | //Optional. The passphrase for GPG signing'
60 | }
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/gradle/bintray-java-v1.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.jfrog.bintray'
2 |
3 | version = libraryVersion
4 |
5 | task sourcesJar(type: Jar) {
6 | from sourceSets.main.allSource
7 | classifier = 'sources'
8 | }
9 |
10 | task javadocJar(type: Jar, dependsOn: javadoc) {
11 | classifier = 'javadoc'
12 | from javadoc.destinationDir
13 | }
14 | artifacts {
15 | archives javadocJar
16 | archives sourcesJar
17 | }
18 |
19 | // Bintray
20 |
21 | def _user = System.getenv("BINTRAY_USER")
22 | def _key = System.getenv("BINTRAY_API_KEY")
23 | def _passphrase = System.getenv("BINTRAY_PASSPHRASE")
24 |
25 | if(project.rootProject.file('local.properties').exists() && (_user == null || _user.isEmpty())){
26 | Properties properties = new Properties()
27 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
28 |
29 | _user = properties.getProperty("bintray.user")
30 | _key = properties.getProperty("bintray.apikey");
31 | _passphrase = properties.getProperty("bintray.gpg.password")
32 | }
33 |
34 | bintray {
35 | user = _user
36 | key = _key
37 | override = true
38 | configurations = ['archives']
39 | pkg {
40 | repo = bintrayRepo
41 | name = bintrayName
42 | desc = libraryDescription
43 | userOrg = orgName
44 | websiteUrl = siteUrl
45 | vcsUrl = gitUrl
46 | licenses = ['Apache-2.0']
47 | publish = true
48 | publicDownloadNumbers = true
49 | version {
50 | desc = libraryDescription
51 | gpg {
52 | sign = true //Determines whether to GPG sign the files. The default is false
53 | passphrase = _passphrase
54 | //Optional. The passphrase for GPG signing'
55 | }
56 | }
57 | }
58 | }
59 |
60 | //from https://github.com/workarounds/bundler/blob/master/gradle/bintray-java-v1.gradle
--------------------------------------------------------------------------------
/gradle/install-v1.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.github.dcendents.android-maven'
2 |
3 | group = publishedGroupId // Maven Group ID for the artifact
4 |
5 | install {
6 | repositories.mavenInstaller {
7 | // This generates POM.xml with proper parameters
8 | pom {
9 | project {
10 | packaging 'aar'
11 | groupId publishedGroupId
12 | artifactId artifact
13 |
14 | // Add your description here
15 | name libraryName
16 | description libraryDescription
17 | url siteUrl
18 |
19 | // Set your license
20 | licenses {
21 | license {
22 | name licenseName
23 | url licenseUrl
24 | }
25 | }
26 | developers {
27 | developer {
28 | id developerId
29 | name developerName
30 | email developerEmail
31 | }
32 | }
33 | scm {
34 | connection gitUrl
35 | developerConnection gitUrl
36 | url siteUrl
37 |
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
44 | //from https://github.com/workarounds/bundler/blob/master/gradle/install-v1.gradle
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/florent37/RxAndroidOrm/169378bb4617fdffcbd383b07a196798fbe2f7fc/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue May 09 19:39:58 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/publish.sh:
--------------------------------------------------------------------------------
1 | ./gradlew install
2 | ./gradlew :rxandroidorm:bintrayUpload
3 | ./gradlew :rxandroidorm-annotations:bintrayUpload
4 | ./gradlew :rxandroidorm-compiler:bintrayUpload
--------------------------------------------------------------------------------
/rxandroidorm-annotations/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/rxandroidorm-annotations/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | ext {
4 | bintrayRepo = 'maven'
5 | bintrayName = 'rxandroidorm-annotations'
6 | orgName = 'florent37'
7 |
8 | publishedGroupId = 'com.github.florent37'
9 | libraryName = 'RxAndroidOrm'
10 | artifact = 'rxandroidorm-annotations'
11 |
12 | libraryDescription = 'Annotations for RxAndroidOrm'
13 |
14 | siteUrl = 'https://github.com/florent37/RxAndroidOrm'
15 | gitUrl = 'https://github.com/florent37/RxAndroidOrm.git'
16 |
17 | libraryVersion = rootProject.ext.libraryVersion
18 |
19 | developerId = 'florent37'
20 | developerName = 'florent37'
21 | developerEmail = 'champigny.florent@gmail.com'
22 |
23 | licenseName = 'The Apache Software License, Version 2.0'
24 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
25 | }
26 |
27 | apply from: rootProject.file('gradle/install-v1.gradle')
28 | apply from: rootProject.file('gradle/bintray-java-v1.gradle')
--------------------------------------------------------------------------------
/rxandroidorm-annotations/src/main/java/com/github/florent37/rxandroidorm/annotations/DatabaseName.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.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 | * Created by florentchampigny on 07/01/2016.
10 | */
11 | @Retention(RetentionPolicy.SOURCE)
12 | @Target(ElementType.TYPE)
13 | public @interface DatabaseName {
14 | String value();
15 | }
16 |
--------------------------------------------------------------------------------
/rxandroidorm-annotations/src/main/java/com/github/florent37/rxandroidorm/annotations/Id.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.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 | * Created by florentchampigny on 07/01/2016.
10 | */
11 | @Retention(RetentionPolicy.SOURCE)
12 | @Target(ElementType.FIELD)
13 | public @interface Id {
14 | }
15 |
--------------------------------------------------------------------------------
/rxandroidorm-annotations/src/main/java/com/github/florent37/rxandroidorm/annotations/Ignore.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.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 | * Created by florentchampigny on 07/01/2016.
10 | */
11 | @Retention(RetentionPolicy.SOURCE)
12 | @Target(ElementType.FIELD)
13 | public @interface Ignore {
14 | }
15 |
--------------------------------------------------------------------------------
/rxandroidorm-annotations/src/main/java/com/github/florent37/rxandroidorm/annotations/Migration.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.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 | * Created by florentchampigny on 07/01/2016.
10 | */
11 | @Retention(RetentionPolicy.SOURCE)
12 | @Target(ElementType.METHOD)
13 | public @interface Migration {
14 | int value();
15 | }
16 |
--------------------------------------------------------------------------------
/rxandroidorm-annotations/src/main/java/com/github/florent37/rxandroidorm/annotations/Model.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.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 | * Created by florentchampigny on 07/01/2016.
10 | */
11 | @Retention(RetentionPolicy.SOURCE)
12 | @Target(ElementType.TYPE)
13 | public @interface Model {
14 | }
15 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | targetCompatibility = project.targetCompatibilityVersion
4 | sourceCompatibility = project.sourceCompatibilityVersion
5 |
6 | dependencies {
7 | compile 'com.squareup:javapoet:1.4.0'
8 | compile 'com.google.auto.service:auto-service:1.0-rc2'
9 |
10 | compile 'io.reactivex.rxjava2:rxjava:2.0.6'
11 |
12 | compile 'com.facebook.stetho:stetho:1.4.2'
13 |
14 | testCompile 'com.google.truth:truth:0.27'
15 | testCompile 'com.google.testing.compile:compile-testing:0.8'
16 | testCompile 'junit:junit:4.12'
17 | testCompile 'org.assertj:assertj-core:3.2.0'
18 | testCompile 'pl.pragmatists:JUnitParams:1.0.3'
19 |
20 | compile project(':rxandroidorm-annotations')
21 | }
22 |
23 | ext {
24 | bintrayRepo = 'maven'
25 | bintrayName = 'rxandroidorm-compiler'
26 | orgName = 'florent37'
27 |
28 | publishedGroupId = 'com.github.florent37'
29 | libraryName = 'RxAndroidOrm'
30 | artifact = 'rxandroidorm-compiler'
31 |
32 | libraryDescription = 'A simple & fluent Android ORM'
33 |
34 | siteUrl = 'https://github.com/florent37/RxAndroidOrm'
35 | gitUrl = 'https://github.com/florent37/RxAndroidOrm.git'
36 |
37 | libraryVersion = rootProject.ext.libraryVersion
38 |
39 | developerId = 'florent37'
40 | developerName = 'florent37'
41 | developerEmail = 'champigny.florent@gmail.com'
42 |
43 | licenseName = 'The Apache Software License, Version 2.0'
44 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
45 | allLicenses = ["Apache-2.0"]
46 | }
47 |
48 |
49 | apply from: rootProject.file('gradle/install-v1.gradle')
50 | apply from: rootProject.file('gradle/bintray-java-v1.gradle')
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/Constants.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm;
2 |
3 | import com.squareup.javapoet.ClassName;
4 | import com.squareup.javapoet.TypeName;
5 |
6 | import java.text.SimpleDateFormat;
7 | import java.util.Date;
8 |
9 | import io.reactivex.Observable;
10 | import io.reactivex.ObservableEmitter;
11 | import io.reactivex.ObservableOnSubscribe;
12 | import io.reactivex.ObservableSource;
13 | import io.reactivex.functions.Function;
14 |
15 | /**
16 | * Created by florentchampigny on 18/01/2016.
17 | */
18 | public class Constants {
19 | public static final String DAO_PACKAGE = "com.github.florent37.rxandroidorm";
20 |
21 | public static final String DAO_CLASS_NAME = "RxAndroidOrm";
22 | public static final String DATABASE_HELPER_CLASS_NAME = "DatabaseHelper";
23 | public static final String DATABASE_COMMON_INTERFACE_NAME = "Database";
24 | public static final String MIGRATOR = "Migrator";
25 | public static final String CALLBACK = "Callback";
26 |
27 | public static final String DAO_SUFFIX = "Database";
28 | public static final String CURSOR_HELPER_SUFFIX = "CursorHelper";
29 | public static final String QUERY_BUILDER_SUFFIX = "QueryBuilder";
30 | public static final String ENUM_COLUMN_SUFFIX = "Columns";
31 |
32 | public static final TypeName daoClassName = ClassName.get(Constants.DAO_PACKAGE, DAO_CLASS_NAME);
33 | public static final TypeName dbHelperClassName = ClassName.get(Constants.DAO_PACKAGE, DATABASE_HELPER_CLASS_NAME);
34 | public static final TypeName queryBuilderClassName = ClassName.get(Constants.DAO_PACKAGE, QUERY_BUILDER_SUFFIX);
35 | public static final TypeName databaseCommonInterfaceClassName = ClassName.get(Constants.DAO_PACKAGE, DATABASE_COMMON_INTERFACE_NAME);
36 | public static final TypeName migrator = ClassName.get(Constants.DAO_PACKAGE+".migration", MIGRATOR);
37 |
38 | public static final TypeName applicationClassName = ClassName.get("android.app", "Application");
39 | public static final TypeName databaseClassName = ClassName.get("android.database.sqlite", "SQLiteDatabase");
40 | public static final TypeName sqliteOpenHelperClassName = ClassName.get("android.database.sqlite", "SQLiteOpenHelper");
41 | public static final TypeName contextClassName = ClassName.get("android.content", "Context");
42 | public static final TypeName cursorClassName = ClassName.get("android.database", "Cursor");
43 | public static final TypeName contentValuesClassName = ClassName.get("android.content", "ContentValues");
44 | public static final TypeName dateClassName = ClassName.get(Date.class);
45 | public static final TypeName simpleDateFormatClassName = ClassName.get(SimpleDateFormat.class);
46 | public static final TypeName stringBuilderClassName = ClassName.get(StringBuilder.class);
47 |
48 | public static final String ENUM_COLUMN_ELEMENT_NAME = "column_name";
49 | public static final String ENUM_COLUMN_IS_PRIMITIVE = "column_is_primitive";
50 |
51 | public static final String FIELD_ID = "_id";
52 | public static final String FIELD_NAME = "_field_name";
53 | public static final String QUERY_TABLE_VARIABLE = "t";
54 | public static final String QUERY_NAMED = "NAMED";
55 |
56 | public static final String PRIMITIVE_CURSOR_HELPER = "PrimitiveCursorHelper";
57 | public static final TypeName primitiveCursorHelper = ClassName.get(Constants.DAO_PACKAGE, PRIMITIVE_CURSOR_HELPER);
58 | public static final String PRIMITIVE_TABLE_INT = "MODEL_INT";
59 | public static final String PRIMITIVE_TABLE_LONG = "MODEL_INT";
60 | public static final String PRIMITIVE_TABLE_STRING = "MODEL_STRING";
61 | public static final String PRIMITIVE_TABLE_FLOAT = "MODEL_FLOAT";
62 | public static final String PRIMITIVE_TABLE_DOUBLE = "MODEL_FLOAT";
63 | public static final String PRIMITIVE_TABLE_BOOLEAN = "MODEL_BOOLEAN";
64 |
65 | public static final String SELECTOR_NUMBER = "NumberSelector";
66 | public static final String SELECTOR_NUMBER_LIST = "ListNumberSelector";
67 | public static final String SELECTOR_BOOLEAN = "BooleanSelector";
68 | public static final String SELECTOR_BOOLEAN_LIST = "ListBooleanSelector";
69 | public static final String SELECTOR_STRING = "StringSelector";
70 | public static final String SELECTOR_STRING_LIST = "ListStringSelector";
71 | public static final String SELECTOR_DATE = "DateSelector";
72 |
73 | public static final ClassName queryBuilder_NumberSelectorClassName = ClassName.bestGuess(Constants.DAO_PACKAGE + "." + QUERY_BUILDER_SUFFIX + "." + SELECTOR_NUMBER);
74 | public static final ClassName queryBuilder_ListNumberSelectorClassName = ClassName.bestGuess(Constants.DAO_PACKAGE + "." + QUERY_BUILDER_SUFFIX + "." + SELECTOR_NUMBER_LIST);
75 | public static final ClassName queryBuilder_BooleanSelectorClassName = ClassName.bestGuess(Constants.DAO_PACKAGE + "." + QUERY_BUILDER_SUFFIX + "." + SELECTOR_BOOLEAN);
76 | public static final ClassName queryBuilder_ListBooleanSelectorClassName = ClassName.bestGuess(Constants.DAO_PACKAGE + "." + QUERY_BUILDER_SUFFIX + "." + SELECTOR_BOOLEAN_LIST);
77 | public static final ClassName queryBuilder_StringSelectorClassName = ClassName.bestGuess(Constants.DAO_PACKAGE + "." + QUERY_BUILDER_SUFFIX + "." + SELECTOR_STRING);
78 | public static final ClassName queryBuilder_ListStringSelectorClassName = ClassName.bestGuess(Constants.DAO_PACKAGE + "." + QUERY_BUILDER_SUFFIX + "." + SELECTOR_STRING_LIST);
79 | public static final ClassName queryBuilder_DateSelectorClassName = ClassName.bestGuess(Constants.DAO_PACKAGE + "." + QUERY_BUILDER_SUFFIX + "." + SELECTOR_DATE);
80 |
81 | public static final ClassName RX_OBSERVABLE = ClassName.get(Observable.class);
82 | public static final ClassName RX_OBSERVABLE_EMITTER = ClassName.get(ObservableEmitter.class);
83 | public static final ClassName RX_OBSERVABLE_ON_SUBSCRIBE = ClassName.get(ObservableOnSubscribe.class);
84 | public static final ClassName RX_OBSERVABLE_SOURCE = ClassName.get(ObservableSource.class);
85 | public static final ClassName RX_FUNCTION = ClassName.get(Function.class);
86 |
87 | public static final String QUERY_LOGGER = "QueryLogger";
88 | public static final String MODEL_ENTITY_PROXY = "Entity";
89 | public static final String MODEL_ENTITY_PROXY_INTERFACE = "DataBaseModel";
90 | public static final String MODEL_ENTITY_PROXY_GET_ID_METHOD = "getDatabaseModelId";
91 | public static final String MODEL_ENTITY_PROXY_SET_ID_METHOD = "setDatabaseModelId";
92 |
93 | public static final String entityProxyClassString = Constants.DAO_PACKAGE + "." + MODEL_ENTITY_PROXY_INTERFACE;
94 | public static final ClassName entityProxyClass = ClassName.bestGuess(entityProxyClassString);
95 |
96 | public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
97 |
98 | public static final String PARCEL_CREATOR = "CREATOR";
99 | }
100 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/CursorHelper.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm;
2 |
3 | import com.squareup.javapoet.TypeSpec;
4 |
5 | import java.util.List;
6 |
7 | import javax.lang.model.element.Element;
8 |
9 | /**
10 | * Created by florentchampigny on 20/01/2016.
11 | */
12 | public class CursorHelper {
13 | Element element;
14 | TypeSpec typeSpec;
15 |
16 | List dependencies;
17 |
18 | public CursorHelper(Element element, TypeSpec typeSpec, List dependencies) {
19 | this.element = element;
20 | this.typeSpec = typeSpec;
21 | this.dependencies = dependencies;
22 | }
23 |
24 | public String getPackage(){
25 | return ProcessUtils.getObjectPackage(element);
26 | }
27 |
28 | public Element getElement() {
29 | return element;
30 | }
31 |
32 | public TypeSpec getTypeSpec() {
33 | return typeSpec;
34 | }
35 |
36 | public void setTypeSpec(TypeSpec typeSpec) {
37 | this.typeSpec = typeSpec;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/Dependency.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm;
2 |
3 | import com.squareup.javapoet.MethodSpec;
4 | import com.squareup.javapoet.TypeName;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * Created by florentchampigny on 20/01/2016.
10 | */
11 | public class Dependency {
12 | TypeName typeName;
13 | List methodsToAdd;
14 |
15 | public Dependency(TypeName typeName, List methodsToAdd) {
16 | this.typeName = typeName;
17 | this.methodsToAdd = methodsToAdd;
18 | }
19 |
20 | public TypeName getTypeName() {
21 | return typeName;
22 | }
23 |
24 | public void setTypeName(TypeName typeName) {
25 | this.typeName = typeName;
26 | }
27 |
28 | public List getMethodsToAdd() {
29 | return methodsToAdd;
30 | }
31 |
32 | public void setMethodsToAdd(List methodsToAdd) {
33 | this.methodsToAdd = methodsToAdd;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/ProcessUtils.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm;
2 |
3 | import com.github.florent37.rxandroidorm.annotations.Id;
4 | import com.github.florent37.rxandroidorm.annotations.Ignore;
5 | import com.squareup.javapoet.ArrayTypeName;
6 | import com.squareup.javapoet.ClassName;
7 | import com.squareup.javapoet.MethodSpec;
8 | import com.squareup.javapoet.ParameterizedTypeName;
9 | import com.squareup.javapoet.TypeName;
10 | import com.squareup.javapoet.TypeSpec;
11 |
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.List;
15 | import java.util.Set;
16 | import javax.lang.model.element.Element;
17 | import javax.lang.model.element.ElementKind;
18 | import javax.lang.model.element.Modifier;
19 | import javax.lang.model.element.VariableElement;
20 | import javax.lang.model.util.ElementFilter;
21 |
22 | /**
23 | * Created by florentchampigny on 17/01/16.
24 | */
25 | public class ProcessUtils {
26 |
27 | public static List filterIgnore(List elements) {
28 | List filtered = new ArrayList<>();
29 | for (VariableElement variableElement : elements) {
30 | if (variableElement.getAnnotation(Ignore.class) == null && !Constants.PARCEL_CREATOR.equals(
31 | ProcessUtils.getObjectName(variableElement)) || ProcessUtils.isNotVariable(variableElement)) {
32 | filtered.add(variableElement);
33 | }
34 | }
35 | return filterStaticFinal(filtered);
36 | }
37 |
38 | private static boolean isNotVariable(VariableElement variableElement) {
39 | return variableElement.getKind() == ElementKind.ENUM ||
40 | variableElement.getKind() == ElementKind.INTERFACE ||
41 | variableElement.getKind() == ElementKind.CLASS;
42 | }
43 |
44 | public static List filterStaticFinal(List elements) {
45 | List filtered = new ArrayList<>();
46 | for (VariableElement variableElement : elements) {
47 | final Set modifiers = variableElement.getModifiers();
48 | if (!modifiers.containsAll(Arrays.asList(Modifier.FINAL, Modifier.STATIC))) {
49 | filtered.add(variableElement);
50 | }
51 | } return filtered;
52 | }
53 |
54 | public static List getFields(Element element) {
55 | return filterIgnore(ElementFilter.fieldsIn(element.getEnclosedElements()));
56 | }
57 |
58 | public static List getPrimitiveFields(Element element) {
59 | List primitives = new ArrayList<>();
60 | for (VariableElement e : getFields(element)) {
61 | if (isPrimitive(e) && !isCollectionOfPrimitive(e) && !isNotVariable(e)) {
62 | primitives.add(e);
63 | }
64 | }
65 | return filterIgnore(primitives);
66 | }
67 |
68 | public static List getCollectionsOfPrimitiveFields(Element element) {
69 | List collectionsOfPrimitives = new ArrayList<>();
70 | for (VariableElement e : getFields(element)) {
71 | if (isCollectionOfPrimitive(e) && !isNotVariable(e)) {
72 | collectionsOfPrimitives.add(e);
73 | }
74 | }
75 | return filterIgnore(collectionsOfPrimitives);
76 | }
77 |
78 | public static List getNonPrimitiveClassFields(Element element) {
79 | List nonPrimitive = new ArrayList<>();
80 | for (VariableElement e : getFields(element)) {
81 | if (!isPrimitive(e) && !isCollectionOfPrimitive(e) && !isNotVariable(e)) {
82 | nonPrimitive.add(e);
83 | }
84 | }
85 | return filterIgnore(nonPrimitive);
86 | }
87 |
88 | public static boolean hasIdField(Element element) {
89 | return getIdField(element) != null;
90 | }
91 |
92 | public static Element getIdField(Element element) {
93 | for (VariableElement e : getFields(element)) {
94 | if (isIdField(e)) {
95 | return e;
96 | }
97 | }
98 | return null;
99 | }
100 |
101 | public static String getFieldType(VariableElement variableElement) {
102 | TypeName typeName = getFieldClass(variableElement);
103 | if (typeName == TypeName.INT || typeName == TypeName.BOOLEAN || typeName == TypeName.BYTE) {
104 | return "Int";
105 | } else if (typeName == TypeName.LONG) {
106 | return "Long";
107 | } else if (typeName == TypeName.FLOAT) {
108 | return "Float";
109 | } else if (typeName == TypeName.DOUBLE) {
110 | return "Double";
111 | } else if (ClassName.get(String.class).equals(typeName)) {
112 | return "String";
113 | }
114 | return "";
115 | }
116 |
117 | public static String getFieldCast(VariableElement variableElement) {
118 | TypeName typeName = getFieldClass(variableElement);
119 | if (typeName == TypeName.BOOLEAN) {
120 | return "(1 == %s)";
121 | }
122 | return "%s";
123 | }
124 |
125 | public static String getFieldTableType(Element variableElement) {
126 | TypeName typeName = getFieldClass(variableElement);
127 | if (typeName == TypeName.INT
128 | || typeName == TypeName.BOOLEAN
129 | || typeName == TypeName.LONG
130 | || typeName == TypeName.BYTE) {
131 | return "integer";
132 | }
133 | if (typeName == TypeName.FLOAT) {
134 | return "real";
135 | } else if (ClassName.get(String.class).equals(typeName) || isDate(typeName)) {
136 | return "text";
137 | }
138 | return null;
139 | }
140 |
141 | public static String getObjectName(Element element) {
142 | return element.getSimpleName().toString();
143 | }
144 |
145 | public static boolean isIdField(Element element) {
146 | return element.getAnnotation(Id.class) != null && TypeName.LONG.equals(TypeName.get(element.asType()));
147 | }
148 |
149 | public static String getObjectPackage(Element element) {
150 | return element.getEnclosingElement().toString();
151 | }
152 |
153 | public static TypeName getCursorHelper(Element element) {
154 | return ClassName.get(getObjectPackage(element), getCursorHelperName(getObjectName(element)));
155 | }
156 |
157 | public static String getCursorHelperName(String objectName) {
158 | return objectName + Constants.CURSOR_HELPER_SUFFIX;
159 | }
160 |
161 | public static String getQueryBuilderName(String modelName) {
162 | return modelName + Constants.QUERY_BUILDER_SUFFIX;
163 | }
164 |
165 | public static TypeName getQueryBuilder(Element element) {
166 | return ClassName.get(getObjectPackage(element), getObjectName(element) + Constants.QUERY_BUILDER_SUFFIX);
167 | }
168 |
169 | public static String getModelDaoName(Element element) {
170 | return getModelDaoName(getObjectName(element));
171 | }
172 |
173 | public static String getModelDaoName(String modelName) {
174 | return modelName + Constants.DAO_SUFFIX;
175 | }
176 |
177 | public static ClassName getModelDao(Element element) {
178 | return ClassName.get(getObjectPackage(element), getModelDaoName(element));
179 | }
180 |
181 | public static ParameterizedTypeName listOf(TypeName type) {
182 | return ParameterizedTypeName.get(ClassName.get(List.class), type);
183 | }
184 |
185 | public static ParameterizedTypeName listOf(Element element) {
186 | return ParameterizedTypeName.get(ClassName.get(List.class), getFieldClass(element));
187 | }
188 |
189 | public static ParameterizedTypeName listOf(Class classe) {
190 | return ParameterizedTypeName.get(ClassName.get(List.class), ClassName.get(classe));
191 | }
192 |
193 | public static ParameterizedTypeName arraylistOf(TypeName type) {
194 | return ParameterizedTypeName.get(ClassName.get(ArrayList.class), type);
195 | }
196 |
197 | public static ParameterizedTypeName arraylistOf(Class classe) {
198 | return ParameterizedTypeName.get(ClassName.get(ArrayList.class), ClassName.get(classe));
199 | }
200 |
201 | public static boolean isPrimitive(Element element) {
202 | return isPrimitive(TypeName.get(element.asType()));
203 | }
204 |
205 | public static boolean isModelId(VariableElement variableElement) {
206 | return Constants.FIELD_ID.equals(variableElement.getSimpleName().toString());
207 | }
208 |
209 | public static TypeName unbox(TypeName typeName) {
210 | try {
211 | return typeName.unbox();
212 | } catch (Exception e) {
213 | return typeName;
214 | }
215 | }
216 |
217 | public static boolean isPrimitive(TypeName typeName) {
218 | return typeName.isPrimitive()
219 | || unbox(typeName).isPrimitive()
220 | || (ClassName.get(String.class).equals(typeName))
221 | || isDate(typeName);
222 | }
223 |
224 | public static boolean isCollectionOfPrimitive(Element element) {
225 | return isCollection(element) && isPrimitive(getFieldClass(element));
226 | }
227 |
228 | public static String getQueryCast(VariableElement variableElement) {
229 | TypeName typeName = getFieldClass(variableElement);
230 | if (ClassName.get(String.class).equals(typeName)) {
231 | return "$L";
232 | } else if (typeName == TypeName.BOOLEAN || typeName.equals(TypeName.get(Boolean.class))) {
233 | return "String.valueOf($L ? 1 : 0)";
234 | } else {
235 | return "String.valueOf($L)";
236 | }
237 | }
238 |
239 | public static String getKeyName(VariableElement variableElement) {
240 | return getKeyName(getFieldClassName(variableElement));
241 | }
242 |
243 | public static String getKeyName(String modelName) {
244 | return modelName.toLowerCase() + "_id";
245 | }
246 |
247 | public static String getTableName(String elementName) {
248 | return elementName.toUpperCase();
249 | }
250 |
251 | public static String getTableName(Element element) {
252 | return getTableName(getFieldClassName(element));
253 | }
254 |
255 | public static List getParameters(Element element) {
256 | try {
257 | return ((ParameterizedTypeName) ParameterizedTypeName.get(element.asType())).typeArguments;
258 | } catch (Exception e) {
259 | return null;
260 | }
261 | }
262 |
263 | public static TypeName getEnclosedTypeName(Element element) {
264 | List parameters = getParameters(element);
265 | if (parameters == null || parameters.isEmpty()) {
266 | return null;
267 | } else {
268 | return parameters.get(0);
269 | }
270 | }
271 |
272 | public static TypeName getFieldCursorHelperClass(VariableElement element) {
273 | return ClassName.bestGuess(getFieldClass(element).toString() + Constants.CURSOR_HELPER_SUFFIX);
274 | }
275 |
276 | public static TypeName getFieldQueryBuilderClass(VariableElement element) {
277 | return ClassName.bestGuess(getFieldClass(element).toString() + Constants.QUERY_BUILDER_SUFFIX);
278 | }
279 |
280 | public static TypeName getFieldClass(Element element) {
281 | if (isArray(element)) {
282 | TypeName typeName = getArrayEnclosedType(element);
283 | return unbox(typeName);
284 | } else {
285 | TypeName enclosed = unbox(getEnclosedTypeName(element));
286 | if (enclosed != null) {
287 | return enclosed;
288 | } else {
289 | return unbox(TypeName.get(element.asType()));
290 | }
291 | }
292 | }
293 |
294 | public static String getFieldClassName(Element element) {
295 | String name;
296 |
297 | TypeName t = getFieldClass(element);
298 | if (t instanceof ClassName) {
299 | ClassName className = (ClassName) t;
300 | name = className.simpleName();
301 | } else {
302 | name = t.toString();
303 | }
304 |
305 | return name;
306 | }
307 |
308 | public static boolean isArray(Element element) {
309 | try {
310 | return getArrayEnclosedType(element) != null;
311 | } catch (Exception e) {
312 | return false;
313 | }
314 | }
315 |
316 | public static TypeName getArrayEnclosedType(Element element) {
317 | return ((ArrayTypeName) ArrayTypeName.get(element.asType())).componentType;
318 | }
319 |
320 | public static boolean isCollection(Element element) {
321 | return isArray(element) || getEnclosedTypeName(element) != null;
322 | }
323 |
324 | public static String getMethodId(MethodSpec methodSpec) {
325 | return methodSpec.name + methodSpec.parameters.toString();
326 | }
327 |
328 | public static TypeName getElementEnumColumn(Element element) {
329 | return ClassName.bestGuess(getFieldClass(element).toString() + Constants.ENUM_COLUMN_SUFFIX);
330 | }
331 |
332 | public static String getModelId(Element element, String elementVarialbe, String idVariableName) {
333 | StringBuilder stringBuilder = new StringBuilder();
334 | Element idField = getIdField(element);
335 | if (idField != null) {
336 | stringBuilder.append("java.lang.Long ")
337 | .append(idVariableName)
338 | .append(" = ")
339 | .append(elementVarialbe)
340 | .append(".")
341 | .append(getObjectName(idField));
342 | } else {
343 | stringBuilder.append("java.lang.Long ").append(idVariableName).append(" = ");
344 | stringBuilder.append(elementVarialbe)
345 | .append(" instanceof ")
346 | .append(Constants.entityProxyClassString)
347 | .append(" ? ");
348 | stringBuilder.append(
349 | String.format("((%s.%s)%s).%s()", Constants.DAO_PACKAGE, Constants.MODEL_ENTITY_PROXY_INTERFACE,
350 | elementVarialbe, Constants.MODEL_ENTITY_PROXY_GET_ID_METHOD));
351 | stringBuilder.append(": null");
352 | }
353 | return stringBuilder.toString();
354 | }
355 |
356 | public static String setModelId(String variable) {
357 | return String.format("((%s.%s)%s).%s", Constants.DAO_PACKAGE, Constants.MODEL_ENTITY_PROXY_INTERFACE, variable,
358 | Constants.MODEL_ENTITY_PROXY_SET_ID_METHOD);
359 | }
360 |
361 | public static TypeName getModelProxy(Element element) {
362 | return ClassName.get(getObjectPackage(element), getObjectName(element) + Constants.MODEL_ENTITY_PROXY);
363 | }
364 |
365 | public static String getPrimitiveCursorHelperFunction(Element element) {
366 | TypeName typeName = getFieldClass(element);
367 | if (isArray(element)) {
368 | if (getArrayEnclosedType(element).isPrimitive()) {
369 | if (ClassName.get(String.class).equals(typeName)) {
370 | return "getStringsPrimitiveArray";
371 | } else if (TypeName.INT.equals(typeName)) {
372 | return "getIntegersPrimitiveArray";
373 | } else if (TypeName.LONG.equals(typeName)) {
374 | return "getLongsPrimitiveArray";
375 | } else if (TypeName.FLOAT.equals(typeName)) {
376 | return "getFloatsPrimitiveArray";
377 | } else if (TypeName.DOUBLE.equals(typeName)) {
378 | return "getDoublesPrimitiveArray";
379 | } else if (TypeName.BOOLEAN.equals(typeName)) {
380 | return "getBooleansPrimitiveArray";
381 | }
382 | } else {
383 | if (ClassName.get(String.class).equals(typeName)) {
384 | return "getStringsArray";
385 | } else if (TypeName.INT.equals(typeName)) {
386 | return "getIntegersArray";
387 | } else if (TypeName.LONG.equals(typeName)) {
388 | return "getLongsArray";
389 | } else if (TypeName.FLOAT.equals(typeName)) {
390 | return "getFloatsArray";
391 | } else if (TypeName.DOUBLE.equals(typeName)) {
392 | return "getDoublesArray";
393 | } else if (TypeName.BOOLEAN.equals(typeName)) {
394 | return "getBooleansArray";
395 | }
396 | }
397 | } else {
398 | if (ClassName.get(String.class).equals(typeName)) {
399 | return "getStrings";
400 | } else if (TypeName.INT.equals(typeName)) {
401 | return "getIntegers";
402 | } else if (TypeName.LONG.equals(typeName)) {
403 | return "getLongs";
404 | } else if (TypeName.FLOAT.equals(typeName)) {
405 | return "getFloats";
406 | } else if (TypeName.DOUBLE.equals(typeName)) {
407 | return "getDoubles";
408 | } else if (TypeName.BOOLEAN.equals(typeName)) {
409 | return "getBooleans";
410 | }
411 | }
412 | return null;
413 | }
414 |
415 | public static String addPrimitiveCursorHelperFunction(Element element) {
416 | TypeName typeName = getFieldClass(element);
417 | if (ClassName.get(String.class).equals(typeName)) {
418 | return "addStrings";
419 | } else if (TypeName.INT.equals(typeName)) {
420 | return "addIntegers";
421 | } else if (TypeName.LONG.equals(typeName)) {
422 | return "addLongs";
423 | } else if (TypeName.FLOAT.equals(typeName)) {
424 | return "addFloats";
425 | } else if (TypeName.DOUBLE.equals(typeName)) {
426 | return "addDoubles";
427 | } else if (TypeName.BOOLEAN.equals(typeName)) {
428 | return "addBooleans";
429 | }
430 | return null;
431 | }
432 |
433 | public static ClassName getSelectorName(Element element) {
434 | TypeName typeName = getFieldClass(element);
435 | if (isCollection(element)) {
436 | if (TypeName.INT.equals(typeName) || TypeName.LONG.equals(typeName) || TypeName.FLOAT.equals(typeName)) {
437 | return Constants.queryBuilder_ListNumberSelectorClassName;
438 | }
439 | if (TypeName.BOOLEAN.equals(typeName)) {
440 | return Constants.queryBuilder_ListBooleanSelectorClassName;
441 | }
442 | if (TypeName.get(String.class).equals(typeName)) {
443 | return Constants.queryBuilder_ListStringSelectorClassName;
444 | }
445 | } else {
446 | if (TypeName.INT.equals(typeName) || TypeName.LONG.equals(typeName) || TypeName.FLOAT.equals(typeName)) {
447 | return Constants.queryBuilder_NumberSelectorClassName;
448 | }
449 | if (TypeName.BOOLEAN.equals(typeName)) {
450 | return Constants.queryBuilder_BooleanSelectorClassName;
451 | }
452 | if (TypeName.get(String.class).equals(typeName)) {
453 | return Constants.queryBuilder_StringSelectorClassName;
454 | }
455 | if (isDate(typeName)) {
456 | return Constants.queryBuilder_DateSelectorClassName;
457 | }
458 | }
459 | return null;
460 | }
461 |
462 | public static TypeName getUnboxedClass(Element element) {
463 | TypeName typeName = getFieldClass(element);
464 | if (TypeName.INT.equals(typeName)) {
465 | return TypeName.get(Integer.class);
466 | }
467 | if (TypeName.LONG.equals(typeName)) {
468 | return TypeName.get(Long.class);
469 | }
470 | if (TypeName.FLOAT.equals(typeName)) {
471 | return TypeName.get(Float.class);
472 | }
473 | if (TypeName.DOUBLE.equals(typeName)) {
474 | return TypeName.get(Double.class);
475 | }
476 | if (TypeName.BOOLEAN.equals(typeName)) {
477 | return TypeName.get(Boolean.class);
478 | }
479 | if (TypeName.get(String.class).equals(typeName)) {
480 | return typeName;
481 | }
482 | return null;
483 | }
484 |
485 | public static boolean isDate(Element element) {
486 | return isDate(getFieldClass(element));
487 | }
488 |
489 | public static boolean isDate(TypeName typeName) {
490 | return Constants.dateClassName.equals(typeName);
491 | }
492 |
493 | protected static List getMethodsNames(TypeSpec typeSpec) {
494 | List names = new ArrayList<>();
495 | for (MethodSpec methodSpec : typeSpec.methodSpecs) {
496 | names.add(methodSpec.name + methodSpec.parameters.toString());
497 | }
498 | return names;
499 | }
500 |
501 | public static TypeName observableOf(TypeName typeName){
502 | return ParameterizedTypeName.get(Constants.RX_OBSERVABLE, typeName);
503 | }
504 |
505 | public static TypeName observableSourceOf(TypeName typeName){
506 | return ParameterizedTypeName.get(Constants.RX_OBSERVABLE_SOURCE, typeName);
507 | }
508 |
509 | public static TypeName functionOf(TypeName...typeName){
510 | return ParameterizedTypeName.get(Constants.RX_FUNCTION, typeName);
511 | }
512 | }
513 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/Processor.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm;
2 |
3 | import com.github.florent37.rxandroidorm.annotations.DatabaseName;
4 | import com.github.florent37.rxandroidorm.annotations.Migration;
5 | import com.github.florent37.rxandroidorm.annotations.Model;
6 | import com.github.florent37.rxandroidorm.generator.CursorHelperGenerator;
7 | import com.github.florent37.rxandroidorm.generator.DatabaseHelperGenerator;
8 | import com.github.florent37.rxandroidorm.generator.EnumColumnGenerator;
9 | import com.github.florent37.rxandroidorm.generator.ModelEntityProxyGenerator;
10 | import com.github.florent37.rxandroidorm.generator.ModelORMGenerator;
11 | import com.github.florent37.rxandroidorm.generator.ModelORMInterfaceGenerator;
12 | import com.github.florent37.rxandroidorm.generator.PrimitiveCursorHelperGenerator;
13 | import com.github.florent37.rxandroidorm.generator.QueryBuilderGenerator;
14 | import com.github.florent37.rxandroidorm.generator.QueryLoggerGenerator;
15 | import com.google.auto.service.AutoService;
16 | import com.squareup.javapoet.ClassName;
17 | import com.squareup.javapoet.JavaFile;
18 | import com.squareup.javapoet.MethodSpec;
19 | import com.squareup.javapoet.TypeSpec;
20 |
21 | import java.io.IOException;
22 | import java.util.ArrayList;
23 | import java.util.HashMap;
24 | import java.util.HashSet;
25 | import java.util.List;
26 | import java.util.Map;
27 | import java.util.Set;
28 |
29 | import javax.annotation.processing.AbstractProcessor;
30 | import javax.annotation.processing.RoundEnvironment;
31 | import javax.annotation.processing.SupportedAnnotationTypes;
32 | import javax.annotation.processing.SupportedSourceVersion;
33 | import javax.lang.model.SourceVersion;
34 | import javax.lang.model.element.Element;
35 | import javax.lang.model.element.TypeElement;
36 |
37 | /**
38 | * Created by florentchampigny on 07/01/2016.
39 | */
40 | @SupportedSourceVersion(SourceVersion.RELEASE_7)
41 | @SupportedAnnotationTypes(
42 | {
43 | "com.github.florent37.rxandroidorm.annotations.Model",
44 | "com.github.florent37.rxandroidorm.annotations.Migration",
45 | "com.github.florent37.rxandroidorm.annotations.DatabaseName",
46 | "com.github.florent37.rxandroidorm.annotations.Ignore"
47 | })
48 | @AutoService(javax.annotation.processing.Processor.class)
49 | public class Processor extends AbstractProcessor {
50 |
51 | List models = new ArrayList<>();
52 | List daosList = new ArrayList<>();
53 |
54 | List cursorHelpers = new ArrayList<>();
55 |
56 | Map migrators = new HashMap<>();
57 | String dbFile = "database.db";
58 | int version = 1;
59 |
60 | @Override
61 | public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
62 | writeStaticJavaFiles();
63 |
64 | getMigrators(roundEnv);
65 | getDatabaseName(roundEnv);
66 |
67 | for (Element element : roundEnv.getElementsAnnotatedWith(Model.class)) {
68 | models.add(element);
69 | generateColumnEnums(element);
70 | generateEntityProxies(element);
71 | generateCursorHelperFiles(element);
72 | generateModelDaoFiles(element);
73 | }
74 | resolveDependencies();
75 | writeJavaFiles();
76 | return true;
77 | }
78 |
79 | protected void writeStaticJavaFiles() {
80 | //writeFile(JavaFile.builder(Constants.DAO_PACKAGE, new DAOGenerator().generate()).build());
81 | writeFile(JavaFile.builder(Constants.DAO_PACKAGE, new QueryLoggerGenerator().generate()).build());
82 | writeFile(JavaFile.builder(Constants.DAO_PACKAGE, ModelEntityProxyGenerator.generateModelProxyInterface()).build());
83 | writeFile(JavaFile.builder(Constants.DAO_PACKAGE, new PrimitiveCursorHelperGenerator().generate()).build());
84 | writeFile(JavaFile.builder(Constants.DAO_PACKAGE, new QueryBuilderGenerator().generate()).build());
85 | writeFile(JavaFile.builder(Constants.DAO_PACKAGE, new ModelORMInterfaceGenerator().generate()).build());
86 | }
87 |
88 | protected void writeJavaFiles() {
89 | for (CursorHelper cursorHelper : cursorHelpers) {
90 | writeFile(JavaFile.builder(cursorHelper.getPackage(), cursorHelper.getTypeSpec()).build());
91 | }
92 |
93 | writeFile(JavaFile.builder(Constants.DAO_PACKAGE, new DatabaseHelperGenerator(dbFile, version, daosList, migrators).generate()).build());
94 | }
95 |
96 | protected void writeFile(JavaFile javaFile) {
97 | //try {
98 | // javaFile.writeTo(System.out);
99 | //} catch (IOException e) {
100 | // //e.printStackTrace();
101 | //}
102 |
103 | try {
104 | javaFile.writeTo(this.processingEnv.getFiler());
105 | } catch (IOException e) {
106 | //e.printStackTrace();
107 | }
108 | }
109 |
110 | private void getMigrators(RoundEnvironment roundEnv) {
111 | int max = 1;
112 | for (Element element : roundEnv.getElementsAnnotatedWith(Migration.class)) {
113 | int v = element.getAnnotation(Migration.class).value();
114 | if (max < v) {
115 | max = v;
116 | }
117 | migrators.put(v, element);
118 | }
119 | version = max;
120 | }
121 |
122 | private void getDatabaseName(RoundEnvironment roundEnv) {
123 | for (Element element : roundEnv.getElementsAnnotatedWith(DatabaseName.class)) {
124 | String name = element.getAnnotation(DatabaseName.class).value();
125 | if (name != null && name.trim().length() > 0) {
126 | if (!name.endsWith(".db")) {
127 | name = name + ".db";
128 | }
129 | dbFile = name;
130 | return;
131 | }
132 | }
133 | }
134 |
135 | private void generateEntityProxies(Element element) {
136 | ModelEntityProxyGenerator entityProxyGenerator = new ModelEntityProxyGenerator(element);
137 |
138 | writeFile(JavaFile.builder(ProcessUtils.getObjectPackage(element), entityProxyGenerator.generate()).build());
139 | }
140 |
141 | private void generateColumnEnums(Element element) {
142 | EnumColumnGenerator columnGenerator = new EnumColumnGenerator(element);
143 |
144 | writeFile(JavaFile.builder(ProcessUtils.getObjectPackage(element), columnGenerator.generate()).build());
145 | }
146 |
147 | private void resolveDependencies() {
148 | for (CursorHelper from : cursorHelpers) {
149 | for (Dependency dependency : from.dependencies) {
150 | for (CursorHelper to : cursorHelpers) {
151 | if (dependency.getTypeName().equals(ProcessUtils.getFieldClass(to.element))) {
152 | HashSet methodsNames = new HashSet<>(ProcessUtils.getMethodsNames(to.getTypeSpec()));
153 |
154 | TypeSpec.Builder builder = to.getTypeSpec().toBuilder();
155 |
156 | for (MethodSpec methodSpec : dependency.getMethodsToAdd()) {
157 | if (!methodsNames.contains(ProcessUtils.getMethodId(methodSpec))) {
158 | builder.addMethod(methodSpec);
159 | methodsNames.add(ProcessUtils.getMethodId(methodSpec));
160 | }
161 | }
162 | to.setTypeSpec(builder.build());
163 | }
164 | }
165 | }
166 | }
167 | }
168 |
169 | private void generateCursorHelperFiles(Element element) {
170 | CursorHelperGenerator cursorHelperGenerator = new CursorHelperGenerator(element);
171 | cursorHelpers.add(new CursorHelper(element, cursorHelperGenerator.generate(), cursorHelperGenerator.getDependencies()));
172 | }
173 |
174 | private void generateModelDaoFiles(Element element) {
175 | ModelORMGenerator modelORMGenerator = new ModelORMGenerator(element).generate();
176 |
177 | writeFile(JavaFile.builder(ProcessUtils.getObjectPackage(element), modelORMGenerator.getDao()).build());
178 | writeFile(JavaFile.builder(ProcessUtils.getObjectPackage(element), modelORMGenerator.getQueryBuilder()).build());
179 |
180 | daosList.add(ProcessUtils.getModelDao(element));
181 | }
182 |
183 | private void generateModelDaoInterface() {
184 | ModelORMInterfaceGenerator modelORMInterfaceGenerator = new ModelORMInterfaceGenerator();
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/generator/CursorHelperGenerator.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.generator;
2 |
3 | import com.squareup.javapoet.ClassName;
4 | import com.squareup.javapoet.MethodSpec;
5 | import com.squareup.javapoet.TypeName;
6 | import com.squareup.javapoet.TypeSpec;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.HashSet;
11 | import java.util.List;
12 | import java.util.Set;
13 |
14 | import javax.lang.model.element.Element;
15 | import javax.lang.model.element.Modifier;
16 | import javax.lang.model.element.VariableElement;
17 |
18 | import com.github.florent37.rxandroidorm.Constants;
19 | import com.github.florent37.rxandroidorm.Dependency;
20 | import com.github.florent37.rxandroidorm.ProcessUtils;
21 |
22 | /**
23 | * Created by florentchampigny on 18/01/2016.
24 | */
25 | public class CursorHelperGenerator {
26 |
27 | Element element;
28 | String objectName;
29 | TypeName modelType;
30 | List fields;
31 | List otherClassFields;
32 | List collections;
33 | List dependencies = new ArrayList<>();
34 |
35 | public CursorHelperGenerator(Element element) {
36 | this.element = element;
37 | this.objectName = ProcessUtils.getObjectName(element);
38 | this.modelType = TypeName.get(element.asType());
39 | this.fields = ProcessUtils.getPrimitiveFields(element);
40 | this.otherClassFields = ProcessUtils.getNonPrimitiveClassFields(element);
41 | this.collections = ProcessUtils.getCollectionsOfPrimitiveFields(element);
42 | }
43 |
44 | public TypeSpec generate() {
45 |
46 | MethodSpec.Builder fromCursorB = MethodSpec.methodBuilder("fromCursor")
47 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
48 | .returns(modelType)
49 | .addParameter(Constants.cursorClassName, "cursor")
50 | .addParameter(Constants.databaseClassName, "db")
51 | .addStatement("$T object = new $T()", modelType, ProcessUtils.getModelProxy(element))
52 |
53 | .addStatement("long objectId = cursor.getLong(cursor.getColumnIndex($S))", Constants.FIELD_ID)
54 | .addStatement("$L(objectId)", ProcessUtils.setModelId("object"));
55 |
56 | //for
57 | for (int i = 0; i < fields.size(); ++i) {
58 | VariableElement variableElement = fields.get(i);
59 | if (ProcessUtils.isPrimitive(variableElement)) {
60 | fromCursorB.addStatement("int index$L = cursor.getColumnIndex($S)", i, variableElement.getSimpleName());
61 | fromCursorB.beginControlFlow("if(index$L != -1)", i);
62 | String cursor = "cursor.get$L(index$L)";
63 |
64 | if (ProcessUtils.isDate(variableElement)) {
65 | fromCursorB.addCode("try{ \n")
66 | .addStatement("String date$L = cursor.getString(cursor.getColumnIndex($S))", i, variableElement.getSimpleName())
67 | .addStatement("if(date$L != null) object.$L = new $T($S).parse(date$L)",
68 | i, variableElement.getSimpleName(), Constants.simpleDateFormatClassName, Constants.DATE_FORMAT, i)
69 | .addCode("} catch ($T e) { e.printStackTrace(); }", TypeName.get(Exception.class));
70 | } else {
71 | cursor = String.format(ProcessUtils.getFieldCast(variableElement), cursor);
72 |
73 | fromCursorB.addStatement("object.$L = " + cursor, variableElement.getSimpleName(), ProcessUtils.getFieldType(variableElement), i);
74 | }
75 | fromCursorB.endControlFlow();
76 | }
77 | }
78 |
79 | for (int i = 0; i < otherClassFields.size(); ++i) {
80 | VariableElement variableElement = otherClassFields.get(i);
81 |
82 | fromCursorB.addCode("\n");
83 | String JOIN_NAME = ProcessUtils.getTableName(objectName) + "_" + ProcessUtils.getTableName(variableElement);
84 |
85 | fromCursorB.addStatement("$T cursor$L = db.rawQuery($S,new String[]{String.valueOf(objectId), $S})", Constants.cursorClassName, i, "SELECT * FROM " + ProcessUtils.getTableName(variableElement) + ", " + JOIN_NAME + " WHERE " + JOIN_NAME + "." + ProcessUtils.getKeyName(objectName) + " = ? AND " + ProcessUtils.getTableName(variableElement) + "." + Constants.FIELD_ID + " = " + JOIN_NAME + "." + ProcessUtils.getKeyName(variableElement) + " AND " + JOIN_NAME + "." + Constants.FIELD_NAME + "= ?", ProcessUtils.getObjectName(variableElement));
86 |
87 | fromCursorB.addStatement("$T objects$L = $T.get(cursor$L,db)", ProcessUtils.listOf(variableElement), i, ProcessUtils.getFieldCursorHelperClass(variableElement), i);
88 |
89 | if (ProcessUtils.isCollection(variableElement))
90 | fromCursorB.addStatement("if(!objects$L.isEmpty()) object.$L = objects$L", i, ProcessUtils.getObjectName(variableElement), i);
91 | else
92 | fromCursorB.addStatement("if(!objects$L.isEmpty()) object.$L = objects$L.get(0)", i, ProcessUtils.getObjectName(variableElement), i);
93 |
94 | fromCursorB.addStatement("cursor$L.close()", i);
95 | }
96 |
97 | for (int i = 0; i < collections.size(); ++i) {
98 | VariableElement variableElement = collections.get(i);
99 | fromCursorB.addStatement("object.$L = $T.$L(db,objectId,$S)", ProcessUtils.getObjectName(variableElement), Constants.primitiveCursorHelper, ProcessUtils.getPrimitiveCursorHelperFunction(variableElement), ProcessUtils.getObjectName(variableElement));
100 | }
101 |
102 | fromCursorB.addCode("\n").addStatement("return object");
103 |
104 | MethodSpec.Builder getValuesB = MethodSpec.methodBuilder("getValues")
105 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
106 | .returns(Constants.contentValuesClassName)
107 | .addParameter(modelType, "object")
108 | .addParameter(ClassName.get(String.class), "name")
109 | .addStatement("$T values = new $T()", Constants.contentValuesClassName, Constants.contentValuesClassName)
110 | .addStatement("if(name != null) values.put($S,name)", Constants.FIELD_NAME);
111 |
112 | for (int i = 0; i < fields.size(); ++i) {
113 | VariableElement variableElement = fields.get(i);
114 | if (ProcessUtils.isPrimitive(variableElement)) {
115 | if (ProcessUtils.isDate(variableElement)) {
116 | getValuesB.addStatement("if(object.$L != null) values.put($S, new $T($S).format(object.$L))", variableElement.getSimpleName(), variableElement.getSimpleName(), Constants.simpleDateFormatClassName, Constants.DATE_FORMAT, variableElement.getSimpleName());
117 | } else if (!ProcessUtils.isIdField(variableElement)) {
118 | String statement = "values.put($S,object.$L)";
119 | if (ProcessUtils.isModelId(variableElement))
120 | statement = "if(" + ProcessUtils.getCursorHelperName("object") + " != 0) " + statement;
121 | getValuesB.addStatement(statement, variableElement.getSimpleName(), variableElement.getSimpleName());
122 | }
123 | }
124 | }
125 |
126 | getValuesB.addStatement(ProcessUtils.getModelId(element, "object", "id"));
127 | getValuesB.addStatement("if(id != null && id != 0) values.put($S, id)", "_id");
128 |
129 | List joinMethods = new ArrayList<>();
130 | Set addedMethodsNames = new HashSet<>();
131 | for (VariableElement variableElement : otherClassFields) {
132 | String JOIN_NAME = ProcessUtils.getTableName(objectName) + "_" + ProcessUtils.getTableName(variableElement);
133 | if (!addedMethodsNames.contains(JOIN_NAME)) {
134 | joinMethods.add(MethodSpec.methodBuilder("get" + JOIN_NAME + "Values")
135 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
136 | .returns(Constants.contentValuesClassName)
137 | .addParameter(TypeName.LONG, "objectId")
138 | .addParameter(TypeName.LONG, "secondObjectId")
139 | .addParameter(ClassName.get(String.class), "name")
140 | .addStatement("$T values = new $T()", Constants.contentValuesClassName, Constants.contentValuesClassName)
141 | .addStatement("values.put($S,objectId)", ProcessUtils.getKeyName(this.objectName))
142 | .addStatement("values.put($S,secondObjectId)", ProcessUtils.getKeyName(variableElement))
143 | .addStatement("values.put($S,name)", Constants.FIELD_NAME)
144 | .addStatement("return values").build());
145 | addedMethodsNames.add(JOIN_NAME);
146 | }
147 | }
148 |
149 | getValuesB.addStatement("return values");
150 |
151 | MethodSpec get = MethodSpec.methodBuilder("get")
152 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
153 | .returns(ProcessUtils.listOf(modelType))
154 | .addParameter(Constants.cursorClassName, "cursor")
155 | .addParameter(Constants.databaseClassName, "db")
156 | .addStatement("$T objects = new $T()", ProcessUtils.listOf(modelType), ProcessUtils.arraylistOf(modelType))
157 | .addStatement("cursor.moveToFirst()")
158 | .addCode("while (!cursor.isAfterLast()) {\n")
159 | .addStatement(" $T object = fromCursor(cursor,db)", modelType)
160 | .addStatement(" objects.add(object)")
161 | .addStatement(" cursor.moveToNext()")
162 | .addCode("}\n")
163 | .addStatement("return objects")
164 | .build();
165 |
166 | return TypeSpec.classBuilder(ProcessUtils.getCursorHelperName(objectName))
167 | .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
168 | .addMethod(fromCursorB.build())
169 | .addMethod(getValuesB.build())
170 | .addMethod(get)
171 | .addMethods(joinMethods)
172 | .addMethods(generateInsertMethods())
173 | .addMethods(generateUpdateMethod())
174 | .build();
175 |
176 | }
177 |
178 | protected List generateUpdateMethod() {
179 | List methodSpecs = new ArrayList<>();
180 |
181 | MethodSpec.Builder updateB = MethodSpec.methodBuilder("update")
182 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
183 | .returns(TypeName.LONG)
184 | .addParameter(Constants.databaseClassName, "database")
185 | .addParameter(modelType, "object");
186 |
187 | updateB.addStatement(ProcessUtils.getModelId(element, "object", "objectId"));
188 |
189 | updateB.beginControlFlow("if(objectId != null)");
190 | updateB.addStatement("database.update($S, getValues(object,null), $S, new String[]{String.valueOf(objectId)})", ProcessUtils.getTableName(objectName), Constants.FIELD_ID + " = ?");
191 |
192 | //for (int i = 0; i < collections.size(); ++i) {
193 | // VariableElement variableElement = collections.get(i);
194 | // updateB.addStatement("if(object.$L != null) $T.$L(database,objectId,$S,object.$L)", ProcessUtils.getObjectName(variableElement), Constants.primitiveCursorHelper, ProcessUtils.addPrimitiveCursorHelperFunction(variableElement), ProcessUtils.getObjectName(variableElement), ProcessUtils.getObjectName(variableElement));
195 | //}
196 |
197 | updateB.endControlFlow();
198 |
199 | for (VariableElement variableElement : otherClassFields) {
200 | updateB.addStatement("$T.updateFor$L(database,object.$L, objectId , $S)", ProcessUtils.getFieldCursorHelperClass(variableElement), objectName, ProcessUtils.getObjectName(variableElement), ProcessUtils.getObjectName(variableElement));
201 |
202 | String JOINTABLE = ProcessUtils.getTableName(objectName) + "_" + ProcessUtils.getTableName(variableElement);
203 |
204 | MethodSpec.Builder updateForB = MethodSpec.methodBuilder("updateFor" + objectName)
205 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
206 | .addParameter(Constants.databaseClassName, "database")
207 | .addParameter(ProcessUtils.getFieldClass(variableElement), "child")
208 | .addParameter(TypeName.LONG, "parentId")
209 | .addParameter(ClassName.get(String.class), "variable")
210 |
211 | .beginControlFlow("if(child == null)")
212 | .addStatement("database.delete($S, \"$L = ? AND $L = ?\", new String[]{String.valueOf(parentId), variable})", JOINTABLE, ProcessUtils.getKeyName(objectName), Constants.FIELD_NAME)
213 | .endControlFlow()
214 |
215 | .beginControlFlow("else");
216 | {
217 | updateForB.addStatement(ProcessUtils.getModelId(variableElement, "child", "objectId"));
218 | }
219 |
220 | updateForB
221 | .beginControlFlow("if(objectId != null)")
222 | .addStatement("update(database,child)")
223 | .endControlFlow()
224 |
225 | .beginControlFlow("else")
226 | .addStatement("insertFor$L(database,child,parentId,variable)", objectName)
227 | .endControlFlow()
228 |
229 | .endControlFlow();
230 |
231 | MethodSpec update = updateForB.build();
232 |
233 | MethodSpec.Builder updateAllB = MethodSpec.methodBuilder("updateFor" + objectName)
234 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
235 | .addParameter(Constants.databaseClassName, "database")
236 | .addParameter(ProcessUtils.listOf(ProcessUtils.getFieldClass(variableElement)), "objects")
237 | .addParameter(TypeName.LONG, "parentId")
238 | .addParameter(ClassName.get(String.class), "variable")
239 |
240 | .addStatement("database.delete($S, \"$L = ? AND $L = ?\", new String[]{String.valueOf(parentId), variable})", JOINTABLE, ProcessUtils.getKeyName(objectName), Constants.FIELD_NAME)
241 | .beginControlFlow("if(objects != null)")
242 | .beginControlFlow("for($T child : objects)", ProcessUtils.getFieldClass(variableElement));
243 |
244 | {
245 | updateAllB.addStatement(ProcessUtils.getModelId(variableElement, "child", "objectId"));
246 |
247 | updateAllB
248 | .beginControlFlow("if(objectId != null)")
249 | .addStatement("update(database,child)")
250 | .addStatement("database.insert($S, null, get$LValues(parentId, objectId, variable))", JOINTABLE, JOINTABLE)
251 | .endControlFlow()
252 |
253 | .beginControlFlow("else")
254 | .addStatement("insertFor$L(database,child,parentId,variable)", objectName)
255 | .endControlFlow();
256 | }
257 |
258 | updateAllB
259 | .endControlFlow()
260 | .endControlFlow();
261 |
262 | dependencies.add(new Dependency(ProcessUtils.getFieldClass(variableElement), Arrays.asList(update, updateAllB.build())));
263 | }
264 |
265 | methodSpecs.add(updateB.addStatement("return objectId").build());
266 |
267 | methodSpecs.add(MethodSpec.methodBuilder("update")
268 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
269 | .addParameter(Constants.databaseClassName, "database")
270 | .addParameter(ProcessUtils.listOf(modelType), "objects")
271 | .addStatement("for($T object : objects) update(database,object)", modelType)
272 | .build());
273 |
274 | return methodSpecs;
275 | }
276 |
277 | protected List generateInsertMethods() {
278 | List methodSpecs = new ArrayList<>();
279 |
280 | MethodSpec.Builder insertB = MethodSpec.methodBuilder("insert")
281 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
282 | .returns(TypeName.LONG)
283 | .addParameter(Constants.databaseClassName, "database")
284 | .addParameter(modelType, "object")
285 | .addStatement("long objectId = database.insertWithOnConflict($S, null, getValues(object,null), android.database.sqlite.SQLiteDatabase.CONFLICT_REPLACE)", ProcessUtils.getTableName(objectName));
286 |
287 | Element idField = ProcessUtils.getIdField(element);
288 | if (idField != null)
289 | insertB.addStatement("object.$L = objectId", ProcessUtils.getObjectName(idField));
290 |
291 | for (VariableElement variableElement : otherClassFields) {
292 | insertB.addStatement("$T.insertFor$L(database,object.$L, objectId , $S)", ProcessUtils.getFieldCursorHelperClass(variableElement), objectName, ProcessUtils.getObjectName(variableElement), ProcessUtils.getObjectName(variableElement));
293 |
294 | String JOINTABLE = ProcessUtils.getTableName(objectName) + "_" + ProcessUtils.getTableName(variableElement);
295 |
296 | MethodSpec insert = MethodSpec.methodBuilder("insertFor" + objectName)
297 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
298 | .addParameter(Constants.databaseClassName, "database")
299 | .addParameter(ProcessUtils.getFieldClass(variableElement), "child")
300 | .addParameter(TypeName.LONG, "parentId")
301 | .addParameter(ClassName.get(String.class), "variable")
302 |
303 | .beginControlFlow("if(child != null)")
304 | .addStatement("long objectId = insert(database,child)")
305 | .addStatement("database.insert($S, null, get$LValues(parentId, objectId, variable))", JOINTABLE, JOINTABLE)
306 | .endControlFlow()
307 |
308 | .build();
309 |
310 | MethodSpec insertAll = MethodSpec.methodBuilder("insertFor" + objectName)
311 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
312 | .addParameter(Constants.databaseClassName, "database")
313 | .addParameter(ProcessUtils.listOf(ProcessUtils.getFieldClass(variableElement)), "objects")
314 | .addParameter(TypeName.LONG, "parentId")
315 | .addParameter(ClassName.get(String.class), "variable")
316 |
317 | .beginControlFlow("if(objects != null)")
318 | .beginControlFlow("for($T child : objects)", ProcessUtils.getFieldClass(variableElement))
319 | .addStatement("insertFor$L(database,child, parentId, variable)", objectName)
320 | .endControlFlow()
321 | .endControlFlow()
322 |
323 | .build();
324 |
325 | MethodSpec getTABLE_NAMEvalues = MethodSpec.methodBuilder("get" + JOINTABLE + "Values")
326 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
327 | .returns(Constants.contentValuesClassName)
328 | .addParameter(TypeName.LONG, "objectId")
329 | .addParameter(TypeName.LONG, "secondObjectId")
330 | .addParameter(ClassName.get(String.class), "name")
331 | .addStatement("$T values = new $T()", Constants.contentValuesClassName, Constants.contentValuesClassName)
332 | .addStatement("values.put($S,objectId)", ProcessUtils.getKeyName(this.objectName))
333 | .addStatement("values.put($S,secondObjectId)", ProcessUtils.getKeyName(variableElement))
334 | .addStatement("values.put($S,name)", Constants.FIELD_NAME)
335 | .addStatement("return values").build();
336 |
337 | dependencies.add(new Dependency(ProcessUtils.getFieldClass(variableElement), Arrays.asList(insert, insertAll, getTABLE_NAMEvalues)));
338 | }
339 |
340 | for (int i = 0; i < collections.size(); ++i) {
341 | VariableElement variableElement = collections.get(i);
342 | insertB.addStatement("if(object.$L != null) $T.$L(database,objectId,$S,object.$L)", ProcessUtils.getObjectName(variableElement), Constants.primitiveCursorHelper, ProcessUtils.addPrimitiveCursorHelperFunction(variableElement), ProcessUtils.getObjectName(variableElement), ProcessUtils.getObjectName(variableElement));
343 | }
344 |
345 | methodSpecs.add(insertB.addStatement("return objectId").build());
346 |
347 | methodSpecs.add(MethodSpec.methodBuilder("insert")
348 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
349 | .addParameter(Constants.databaseClassName, "database")
350 | .addParameter(ProcessUtils.listOf(modelType), "objects")
351 | .addStatement("for($T object : objects) insert(database,object)", modelType)
352 | .build());
353 |
354 | return methodSpecs;
355 | }
356 |
357 | public List getDependencies() {
358 | return dependencies;
359 | }
360 | }
361 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/generator/DAOGenerator.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.generator;
2 |
3 | import com.squareup.javapoet.ClassName;
4 | import com.squareup.javapoet.MethodSpec;
5 | import com.squareup.javapoet.TypeSpec;
6 | import com.github.florent37.rxandroidorm.Constants;
7 |
8 | import javax.lang.model.element.Modifier;
9 |
10 | /**
11 | * Created by florentchampigny on 18/01/2016.
12 | */
13 | public class DAOGenerator {
14 |
15 | public DAOGenerator() {
16 | }
17 |
18 | public TypeSpec generate() {
19 |
20 | return TypeSpec.classBuilder(Constants.DAO_CLASS_NAME)
21 | .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
22 | .addField(Constants.daoClassName, "INSTANCE", Modifier.PRIVATE, Modifier.STATIC)
23 | .addField(Constants.databaseClassName, "database", Modifier.PRIVATE)
24 | .addField(Constants.dbHelperClassName, "helper", Modifier.PRIVATE)
25 |
26 | .addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build())
27 |
28 | .addMethod(MethodSpec.methodBuilder("onCreate")
29 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
30 | .addParameter(Constants.applicationClassName, "application")
31 | .addStatement("if(INSTANCE == null) INSTANCE = new $T()", Constants.daoClassName)
32 | .addStatement("INSTANCE.helper = new $T(application)", Constants.dbHelperClassName)
33 | .build())
34 |
35 | .addMethod(MethodSpec.methodBuilder("getInstance")
36 | .returns(Constants.daoClassName)
37 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
38 | .addStatement("return INSTANCE")
39 | .build())
40 |
41 | .addMethod(MethodSpec.methodBuilder("onDestroy")
42 | .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
43 | .build())
44 |
45 | .addMethod(MethodSpec.methodBuilder("getDatabase")
46 | .returns(Constants.databaseClassName)
47 | .addModifiers(Modifier.PUBLIC)
48 | .addStatement("return database")
49 | .build())
50 |
51 | .addMethod(MethodSpec.methodBuilder("open")
52 | .returns(Constants.daoClassName)
53 | .addException(ClassName.get("android.database", "SQLException"))
54 | .addModifiers(Modifier.PUBLIC)
55 | .addStatement("database = helper.getWritableDatabase()")
56 | .addStatement("return this")
57 | .build())
58 |
59 | .addMethod(MethodSpec.methodBuilder("close")
60 | .returns(Constants.daoClassName)
61 | .addModifiers(Modifier.PUBLIC)
62 | .addStatement("helper.close()")
63 | .addStatement("return this")
64 | .build())
65 |
66 | .build();
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/generator/DatabaseHelperGenerator.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.generator;
2 |
3 | import com.squareup.javapoet.ClassName;
4 | import com.squareup.javapoet.MethodSpec;
5 | import com.squareup.javapoet.TypeName;
6 | import com.squareup.javapoet.TypeSpec;
7 | import com.github.florent37.rxandroidorm.Constants;
8 |
9 | import java.util.List;
10 | import java.util.Map;
11 |
12 | import javax.lang.model.element.Element;
13 | import javax.lang.model.element.Modifier;
14 |
15 | /**
16 | * Created by florentchampigny on 18/01/2016.
17 | */
18 | public class DatabaseHelperGenerator {
19 |
20 | String fileName;
21 | int version;
22 |
23 | List daos;
24 | Map migrators;
25 |
26 | public DatabaseHelperGenerator(String fileName, int version, List daos, Map migrators) {
27 | this.fileName = fileName;
28 | this.version = version;
29 | this.daos = daos;
30 | this.migrators = migrators;
31 | }
32 |
33 | public TypeSpec generate() {
34 |
35 | MethodSpec.Builder onCreate = MethodSpec.methodBuilder("onCreate")
36 | .addModifiers(Modifier.PUBLIC)
37 | .addParameter(Constants.databaseClassName, "database");
38 | for (ClassName dao : daos)
39 | onCreate.addStatement("for($T s : $T.create()) database.execSQL(s)", ClassName.get(String.class), dao);
40 |
41 | onCreate.addStatement("for($T s : $T.create()) database.execSQL(s)", ClassName.get(String.class), ClassName.get(Constants.DAO_PACKAGE, Constants.PRIMITIVE_CURSOR_HELPER));
42 |
43 | MethodSpec.Builder onUpgrade = MethodSpec.methodBuilder("onUpgrade")
44 | .addModifiers(Modifier.PUBLIC)
45 | .addParameter(Constants.databaseClassName, "database")
46 | .addParameter(TypeName.INT, "oldVersion")
47 | .addParameter(TypeName.INT, "newVersion")
48 |
49 | .addStatement("int version = oldVersion")
50 | .addStatement("$T freezerMigrator = new $T(database)", Constants.migrator, Constants.migrator)
51 | ;
52 |
53 | for(int i=1;i fields;
23 |
24 | public EnumColumnGenerator(Element element) {
25 | this.element = element;
26 | this.fields = ProcessUtils.getFields(element);
27 | }
28 |
29 | public TypeSpec generate() {
30 | TypeSpec.Builder enumBuilder = TypeSpec.enumBuilder(ProcessUtils.getObjectName(element) + Constants.ENUM_COLUMN_SUFFIX)
31 | .addModifiers(Modifier.PUBLIC)
32 | .addField(String.class, Constants.ENUM_COLUMN_ELEMENT_NAME, Modifier.PRIVATE, Modifier.FINAL)
33 | .addField(TypeName.BOOLEAN, Constants.ENUM_COLUMN_IS_PRIMITIVE, Modifier.PRIVATE, Modifier.FINAL)
34 | .addMethod(MethodSpec.methodBuilder("getName")
35 | .addModifiers(Modifier.PUBLIC)
36 | .returns(TypeName.get(String.class))
37 | .addStatement("return this.$L", Constants.ENUM_COLUMN_ELEMENT_NAME)
38 | .build())
39 | .addMethod(MethodSpec.methodBuilder("isPrimitive")
40 | .addModifiers(Modifier.PUBLIC)
41 | .returns(TypeName.BOOLEAN)
42 | .addStatement("return this.$L", Constants.ENUM_COLUMN_IS_PRIMITIVE)
43 | .build())
44 | .addMethod(MethodSpec.constructorBuilder()
45 | .addParameter(String.class, "name")
46 | .addParameter(TypeName.BOOLEAN, "primitive")
47 | .addStatement("this.$L = name", Constants.ENUM_COLUMN_ELEMENT_NAME)
48 | .addStatement("this.$L = primitive", Constants.ENUM_COLUMN_IS_PRIMITIVE)
49 | .build());
50 |
51 | for (VariableElement variableElement : fields) {
52 | String fieldSqlName = ProcessUtils.getObjectName(variableElement);
53 | if (ProcessUtils.isIdField(variableElement))
54 | fieldSqlName = Constants.FIELD_ID;
55 | boolean isPrimivive = ProcessUtils.isPrimitive(variableElement);
56 | enumBuilder.addEnumConstant(ProcessUtils.getObjectName(variableElement), TypeSpec.anonymousClassBuilder("$S, $L", fieldSqlName, isPrimivive)
57 | .build());
58 | }
59 |
60 | return enumBuilder.build();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/generator/ModelEntityProxyGenerator.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.generator;
2 |
3 | import com.squareup.javapoet.ClassName;
4 | import com.squareup.javapoet.MethodSpec;
5 | import com.squareup.javapoet.TypeName;
6 | import com.squareup.javapoet.TypeSpec;
7 |
8 | import javax.lang.model.element.Element;
9 | import javax.lang.model.element.Modifier;
10 |
11 | import com.github.florent37.rxandroidorm.Constants;
12 | import com.github.florent37.rxandroidorm.ProcessUtils;
13 |
14 | /**
15 | * Created by florentchampigny on 26/01/2016.
16 | */
17 | public class ModelEntityProxyGenerator {
18 |
19 | Element element;
20 |
21 | public ModelEntityProxyGenerator(Element element) {
22 | this.element = element;
23 | }
24 |
25 | public static TypeSpec generateModelProxyInterface() {
26 | return TypeSpec.interfaceBuilder(Constants.MODEL_ENTITY_PROXY_INTERFACE)
27 | .addModifiers(Modifier.PUBLIC)
28 | .addMethod(MethodSpec.methodBuilder(Constants.MODEL_ENTITY_PROXY_GET_ID_METHOD)
29 | .returns(TypeName.LONG)
30 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
31 | .build())
32 | .addMethod(MethodSpec.methodBuilder(Constants.MODEL_ENTITY_PROXY_SET_ID_METHOD)
33 | .returns(TypeName.VOID)
34 | .addParameter(TypeName.LONG, "id")
35 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
36 | .build())
37 | .build();
38 | }
39 |
40 | public TypeSpec generate() {
41 | String idFieldName = Constants.FIELD_ID;
42 | Element idField = ProcessUtils.getIdField(element);
43 | if (idField != null)
44 | idFieldName = ProcessUtils.getObjectName(idField);
45 |
46 | TypeSpec.Builder builder = TypeSpec.classBuilder(ProcessUtils.getObjectName(element) + Constants.MODEL_ENTITY_PROXY)
47 | .addModifiers(Modifier.PUBLIC)
48 | .superclass(TypeName.get(element.asType()))
49 | .addSuperinterface(ClassName.get(Constants.DAO_PACKAGE, Constants.MODEL_ENTITY_PROXY_INTERFACE));
50 |
51 | if (idField == null) {
52 | builder.addField(TypeName.LONG, Constants.FIELD_ID);
53 | }
54 |
55 | builder.addMethod(MethodSpec.methodBuilder(Constants.MODEL_ENTITY_PROXY_GET_ID_METHOD)
56 | .addModifiers(Modifier.PUBLIC)
57 | .returns(TypeName.LONG)
58 | .addStatement("return $L", idFieldName)
59 | .build())
60 | .addMethod(MethodSpec.methodBuilder(Constants.MODEL_ENTITY_PROXY_SET_ID_METHOD)
61 | .addModifiers(Modifier.PUBLIC)
62 | .returns(TypeName.VOID)
63 | .addParameter(TypeName.LONG, "id")
64 | .addStatement("this.$L = id", idFieldName)
65 | .build());
66 |
67 | return builder.build();
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/generator/ModelORMInterfaceGenerator.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.generator;
2 |
3 | import com.github.florent37.rxandroidorm.Constants;
4 | import com.github.florent37.rxandroidorm.ProcessUtils;
5 | import com.squareup.javapoet.ClassName;
6 | import com.squareup.javapoet.MethodSpec;
7 | import com.squareup.javapoet.ParameterizedTypeName;
8 | import com.squareup.javapoet.TypeName;
9 | import com.squareup.javapoet.TypeSpec;
10 | import com.squareup.javapoet.TypeVariableName;
11 |
12 | import javax.lang.model.element.Modifier;
13 |
14 | /**
15 | * Created by Thibaud Giovannetti on 09/05/2017.
16 | */
17 | public class ModelORMInterfaceGenerator {
18 |
19 | public ModelORMInterfaceGenerator() {
20 |
21 | }
22 |
23 | public TypeSpec generate() {
24 | final TypeVariableName T = TypeVariableName.get("T");
25 | final TypeName LIST_OF_T = ParameterizedTypeName.get(ClassName.get("java.util", "List"), T);
26 |
27 | final TypeName RETURN_T = ProcessUtils.observableOf(T);
28 | final TypeName RETURN_LIST_T = ProcessUtils.observableOf(LIST_OF_T);
29 |
30 | return TypeSpec.interfaceBuilder(Constants.DATABASE_COMMON_INTERFACE_NAME)
31 | .addModifiers(Modifier.PUBLIC)
32 | .addTypeVariable(T)
33 |
34 |
35 | .addMethod(MethodSpec.methodBuilder("select")
36 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
37 | .returns(Constants.queryBuilderClassName)
38 | .build())
39 |
40 | .addMethod(MethodSpec.methodBuilder("add")
41 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
42 | .addParameter(T, "object", Modifier.FINAL)
43 | .returns(RETURN_T)
44 | .build())
45 |
46 | .addMethod(MethodSpec.methodBuilder("add")
47 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
48 | .addParameter(LIST_OF_T, "objects", Modifier.FINAL)
49 | .returns(RETURN_LIST_T)
50 | .build())
51 |
52 | .addMethod(MethodSpec.methodBuilder("update")
53 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
54 | .addParameter(T, "object", Modifier.FINAL)
55 | .returns(RETURN_T)
56 | .build())
57 |
58 | .addMethod(MethodSpec.methodBuilder("update")
59 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
60 | .addParameter(LIST_OF_T, "objects", Modifier.FINAL)
61 | .returns(RETURN_LIST_T)
62 | .build())
63 |
64 | .addMethod(MethodSpec.methodBuilder("delete")
65 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
66 | .addParameter(T, "object", Modifier.FINAL)
67 | .returns(ProcessUtils.observableOf(TypeName.BOOLEAN.box()))
68 | .build())
69 |
70 | .addMethod(MethodSpec.methodBuilder("delete")
71 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
72 | .addParameter(LIST_OF_T, "objects", Modifier.FINAL)
73 | .returns(ProcessUtils.observableOf(TypeName.BOOLEAN.box()))
74 | .build())
75 |
76 | .addMethod(MethodSpec.methodBuilder("deleteAll")
77 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
78 | .returns(ProcessUtils.observableOf(TypeName.BOOLEAN.box()))
79 | .build())
80 |
81 | .addMethod(MethodSpec.methodBuilder("count")
82 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
83 | .returns(ProcessUtils.observableOf(TypeName.INT.box()))
84 | .build())
85 |
86 | .build();
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/rxandroidorm-compiler/src/main/java/com/github/florent37/rxandroidorm/generator/QueryLoggerGenerator.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.generator;
2 |
3 | import com.squareup.javapoet.ArrayTypeName;
4 | import com.squareup.javapoet.ClassName;
5 | import com.squareup.javapoet.MethodSpec;
6 | import com.squareup.javapoet.TypeSpec;
7 | import com.github.florent37.rxandroidorm.Constants;
8 |
9 | import javax.lang.model.element.Modifier;
10 |
11 | /**
12 | * Created by florentchampigny on 25/01/2016.
13 | */
14 | public class QueryLoggerGenerator {
15 |
16 | public QueryLoggerGenerator() {
17 | }
18 |
19 | public TypeSpec generate() {
20 | return TypeSpec.interfaceBuilder(Constants.QUERY_LOGGER)
21 | .addModifiers(Modifier.PUBLIC)
22 | .addMethod(MethodSpec.methodBuilder("onQuery")
23 | .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
24 | .addParameter(ClassName.get(String.class), "query")
25 | .addParameter(ArrayTypeName.get(String[].class), "datas")
26 | .build())
27 | .build();
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/rxandroidorm/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/rxandroidorm/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion project.COMPILE_SDK
5 | buildToolsVersion project.BUILD_TOOL
6 |
7 | defaultConfig {
8 | minSdkVersion project.minSdkVersion
9 | targetSdkVersion project.TARGET_SDK
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 |
14 | android {
15 | lintOptions {
16 | abortOnError false
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | testCompile 'junit:junit:4.12'
24 |
25 | compile 'io.reactivex.rxjava2:rxjava:2.0.6'
26 | }
27 |
28 | ext {
29 | bintrayRepo = 'maven'
30 | bintrayName = 'rxandroidorm'
31 | orgName = 'florent37'
32 |
33 | publishedGroupId = 'com.github.florent37'
34 | libraryName = 'RxAndroidOrm'
35 | artifact = 'rxandroidorm'
36 |
37 | libraryDescription = 'RxAndroidOrm'
38 |
39 | siteUrl = 'https://github.com/florent37/RxAndroidOrm'
40 | gitUrl = 'https://github.com/florent37/RxAndroidOrm.git'
41 |
42 | libraryVersion = rootProject.ext.libraryVersion
43 |
44 | developerId = 'florent37'
45 | developerName = 'florent37'
46 | developerEmail = 'champigny.florent@gmail.com'
47 |
48 | licenseName = 'The Apache Software License, Version 2.0'
49 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
50 | allLicenses = ["Apache-2.0"]
51 | }
52 |
53 |
54 | apply from: rootProject.file('gradle/install-v1.gradle')
55 | apply from: rootProject.file('gradle/bintray-android-v1.gradle')
56 |
--------------------------------------------------------------------------------
/rxandroidorm/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 /Users/florentchampigny/Android/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 |
--------------------------------------------------------------------------------
/rxandroidorm/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/rxandroidorm/src/main/java/com/github/florent37/rxandroidorm/RxAndroidOrm.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import android.database.SQLException;
6 | import android.database.sqlite.SQLiteDatabase;
7 | import android.database.sqlite.SQLiteOpenHelper;
8 | import android.util.Log;
9 |
10 | import java.lang.reflect.Constructor;
11 | import java.util.concurrent.TimeUnit;
12 | import java.util.concurrent.atomic.AtomicInteger;
13 |
14 | import io.reactivex.Observable;
15 | import io.reactivex.ObservableEmitter;
16 | import io.reactivex.ObservableOnSubscribe;
17 | import io.reactivex.annotations.NonNull;
18 | import io.reactivex.functions.Action;
19 | import io.reactivex.functions.Consumer;
20 |
21 | /**
22 | * Created by florentchampigny on 18/05/2016.
23 | */
24 | public final class RxAndroidOrm {
25 |
26 | private static final String TAG = "RxAndroidOrm";
27 | private static RxAndroidOrm INSTANCE;
28 |
29 | private SQLiteDatabase database;
30 |
31 | private SQLiteOpenHelper helper;
32 | private AtomicInteger usages = new AtomicInteger(0);
33 |
34 | private RxAndroidOrm() {
35 | }
36 |
37 | public static RxAndroidOrm getInstance() {
38 | if (INSTANCE == null) {
39 | INSTANCE = new RxAndroidOrm();
40 | }
41 | return INSTANCE;
42 | }
43 |
44 | public static RxAndroidOrm onDestroy() {
45 | RxAndroidOrm rxAndroidOrm = getInstance();
46 | rxAndroidOrm.close();
47 | return rxAndroidOrm;
48 | }
49 |
50 | public static RxAndroidOrm onCreate(Application application) {
51 | RxAndroidOrm rxAndroidOrm = getInstance();
52 | rxAndroidOrm.helper = rxAndroidOrm.findDatabaseHelper(application);
53 | return rxAndroidOrm;
54 | }
55 |
56 | public SQLiteDatabase getDatabase() {
57 | return database;
58 | }
59 |
60 | public RxAndroidOrm open() throws SQLException {
61 | if (helper != null) {
62 | database = helper.getWritableDatabase();
63 | }
64 | return this;
65 | }
66 |
67 | public RxAndroidOrm close() {
68 | if (helper != null) {
69 | helper.close();
70 | }
71 | return this;
72 | }
73 |
74 | private SQLiteOpenHelper findDatabaseHelper(Application application) {
75 | final String className = "com.github.florent37.rxandroidorm.DatabaseHelper";
76 | try {
77 | Class> clazz = Class.forName(className);
78 | Constructor> constructor = clazz.getConstructor(Context.class);
79 | return (SQLiteOpenHelper) constructor.newInstance(application);
80 | } catch (Exception e) {
81 | Log.e(TAG, "cannot construct RxAndroidOrm", e);
82 | }
83 | return null;
84 | }
85 |
86 | public Observable database() {
87 | return Observable
88 | .create(new ObservableOnSubscribe() {
89 | @Override
90 | public void subscribe(ObservableEmitter e) throws Exception {
91 | usages.incrementAndGet();
92 | SQLiteDatabase database = RxAndroidOrm.getInstance().open().getDatabase();
93 |
94 | e.onNext(database);
95 | e.onComplete();
96 | }
97 | })
98 | .doOnTerminate(new Action() {
99 | @Override
100 | public void run() throws Exception {
101 | Observable.timer(3, TimeUnit.SECONDS)
102 | .subscribe(new Consumer() {
103 | @Override
104 | public void accept(@NonNull Long aLong) throws Exception {
105 | final int count = usages.decrementAndGet();
106 | if(count == 0) {
107 | RxAndroidOrm.getInstance().close();
108 | }
109 | }
110 | });
111 | }
112 | });
113 | }
114 |
115 | }
--------------------------------------------------------------------------------
/rxandroidorm/src/main/java/com/github/florent37/rxandroidorm/migration/ColumnType.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.migration;
2 |
3 | /**
4 | * Created by florentchampigny on 28/01/2016.
5 | */
6 | public class ColumnType {
7 |
8 | public static ModelType ofModel(String objectName) {
9 | return new ModelType(objectName,false);
10 | }
11 |
12 | public static ModelType collectionOfModel(String objectName) {
13 | return new ModelType(objectName,true);
14 | }
15 |
16 | public enum Collection {
17 | ListOfInts("MODEL_INT"),
18 | ListOfFloats("MODEL_FLOAT"),
19 | ListOfBooleans("MODEL_BOOLEAN"),
20 | ListOfStrings("MODEL_STRING");
21 |
22 | private String associationTable;
23 |
24 | Collection(String associationTable) {
25 | this.associationTable = associationTable;
26 | }
27 |
28 | public java.lang.String getAssociationTable() {
29 | return associationTable;
30 | }
31 | }
32 |
33 | public enum Array {
34 | ArrayOfInts("MODEL_INT"),
35 | ArrayOfFloats("MODEL_FLOAT"),
36 | ArrayOfBooleans("MODEL_BOOLEAN"),
37 | ArrayOfStrings("MODEL_STRING");
38 |
39 | private String associationTable;
40 |
41 | Array(String associationTable) {
42 | this.associationTable = associationTable;
43 | }
44 |
45 | public java.lang.String getAssociationTable() {
46 | return associationTable;
47 | }
48 | }
49 |
50 | public enum Primitive {
51 | Int("number"),
52 | Float("real"),
53 | Boolean("number"),
54 | String("text"),
55 | Date("text"),
56 | ;
57 |
58 | private String sqlName;
59 |
60 | Primitive(String sqlName) {
61 | this.sqlName = sqlName;
62 | }
63 |
64 | public java.lang.String getSqlName() {
65 | return sqlName;
66 | }
67 | }
68 |
69 | public static class ModelType {
70 | String objectName;
71 | boolean collection;
72 |
73 | protected ModelType(String objectName, boolean collection) {
74 | this.objectName = objectName;
75 | this.collection = collection;
76 | }
77 |
78 | }
79 |
80 | public static String getSqlName(Object type){
81 | if(type instanceof Primitive)
82 | return ((Primitive)type).getSqlName();
83 | return ""; //TODO
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/rxandroidorm/src/main/java/com/github/florent37/rxandroidorm/migration/DatabaseHelper.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.migration;
2 |
3 | import android.database.Cursor;
4 | import android.database.sqlite.SQLiteDatabase;
5 | import android.text.TextUtils;
6 | import android.util.Log;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | /**
12 | * Created by florentchampigny on 29/01/2016.
13 | */
14 | public class DatabaseHelper {
15 |
16 | protected static final String TAG = "DatabaseHelper";
17 |
18 | SQLiteDatabase database;
19 |
20 | public DatabaseHelper(SQLiteDatabase database) {
21 | this.database = database;
22 | }
23 |
24 | public static String getIdAssociationColumn(String tableName) {
25 | return tableName.toLowerCase() + "_id";
26 | }
27 |
28 | public void executeSql(String sql) {
29 | Log.d(TAG, sql);
30 | database.beginTransaction();
31 | try {
32 | database.execSQL(sql);
33 | database.setTransactionSuccessful();
34 | } catch (Exception e) {
35 | Log.e(TAG, sql, e);
36 | } finally {
37 | database.endTransaction();
38 | }
39 |
40 | }
41 |
42 | public String createTableString(String tableName, List columns) {
43 | StringBuilder stringBuilder = new StringBuilder();
44 | stringBuilder.append("CREATE TABLE ").append(tableName).append("(");
45 |
46 | for (int i = 0, size = columns.size(); i < size; ++i) {
47 | TableColumn tableColumn = columns.get(i);
48 | stringBuilder.append(tableColumn.name).append(" ").append(tableColumn.type);
49 | if (tableColumn.primaryKey)
50 | stringBuilder.append(" PRIMARY KEY");
51 | if (i < size - 1)
52 | stringBuilder.append(",");
53 | }
54 |
55 | stringBuilder.append(");");
56 | return stringBuilder.toString();
57 | }
58 |
59 | public void createTable(String tableName, List columns) {
60 | executeSql(createTableString(tableName, columns));
61 | }
62 |
63 | public void createAssociationTable(String tableNameFrom, String tableNameTo) {
64 | executeSql(createAssociationTableString(tableNameFrom, tableNameTo));
65 | }
66 |
67 | public String createAssociationTableString(String tableNameFrom, String tableNameTo) {
68 | String tableName = tableNameFrom.toUpperCase() + "_" + tableNameTo.toUpperCase();
69 | List columns = new ArrayList<>();
70 |
71 | columns.add(new TableColumn("_id", "number", true));
72 | columns.add(new TableColumn(getIdAssociationColumn(tableNameFrom), "number", false));
73 | columns.add(new TableColumn(getIdAssociationColumn(tableNameTo), "number", false));
74 |
75 | return createTableString(tableName, columns);
76 | }
77 |
78 | public void dropColumn(String tableName, String colToRemove) {
79 | final List updatedTableColumns = getTableColumns(tableName, colToRemove);
80 | final String columnsSeperated = TextUtils.join(",", TableColumn.getNames(updatedTableColumns));
81 |
82 | final String oldTable = tableName + "_old";
83 | renameTable(tableName, oldTable);
84 |
85 | // Creating the table on its new format (no redundant columns)
86 | createTable(tableName, updatedTableColumns);
87 |
88 | // Populating the table with the data
89 | executeSql("INSERT INTO " + tableName + "(" + columnsSeperated + ") SELECT " + columnsSeperated + " FROM " + tableName + "_old;");
90 | dropTable(oldTable);
91 | }
92 |
93 | public void renameColumn(String tableName, String oldName, String newName) {
94 | final List updatedTableColumns = getTableColumns(tableName, null);
95 |
96 | final String oldColumnsSeperated = TextUtils.join(",", TableColumn.getNames(updatedTableColumns));
97 | TableColumn.rename(updatedTableColumns, oldName, newName);
98 | final String newColumnsSeperated = TextUtils.join(",", TableColumn.getNames(updatedTableColumns));
99 |
100 | final String oldTable = tableName + "_old";
101 | renameTable(tableName, oldTable);
102 |
103 | // Creating the table on its new format (no redundant columns)
104 | createTable(tableName, updatedTableColumns);
105 |
106 | // Populating the table with the data
107 | executeSql("INSERT INTO " + tableName + "(" + newColumnsSeperated + ") SELECT " + oldColumnsSeperated + " FROM " + tableName + "_old;");
108 | dropTable(oldTable);
109 | }
110 |
111 | public void addColumn(String tableName, String column, String sqlTypeName) {
112 | executeSql(String.format("ALTER TABLE %s ADD COLUMN %s %s", tableName, column, sqlTypeName));
113 | }
114 |
115 | public void dropTable(String tableName) {
116 | executeSql("DROP TABLE " + tableName + ";");
117 | }
118 |
119 | public void renameTable(String tableName, String newName) {
120 | executeSql("ALTER TABLE " + tableName + " RENAME TO " + newName + ";");
121 | }
122 |
123 | public void renameTableDependencies(String tableName, String newName) {
124 | for (String associationName : getTableNamesLike(tableName)) {
125 | String newAssociationName = associationName.replace(tableName, newName);
126 | renameTable(associationName, newAssociationName);
127 | renameColumn(newAssociationName, getIdAssociationColumn(tableName), getIdAssociationColumn(newName));
128 | }
129 | }
130 |
131 | public List getTableColumns(String tableName, String except) {
132 | List columns = new ArrayList<>();
133 |
134 | Cursor cur = database.rawQuery("pragma table_info(" + tableName + ");", null);
135 |
136 | while (cur.moveToNext()) {
137 | String name = cur.getString(cur.getColumnIndex("name"));
138 | if (except == null || !except.equals(name)) {
139 | String type = cur.getString(cur.getColumnIndex("type"));
140 | boolean primaryKey = cur.getInt(cur.getColumnIndex("pk")) == 1;
141 | columns.add(new TableColumn(name, type, primaryKey));
142 | }
143 | }
144 | cur.close();
145 |
146 | return columns;
147 | }
148 |
149 | public List getTableNamesLike(String tableName) {
150 | List tablesNames = new ArrayList<>();
151 | Cursor cur = database.rawQuery("SELECT name FROM sqlite_master WHERE type = \"table\" AND name like '%" + tableName + "%'", null);
152 |
153 | while (cur.moveToNext()) {
154 | tablesNames.add(cur.getString(0));
155 | }
156 | cur.close();
157 |
158 | return tablesNames;
159 | }
160 |
161 | public static class TableColumn {
162 | String name;
163 | String type;
164 | boolean primaryKey;
165 |
166 | public TableColumn(String name, String type, boolean primaryKey) {
167 | this.name = name;
168 | this.type = type;
169 | this.primaryKey = primaryKey;
170 | }
171 |
172 | public static List getNames(List columns) {
173 | List names = new ArrayList<>();
174 | for (TableColumn tableColumn : columns)
175 | names.add(tableColumn.name);
176 | return names;
177 | }
178 |
179 | public static void rename(List columns, String oldName, String newName) {
180 | for (int i = 0, size = columns.size(); i < size; ++i) {
181 | if (oldName.equals(columns.get(i).name))
182 | columns.get(i).name = newName;
183 | }
184 | }
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/rxandroidorm/src/main/java/com/github/florent37/rxandroidorm/migration/FieldType.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.migration;
2 |
3 | /**
4 | * Created by florentchampigny on 28/01/2016.
5 | */
6 | class FieldType {
7 | static final int TYPE_PRIMITIVE = 0;
8 | static final int TYPE_ARRAY = 1;
9 | static final int TYPE_COLLECTION = 2;
10 | static final int TYPE_CUSTOM = 3;
11 | }
12 |
--------------------------------------------------------------------------------
/rxandroidorm/src/main/java/com/github/florent37/rxandroidorm/migration/Migrator.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.migration;
2 |
3 | import android.database.sqlite.SQLiteDatabase;
4 |
5 | /**
6 | * Created by florentchampigny on 28/01/2016.
7 | */
8 | public class Migrator {
9 |
10 | DatabaseHelper databaseHelper;
11 |
12 | public Migrator(SQLiteDatabase database) {
13 | this.databaseHelper = new DatabaseHelper(database);
14 | }
15 |
16 | public TableCreator createModel(String objectName) {
17 | return new TableCreator(databaseHelper, objectName);
18 | }
19 |
20 | public TableTransformer update(String objectName) {
21 | return new TableTransformer(databaseHelper, objectName);
22 | }
23 |
24 | public Migrator dropAndRecreate(String objectName) {
25 | databaseHelper.dropTable(getTableName(objectName));
26 | createModel(objectName);
27 | return this;
28 | }
29 |
30 | public Migrator remove(String objectName) {
31 | databaseHelper.dropTable(getTableName(objectName));
32 | return this;
33 | }
34 |
35 | public Migrator addTable(TableCreator tableCreator) {
36 | String creationQuery = tableCreator.creationQuery;
37 | databaseHelper.executeSql(creationQuery);
38 | return this;
39 | }
40 |
41 | protected static String getTableName(String objectName) {
42 | return objectName.toUpperCase();
43 | }
44 |
45 | public static class TableTransformer {
46 | DatabaseHelper database;
47 | String objectName;
48 |
49 | public TableTransformer(DatabaseHelper database, String objectName) {
50 | this.database = database;
51 | this.objectName = objectName;
52 | }
53 |
54 | public ColumnTransformer transform(String column) {
55 | return new ColumnTransformer(database, this, objectName, column);
56 | }
57 |
58 | public TableTransformer renameTo(String newName) {
59 | database.renameTable(getTableName(objectName), getTableName(newName));
60 | database.renameTableDependencies(getTableName(objectName), getTableName(newName));
61 | return this;
62 | }
63 |
64 | public TableTransformer removeField(String column) {
65 | database.dropColumn(getTableName(objectName), column);
66 | return this;
67 | }
68 |
69 | public TableTransformer addField(String column, ColumnType.Primitive type) {
70 | database.addColumn(getTableName(objectName), column, type.getSqlName());
71 | return this;
72 | }
73 |
74 | public TableTransformer addField(String column, ColumnType.Array type) {
75 | //nothing to do
76 | return this;
77 | }
78 |
79 | public TableTransformer addField(String column, ColumnType.Collection type) {
80 | //nothing to do
81 | return this;
82 | }
83 |
84 | public TableTransformer addField(String column, ColumnType.ModelType type) {
85 | database.createAssociationTable(objectName, type.objectName);
86 | return this;
87 | }
88 |
89 | }
90 |
91 | public static class ColumnTransformer {
92 | DatabaseHelper database;
93 | TableTransformer tableTransformer;
94 | String columnName;
95 | String objectName;
96 |
97 | public ColumnTransformer(DatabaseHelper database, TableTransformer tableTransformer, String objectName, String columnName) {
98 | this.database = database;
99 | this.tableTransformer = tableTransformer;
100 | this.columnName = columnName;
101 | this.objectName = objectName;
102 | }
103 |
104 | public TableTransformer renameTo(String newName) {
105 | database.renameColumn(getTableName(objectName), columnName, newName);
106 | return tableTransformer;
107 | }
108 |
109 | @Deprecated
110 | public TableTransformer type(ColumnType.Primitive fromType, ColumnType.Primitive newType) {
111 | if (!fromType.equals(newType)) {
112 | //try to transform
113 | }
114 | return tableTransformer;
115 | }
116 |
117 | @Deprecated
118 | public TableTransformer type(ColumnType.Primitive fromType, ColumnType.Array newType) {
119 | tableTransformer.removeField(columnName);
120 | tableTransformer.addField(columnName, newType);
121 | return tableTransformer;
122 | }
123 |
124 | @Deprecated
125 | public TableTransformer type(ColumnType.Primitive fromType, ColumnType.Collection newType) {
126 | tableTransformer.removeField(columnName);
127 | tableTransformer.addField(columnName, newType);
128 | return tableTransformer;
129 | }
130 |
131 | @Deprecated
132 | public TableTransformer type(ColumnType.Array fromType, ColumnType.Collection newType) {
133 | if (!(ColumnType.Array.ArrayOfBooleans.equals(fromType) && ColumnType.Collection.ListOfBooleans.equals(newType)) &&
134 | !(ColumnType.Array.ArrayOfStrings.equals(fromType) && ColumnType.Collection.ListOfStrings.equals(newType)) &&
135 | !(ColumnType.Array.ArrayOfInts.equals(fromType) && ColumnType.Collection.ListOfInts.equals(newType)) &&
136 | !(ColumnType.Array.ArrayOfFloats.equals(fromType) && ColumnType.Collection.ListOfFloats.equals(newType))) {
137 | //try to transform
138 | }
139 | //else nothing to do
140 | return tableTransformer;
141 | }
142 |
143 | @Deprecated
144 | public TableTransformer type(ColumnType.Collection fromType, ColumnType.Array newType) {
145 | if (!(ColumnType.Array.ArrayOfBooleans.equals(newType) && ColumnType.Collection.ListOfBooleans.equals(fromType)) &&
146 | !(ColumnType.Array.ArrayOfStrings.equals(newType) && ColumnType.Collection.ListOfStrings.equals(fromType)) &&
147 | !(ColumnType.Array.ArrayOfInts.equals(newType) && ColumnType.Collection.ListOfInts.equals(fromType)) &&
148 | !(ColumnType.Array.ArrayOfFloats.equals(newType) && ColumnType.Collection.ListOfFloats.equals(fromType))) {
149 | //try to transform
150 | }
151 | //else nothing to do
152 | return tableTransformer;
153 | }
154 |
155 | public TableTransformer type(ColumnType.Primitive fromType, ColumnType.ModelType newType) {
156 | tableTransformer.removeField(columnName);
157 | tableTransformer.addField(columnName, newType);
158 | return tableTransformer;
159 | }
160 |
161 | public TableTransformer type(ColumnType.Collection fromType, ColumnType.ModelType newType) {
162 | tableTransformer.removeField(columnName);
163 | tableTransformer.addField(columnName, newType);
164 | return tableTransformer;
165 | }
166 |
167 | public TableTransformer type(ColumnType.Array fromType, ColumnType.ModelType newType) {
168 | tableTransformer.removeField(columnName);
169 | tableTransformer.addField(columnName, newType);
170 | return tableTransformer;
171 | }
172 |
173 | public TableTransformer type(ColumnType.ModelType fromType, ColumnType.ModelType newType) {
174 | tableTransformer.removeField(columnName);
175 | tableTransformer.addField(columnName, newType);
176 | return tableTransformer;
177 | }
178 | }
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/rxandroidorm/src/main/java/com/github/florent37/rxandroidorm/migration/TableCreator.java:
--------------------------------------------------------------------------------
1 | package com.github.florent37.rxandroidorm.migration;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * Created by florentchampigny on 29/01/2016.
8 | */
9 | public class TableCreator {
10 | DatabaseHelper database;
11 | String objectName;
12 | String creationQuery;
13 |
14 | List fieldList = new ArrayList<>();
15 |
16 | public TableCreator(DatabaseHelper database, String objectName) {
17 | this.database = database;
18 | this.objectName = objectName;
19 | }
20 |
21 | public TableCreator field(String name, ColumnType.Primitive type) {
22 | fieldList.add(new Field(name,type));
23 | return this;
24 | }
25 |
26 | @Deprecated
27 | public TableCreator field(String name, ColumnType.Array type) {
28 | //TODO
29 | return this;
30 | }
31 |
32 | @Deprecated
33 | public TableCreator field(String name, ColumnType.Collection type) {
34 | //TODO
35 | return this;
36 | }
37 |
38 | @Deprecated
39 | public TableCreator field(String name, ColumnType.ModelType type) {
40 | //TODO
41 | return this;
42 | }
43 |
44 | public TableCreator build(){
45 | String tableName = objectName.toUpperCase();
46 |
47 | StringBuilder query = new StringBuilder();
48 | query.append("CREATE TABLE ").append(tableName).append("(")
49 | .append("_id number PRIMARY KEY");
50 |
51 | for(int i=0, size=fieldList.size();i