Full Code of guolindev/LitePal for AI

master 8ad8322cc6f8 cached
223 files
1.1 MB
272.3k tokens
1212 symbols
1 requests
Download .txt
Showing preview only (1,182K chars total). Download the full file or copy to clipboard to get everything.
Repository: guolindev/LitePal
Branch: master
Commit: 8ad8322cc6f8
Files: 223
Total size: 1.1 MB

Directory structure:
gitextract__kl11lqh/

├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── core/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── org/
│           │       └── litepal/
│           │           ├── FluentQuery.java
│           │           ├── LitePal.kt
│           │           ├── LitePalApplication.java
│           │           ├── LitePalBase.java
│           │           ├── LitePalDB.java
│           │           ├── Operator.java
│           │           ├── annotation/
│           │           │   ├── Column.java
│           │           │   └── Encrypt.java
│           │           ├── crud/
│           │           │   ├── AssociationsAnalyzer.java
│           │           │   ├── DataHandler.java
│           │           │   ├── DeleteHandler.java
│           │           │   ├── DynamicExecutor.java
│           │           │   ├── LitePalSupport.java
│           │           │   ├── Many2ManyAnalyzer.java
│           │           │   ├── Many2OneAnalyzer.java
│           │           │   ├── One2OneAnalyzer.java
│           │           │   ├── QueryHandler.java
│           │           │   ├── SaveHandler.java
│           │           │   ├── UpdateHandler.java
│           │           │   ├── async/
│           │           │   │   ├── AsyncExecutor.java
│           │           │   │   ├── AverageExecutor.java
│           │           │   │   ├── CountExecutor.java
│           │           │   │   ├── FindExecutor.java
│           │           │   │   ├── FindMultiExecutor.java
│           │           │   │   ├── SaveExecutor.java
│           │           │   │   └── UpdateOrDeleteExecutor.java
│           │           │   ├── callback/
│           │           │   │   ├── AverageCallback.java
│           │           │   │   ├── CountCallback.java
│           │           │   │   ├── FindCallback.java
│           │           │   │   ├── FindMultiCallback.java
│           │           │   │   ├── SaveCallback.java
│           │           │   │   └── UpdateOrDeleteCallback.java
│           │           │   └── model/
│           │           │       └── AssociationsInfo.java
│           │           ├── exceptions/
│           │           │   ├── DataSupportException.java
│           │           │   ├── DatabaseGenerateException.java
│           │           │   ├── GlobalException.java
│           │           │   ├── InvalidAttributesException.java
│           │           │   ├── LitePalSupportException.java
│           │           │   └── ParseConfigurationFileException.java
│           │           ├── extension/
│           │           │   ├── FluentQuery.kt
│           │           │   └── LitePal.kt
│           │           ├── model/
│           │           │   └── Table_Schema.java
│           │           ├── parser/
│           │           │   ├── LitePalAttr.java
│           │           │   ├── LitePalConfig.java
│           │           │   ├── LitePalContentHandler.java
│           │           │   └── LitePalParser.java
│           │           ├── tablemanager/
│           │           │   ├── AssociationCreator.java
│           │           │   ├── AssociationUpdater.java
│           │           │   ├── Connector.java
│           │           │   ├── Creator.java
│           │           │   ├── Dropper.java
│           │           │   ├── Generator.java
│           │           │   ├── LitePalOpenHelper.java
│           │           │   ├── Upgrader.java
│           │           │   ├── callback/
│           │           │   │   └── DatabaseListener.java
│           │           │   ├── model/
│           │           │   │   ├── AssociationsModel.java
│           │           │   │   ├── ColumnModel.java
│           │           │   │   ├── GenericModel.java
│           │           │   │   └── TableModel.java
│           │           │   └── typechange/
│           │           │       ├── BlobOrm.java
│           │           │       ├── BooleanOrm.java
│           │           │       ├── DateOrm.java
│           │           │       ├── DecimalOrm.java
│           │           │       ├── NumericOrm.java
│           │           │       ├── OrmChange.java
│           │           │       └── TextOrm.java
│           │           └── util/
│           │               ├── BaseUtility.java
│           │               ├── Const.java
│           │               ├── DBUtility.java
│           │               ├── LitePalLog.java
│           │               ├── SharedUtil.java
│           │               └── cipher/
│           │                   ├── AESCrypt.java
│           │                   └── CipherUtil.java
│           └── res/
│               └── values/
│                   └── strings.xml
├── downloads/
│   ├── litepal-1.1.0-src.jar
│   ├── litepal-1.1.0.jar
│   ├── litepal-1.1.1-src.jar
│   ├── litepal-1.1.1.jar
│   ├── litepal-1.2.0-src.jar
│   ├── litepal-1.2.0.jar
│   ├── litepal-1.2.1-src.jar
│   ├── litepal-1.2.1.jar
│   ├── litepal-1.3.0-src.jar
│   ├── litepal-1.3.0.jar
│   ├── litepal-1.3.1-src.jar
│   ├── litepal-1.3.1.jar
│   ├── litepal-1.3.2-src.jar
│   ├── litepal-1.3.2.jar
│   ├── litepal-1.4.0-src.jar
│   ├── litepal-1.4.0.jar
│   ├── litepal-1.4.1-src.jar
│   ├── litepal-1.4.1.jar
│   ├── litepal-1.5.1-src.jar
│   ├── litepal-1.5.1.jar
│   ├── litepal-1.6.0-src.jar
│   ├── litepal-1.6.0.jar
│   ├── litepal-1.6.1-src.jar
│   ├── litepal-1.6.1.jar
│   ├── litepal-2.0.0-src.jar
│   └── litepal-2.0.0.jar
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── java/
│   ├── .gitignore
│   ├── bintray.gradle
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── org/
│           │       └── litepal/
│           │           └── LitePal.java
│           └── res/
│               └── values/
│                   └── strings.xml
├── kotlin/
│   ├── .gitignore
│   ├── bintray.gradle
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── org/
│           │       └── litepal/
│           │           ├── LitePal.kt
│           │           └── extension/
│           │               ├── FluentQuery.kt
│           │               └── LitePal.kt
│           └── res/
│               └── values/
│                   └── strings.xml
├── sample/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── litepaltest/
│       │               ├── model/
│       │               │   ├── Book.java
│       │               │   ├── Cellphone.java
│       │               │   ├── Classroom.java
│       │               │   ├── Computer.java
│       │               │   ├── Headset.java
│       │               │   ├── IdCard.java
│       │               │   ├── Message.java
│       │               │   ├── Product.java
│       │               │   ├── Student.java
│       │               │   ├── Teacher.java
│       │               │   ├── WeChatMessage.java
│       │               │   └── WeiboMessage.java
│       │               └── test/
│       │                   ├── LitePalTestCase.java
│       │                   ├── MultiDatabaseTest.java
│       │                   ├── annotation/
│       │                   │   └── ColumnTest.java
│       │                   ├── crud/
│       │                   │   ├── delete/
│       │                   │   │   ├── DeleteKotlinTest.kt
│       │                   │   │   └── DeleteTest.java
│       │                   │   ├── query/
│       │                   │   │   ├── QueryBasicKotlinTest.kt
│       │                   │   │   ├── QueryBasicTest.java
│       │                   │   │   ├── QueryBySQLTest.java
│       │                   │   │   ├── QueryClusterKotlinTest.kt
│       │                   │   │   ├── QueryClusterTest.java
│       │                   │   │   ├── QueryDateTest.java
│       │                   │   │   ├── QueryEagerKotlinTest.kt
│       │                   │   │   ├── QueryEagerTest.java
│       │                   │   │   ├── QueryMathKotlinTest.kt
│       │                   │   │   └── QueryMathTest.java
│       │                   │   ├── save/
│       │                   │   │   ├── Many2ManySaveTest.java
│       │                   │   │   ├── Many2OneBiSaveTest.java
│       │                   │   │   ├── Many2OneUniSaveTest.java
│       │                   │   │   ├── One2OneBiSaveTest.java
│       │                   │   │   ├── One2OneUniSaveTest.java
│       │                   │   │   ├── SaveAllKotlinTest.kt
│       │                   │   │   ├── SaveAllTest.java
│       │                   │   │   └── SaveTest.java
│       │                   │   ├── transaction/
│       │                   │   │   ├── TransactionKotlinTest.kt
│       │                   │   │   └── TransactionTest.java
│       │                   │   └── update/
│       │                   │       ├── UpdateUsingSaveMethodTest.java
│       │                   │       ├── UpdateUsingUpdateMethodKotlinTest.kt
│       │                   │       └── UpdateUsingUpdateMethodTest.java
│       │                   └── util/
│       │                       ├── BaseUtilityTest.java
│       │                       └── DBUtilityTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── assets/
│           │   └── litepal.xml
│           ├── java/
│           │   └── org/
│           │       └── litepal/
│           │           └── litepalsample/
│           │               ├── MyApplication.java
│           │               ├── activity/
│           │               │   ├── AggregateActivity.java
│           │               │   ├── AverageSampleActivity.java
│           │               │   ├── CRUDActivity.java
│           │               │   ├── CountSampleActivity.java
│           │               │   ├── DeleteSampleActivity.java
│           │               │   ├── MainActivity.java
│           │               │   ├── ManageTablesActivity.java
│           │               │   ├── MaxSampleActivity.java
│           │               │   ├── MinSampleActivity.java
│           │               │   ├── ModelListActivity.java
│           │               │   ├── ModelStructureActivity.java
│           │               │   ├── QuerySampleActivity.java
│           │               │   ├── SaveSampleActivity.java
│           │               │   ├── SumSampleActivity.java
│           │               │   ├── TableListActivity.java
│           │               │   ├── TableStructureActivity.java
│           │               │   └── UpdateSampleActivity.java
│           │               ├── adapter/
│           │               │   ├── DataArrayAdapter.java
│           │               │   └── StringArrayAdapter.java
│           │               ├── model/
│           │               │   ├── Album.java
│           │               │   ├── Singer.java
│           │               │   └── Song.java
│           │               └── util/
│           │                   └── Utility.java
│           └── res/
│               ├── layout/
│               │   ├── aggregate_layout.xml
│               │   ├── average_sample_layout.xml
│               │   ├── count_sample_layout.xml
│               │   ├── crud_layout.xml
│               │   ├── delete_sample_layout.xml
│               │   ├── main_layout.xml
│               │   ├── manage_tables_layout.xml
│               │   ├── max_sample_layout.xml
│               │   ├── min_sample_layout.xml
│               │   ├── model_list_layout.xml
│               │   ├── model_structure_item.xml
│               │   ├── model_structure_layout.xml
│               │   ├── query_sample_layout.xml
│               │   ├── save_sample_layout.xml
│               │   ├── simple_list_item.xml
│               │   ├── sum_sample_layout.xml
│               │   ├── table_list_layout.xml
│               │   ├── table_structure_item.xml
│               │   ├── table_structure_layout.xml
│               │   └── update_sample_layout.xml
│               └── values/
│                   ├── dimens.xml
│                   ├── strings.xml
│                   └── styles.xml
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.gradle
gradle.properties
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
bin
tmp
gen

#################
## #IntelliJ IDEA
#################
.idea
*.iml
*.ipr
*.iws
out

#################
## Eclipse
#################

*.pydevproject
.metadata
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
*.classpath
*.project
README.md~

/releaseToBintray.txt


================================================
FILE: LICENSE
================================================
Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright {yyyy} {name of copyright owner}

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.



================================================
FILE: README.md
================================================
# LitePal for Android  
![Logo](https://github.com/LitePalFramework/LitePal/blob/master/sample/src/main/logo/mini_logo.png) 

[中文文档](https://blog.csdn.net/sinyu890807/category_9262963.html)

LitePal is an open source Android library that allows developers to use SQLite database extremely easy. You can finish most of the database operations without writing even a SQL statement, including create or upgrade tables, crud operations, aggregate functions, etc. The setup of LitePal is quite simple as well, you can integrate it into your project in less than 5 minutes. 

Experience the magic right now and have fun!

## Features
 * Using object-relational mapping (ORM) pattern.
 * Almost zero-configuration(only one configuration file with few properties).
 * Maintains all tables automatically(e.g. create, alter or drop tables).
 * Multi databases supported.
 * Encapsulated APIs for avoiding writing SQL statements.
 * Awesome fluent query API.
 * Alternative choice to use SQL still, but easier and better APIs than the originals.
 * More for you to explore.

## Quick Setup
#### 1. Include library

Edit your **build.gradle** file and add below dependency.

``` groovy
dependencies {
    implementation 'org.litepal.guolindev:core:3.2.3'
}
```

#### 2. Configure litepal.xml
Create a file in the **assets** folder of your project and name it as **litepal.xml**. Then copy the following codes into it.
``` xml
<?xml version="1.0" encoding="utf-8"?>
<litepal>
    <!--
    	Define the database name of your application. 
    	By default each database name should be end with .db. 
    	If you didn't name your database end with .db, 
    	LitePal would plus the suffix automatically for you.
    	For example:    
    	<dbname value="demo" />
    -->
    <dbname value="demo" />

    <!--
    	Define the version of your database. Each time you want 
    	to upgrade your database, the version tag would helps.
    	Modify the models you defined in the mapping tag, and just 
    	make the version value plus one, the upgrade of database
    	will be processed automatically without concern.
			For example:    
    	<version value="1" />
    -->
    <version value="1" />

    <!--
    	Define your models in the list with mapping tag, LitePal will
    	create tables for each mapping class. The supported fields
    	defined in models will be mapped into columns.
    	For example:    
    	<list>
    		<mapping class="com.test.model.Reader" />
    		<mapping class="com.test.model.Magazine" />
    	</list>
    -->
    <list>
    </list>
    
    <!--
        Define where the .db file should be. "internal" means the .db file
        will be stored in the database folder of internal storage which no
        one can access. "external" means the .db file will be stored in the
        path to the directory on the primary external storage device where
        the application can place persistent files it owns which everyone
        can access. "internal" will act as default.
        For example:
        <storage value="external" />
    -->
    
</litepal>
```
This is the only configuration file, and the properties are simple. 
 * **dbname** configure the database name of project.
 * **version** configure the version of database. Each time you want to upgrade database, plus the value here.
 * **list** configure the mapping classes.
 * **storage** configure where the database file should be stored. **internal** and **external** are the only valid options.
 
#### 3. Configure LitePalApplication
You don't want to pass the Context param all the time. To makes the APIs simple, just configure the LitePalApplication in **AndroidManifest.xml** as below:
``` xml
<manifest>
    <application
        android:name="org.litepal.LitePalApplication"
        ...
    >
        ...
    </application>
</manifest>
```
Of course you may have your own Application and has already configured here, like:
``` xml
<manifest>
    <application
        android:name="com.example.MyOwnApplication"
        ...
    >
        ...
    </application>
</manifest>
```
That's OK. LitePal can still live with that. Just call **LitePal.initialize(context)** in your own Application:
```java
public class MyOwnApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        LitePal.initialize(this);
    }
    ...
}
```
Make sure to call this method as early as you can. In the **onCreate()** method of Application will be fine. And always remember to use the application context as parameter. Do not use any instance of activity or service as parameter, or memory leaks might happen.
## Get Started
After setup, you can experience the powerful functions now.

#### 1. Create tables
Define the models first. For example you have two models, **Album** and **Song**. The models can be defined as below:
``` java
public class Album extends LitePalSupport {
	
    @Column(unique = true, defaultValue = "unknown")
    private String name;
    
    @Column(index = true)
    private float price;
	
    private List<Song> songs = new ArrayList<>();

    // generated getters and setters.
    ...
}
```
``` java
public class Song extends LitePalSupport {
	
    @Column(nullable = false)
    private String name;
	
    private int duration;
	
    @Column(ignore = true)
    private String uselessField;
	
    private Album album;

    // generated getters and setters.
    ...
}
```
Then add these models into the mapping list in **litepal.xml**:
``` xml
<list>
    <mapping class="org.litepal.litepalsample.model.Album" />
    <mapping class="org.litepal.litepalsample.model.Song" />
</list>
```
OK! The tables will be generated next time you operate database. For example, gets the **SQLiteDatabase** with following codes:
``` java
SQLiteDatabase db = LitePal.getDatabase();
```
Now the tables will be generated automatically with SQLs like this:
``` sql
CREATE TABLE album (
	id integer primary key autoincrement,
	name text unique default 'unknown',
	price real
);

CREATE TABLE song (
	id integer primary key autoincrement,
	name text not null,
	duration integer,
	album_id integer
);
```

#### 2. Upgrade tables
Upgrade tables in LitePal is extremely easy. Just modify your models anyway you want:
```java
public class Album extends LitePalSupport {
	
    @Column(unique = true, defaultValue = "unknown")
    private String name;
	
    @Column(ignore = true)
    private float price;
	
    private Date releaseDate;
	
    private List<Song> songs = new ArrayList<>();

    // generated getters and setters.
    ...
}
```
A **releaseDate** field was added and **price** field was annotated to ignore.
Then increase the version number in **litepal.xml**:
```xml
<!--
    Define the version of your database. Each time you want 
    to upgrade your database, the version tag would helps.
    Modify the models you defined in the mapping tag, and just 
    make the version value plus one, the upgrade of database
    will be processed automatically without concern.
    For example:    
    <version value="1" />
-->
<version value="2" />
```
The tables will be upgraded next time you operate database. A **releasedate** column will be added into **album** table and the original **price** column will be removed. All the data in **album** table except those removed columns will be retained.

But there are some upgrading conditions that LitePal can't handle and all data in the upgrading table will be cleaned:
 * Add a field which annotated as `unique = true`.
 * Change a field's annotation into `unique = true`.
 * Change a field's annotation into `nullable = false`.

Be careful of the above conditions which will cause losing data.

#### 3. Save data
The saving API is quite object oriented. Each model which inherits from **LitePalSupport** would have the **save()** method for free.

Java:
``` java
Album album = new Album();
album.setName("album");
album.setPrice(10.99f);
album.setCover(getCoverImageBytes());
album.save();
Song song1 = new Song();
song1.setName("song1");
song1.setDuration(320);
song1.setAlbum(album);
song1.save();
Song song2 = new Song();
song2.setName("song2");
song2.setDuration(356);
song2.setAlbum(album);
song2.save();
```

Kotlin:
```kotlin
val album = Album()
album.name = "album"
album.price = 10.99f
album.cover = getCoverImageBytes()
album.save()
val song1 = Song()
song1.name = "song1"
song1.duration = 320
song1.album = album
song1.save()
val song2 = Song()
song2.name = "song2"
song2.duration = 356
song2.album = album
song2.save()
```
This will insert album, song1 and song2 into database with associations.

#### 4. Update data
The simplest way, use **save()** method to update a record found by **find()**.

Java:
``` java
Album albumToUpdate = LitePal.find(Album.class, 1);
albumToUpdate.setPrice(20.99f); // raise the price
albumToUpdate.save();
```

Kotlin:
```kotlin
val albumToUpdate = LitePal.find<Album>(1)
albumToUpdate.price = 20.99f // raise the price
albumToUpdate.save()
```

Each model which inherits from **LitePalSupport** would also have **update()** and **updateAll()** method. You can update a single record with a specified id.

Java:
``` java
Album albumToUpdate = new Album();
albumToUpdate.setPrice(20.99f); // raise the price
albumToUpdate.update(id);
```

Kotlin:
```kotlin
val albumToUpdate = Album()
albumToUpdate.price = 20.99f // raise the price
albumToUpdate.update(id)
```

Or you can update multiple records with a where condition.

Java:
``` java
Album albumToUpdate = new Album();
albumToUpdate.setPrice(20.99f); // raise the price
albumToUpdate.updateAll("name = ?", "album");
```

Kotlin:
```kotlin
val albumToUpdate = Album()
albumToUpdate.price = 20.99f // raise the price
albumToUpdate.updateAll("name = ?", "album")
```

#### 5. Delete data
You can delete a single record using the static **delete()** method in **LitePal**.

Java:
``` java
LitePal.delete(Song.class, id);
```

Kotlin:
```kotlin
LitePal.delete<Song>(id)
```

Or delete multiple records using the static **deleteAll()** method in **LitePal**.

Java:
``` java
LitePal.deleteAll(Song.class, "duration > ?" , "350");
```

Kotlin:
```kotlin
LitePal.deleteAll<Song>("duration > ?" , "350")
```

#### 6. Query data
Find a single record from song table with specified id.

Java:
``` java
Song song = LitePal.find(Song.class, id);
```

Kotlin:
```kotlin
val song = LitePal.find<Song>(id)
```

Find all records from song table.

Java:
``` java
List<Song> allSongs = LitePal.findAll(Song.class);
```

Kotlin:
```kotlin
val allSongs = LitePal.findAll<Song>()
```

Constructing complex query with fluent query.

Java:
``` java
List<Song> songs = LitePal.where("name like ? and duration < ?", "song%", "200").order("duration").find(Song.class);
```

Kotlin:
``` kotlin
val songs = LitePal.where("name like ? and duration < ?", "song%", "200").order("duration").find<Song>()
```

#### 7. Multiple databases
If your app needs multiple databases, LitePal support it completely. You can create as many databases as you want at runtime. For example:
```java
LitePalDB litePalDB = new LitePalDB("demo2", 1);
litePalDB.addClassName(Singer.class.getName());
litePalDB.addClassName(Album.class.getName());
litePalDB.addClassName(Song.class.getName());
LitePal.use(litePalDB);
```
This will create a **demo2** database with **singer**, **album** and **song** tables.

If you just want to create a new database but with same configuration as **litepal.xml**, you can do it with:
```java
LitePalDB litePalDB = LitePalDB.fromDefault("newdb");
LitePal.use(litePalDB);
```
You can always switch back to default database with:
```java
LitePal.useDefault();
```
And you can delete any database by specified database name:
```java
LitePal.deleteDatabase("newdb");
```

#### 8. Transaction
LitePal support transaction for atomic db operations. All operations in the transaction will be committed or rolled back together.

Java usage:
```java
LitePal.beginTransaction();
boolean result1 = // db operation1
boolean result2 = // db operation2
boolean result3 = // db operation3
if (result1 && result2 && result3) {
    LitePal.setTransactionSuccessful();
}
LitePal.endTransaction();
```

Kotlin usage:
```kotlin
LitePal.runInTransaction {
    val result1 = // db operation1
    val result2 = // db operation2
    val result3 = // db operation3
    result1 && result2 && result3
}
```

## ProGuard
If you are using ProGuard you might need to add the following option:

```proguard
-keep class org.litepal.** {*;}
-keep class * extends org.litepal.crud.LitePalSupport {*;}
```

## Bugs Report
If you find any bug when using LitePal, please report **[here](https://github.com/LitePalFramework/LitePal/issues/new)**. Thanks for helping us making better.

## Change logs

### 3.2.3
 * Support database index by adding @Column(index = true) on field.
 * Adding return value for **runInTransaction()** function for Kotlin.
 * Fix known bugs.

### 3.1.1
 * Support transaction.
 * Add return value for **LitePal.saveAll()** method.
 * No longer support byte array field as column in table.
 * Deprecate all async methods. You should handle async operations by yourself.
 * Fix known bugs.
 
### 3.0.0
 * Optimize generic usage for async operation APIs.
 * Add **LitePal.registerDatabaseListener()** method for listening create or upgrade database events.
 * Provider better CRUD API usage for using generic declaration instead of Class parameter for kotlin.
 * Fix known bugs.

### 2.0.0
 * Offer new APIs for CRUD operations. Deprecate **DataSupport**, use **LitePal** and **LitePalSupport** instead.
 * Fully support kotlin programming.
 * Fix known bugs.

### 1.6.1
 * Support AES and MD5 encryption with @Encrypt annotation on fields.
 * Support to store database file on any directory of external storage.
 * Fix known bugs.

### 1.5.1
 * Support async operations for all crud methods.
 * Add **saveOrUpdate()** method in DataSupport.
 * Fix known bugs.

### 1.4.1
 * Support multiple databases.
 * Support crud operations for generic collection data in models.
 * Add SQLite keywords convert function to avoid keywords conflict.
 * Fix bug of DateSupport.count error.
 * Fix bug of losing blob data when upgrading database.
 * Fix other known bugs.
 
### 1.3.2
 * Improve an outstanding speed up of querying and saving.
 * Support to store database file in external storage.
 * Support to mapping fields which inherit from superclass.
 * Add **findFirst()** and **findLast()** in fluent query.
 * Add **isExist()** and **saveIfNotExist()** method in DataSupport.

### 1.3.1
 * Support storing binary data. Byte array field will be mapped into database as blob type.
 * Add **saveFast()** method in DataSupport. If your model has no associations to handle, use **saveFast()** method will be much more efficient.
 * Improve query speed with optimized algorithm.
 
### 1.3.0
 * Add annotation functions to declare **unique**, **not null** and **default** constraints.
 * Remove the trick of ignore mapping fields with non-private modifier.
 * Support to use annotation to ignore mapping fields with `ignore = true`
 * Add some magical methods in DataSupport for those who understand LitePal deeper.
 * Fix known bugs.
 
## License
```
Copyright (C) Lin Guo, LitePal Framework Open Source Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```


================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext.kotlin_version = '1.5.21'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.0.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

================================================
FILE: core/.gitignore
================================================
/build


================================================
FILE: core/build.gradle
================================================
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion 31

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 31
        archivesBaseName = "core"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    lintOptions {
        abortOnError false
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    api fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

================================================
FILE: core/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/tony/Android/Sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}


================================================
FILE: core/src/main/AndroidManifest.xml
================================================
<manifest package="org.litepal">

    <application>

    </application>

</manifest>


================================================
FILE: core/src/main/java/org/litepal/FluentQuery.java
================================================
/*
 * Copyright (C)  Tony Green, LitePal Framework Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.litepal;

import android.text.TextUtils;

import org.litepal.crud.LitePalSupport;
import org.litepal.crud.QueryHandler;
import org.litepal.crud.async.AverageExecutor;
import org.litepal.crud.async.CountExecutor;
import org.litepal.crud.async.FindExecutor;
import org.litepal.crud.async.FindMultiExecutor;
import org.litepal.exceptions.LitePalSupportException;
import org.litepal.tablemanager.Connector;
import org.litepal.util.BaseUtility;
import org.litepal.util.DBUtility;

import java.util.List;

/**
 * Allows developers to query tables with fluent style.
 *
 * @author Tony Green
 * @since 2.0
 */
public class FluentQuery {

	/**
	 * Representing the selected columns in SQL.
	 */
	String[] mColumns;

	/**
	 * Representing the where clause in SQL.
	 */
	String[] mConditions;

	/**
	 * Representing the order by clause in SQL.
	 */
	String mOrderBy;

	/**
	 * Representing the limit clause in SQL.
	 */
	String mLimit;

	/**
	 * Representing the offset in SQL.
	 */
	String mOffset;

	/**
	 * Do not allow to create instance by developers.
	 */
	FluentQuery() {
	}

	/**
	 * Declaring to query which columns in table.
	 *
	 * <pre>
	 * LitePal.select(&quot;name&quot;, &quot;age&quot;).find(Person.class);
	 * </pre>
	 *
	 * This will find all rows with name and age columns in Person table.
	 *
	 * @param columns
	 *            A String array of which columns to return. Passing null will
	 *            return all columns.
	 *
	 * @return A ClusterQuery instance.
	 */
	public FluentQuery select(String... columns) {
        mColumns = columns;
        return this;
	}

	/**
	 * Declaring to query which rows in table.
	 *
	 * <pre>
	 * LitePal.where(&quot;name = ? or age &gt; ?&quot;, &quot;Tom&quot;, &quot;14&quot;).find(Person.class);
	 * </pre>
	 *
	 * This will find rows which name is Tom or age greater than 14 in Person
	 * table.
	 *
	 * @param conditions
	 *            A filter declaring which rows to return, formatted as an SQL
	 *            WHERE clause. Passing null will return all rows.
	 * @return A ClusterQuery instance.
	 */
	public FluentQuery where(String... conditions) {
        mConditions = conditions;
        return this;
	}

	/**
	 * Declaring how to order the rows queried from table.
	 *
	 * <pre>
	 * LitePal.order(&quot;name desc&quot;).find(Person.class);
	 * </pre>
	 *
	 * This will find all rows in Person table sorted by name with inverted
	 * order.
	 *
	 * @param column
	 *            How to order the rows, formatted as an SQL ORDER BY clause.
	 *            Passing null will use the default sort order, which may be
	 *            unordered.
	 * @return A ClusterQuery instance.
	 */
	public FluentQuery order(String column) {
        mOrderBy = column;
        return this;
	}

	/**
	 * Limits the number of rows returned by the query.
	 *
	 * <pre>
	 * LitePal.limit(2).find(Person.class);
	 * </pre>
	 *
	 * This will find the top 2 rows in Person table.
	 *
	 * @param value
	 *            Limits the number of rows returned by the query, formatted as
	 *            LIMIT clause.
	 * @return A ClusterQuery instance.
	 */
	public FluentQuery limit(int value) {
        mLimit = String.valueOf(value);
        return this;
	}

	/**
	 * Declaring the offset of rows returned by the query. This method must be
	 * used with {@link #limit(int)}, or nothing will return.
	 *
	 * <pre>
	 * LitePal.limit(1).offset(2).find(Person.class);
	 * </pre>
	 *
	 * This will find the third row in Person table.
	 *
	 * @param value
	 *            The offset amount of rows returned by the query.
	 * @return A ClusterQuery instance.
	 */
	public FluentQuery offset(int value) {
        mOffset = String.valueOf(value);
        return this;
	}

	/**
	 * Finds multiple records by the cluster parameters. You can use the below
	 * way to finish a complicated query:
	 *
	 * <pre>
	 * LitePal.select(&quot;name&quot;).where(&quot;age &gt; ?&quot;, &quot;14&quot;).order(&quot;age&quot;).limit(1).offset(2)
	 * 		.find(Person.class);
	 * </pre>
	 *
	 * You can also do the same job with SQLiteDatabase like this:
	 *
	 * <pre>
	 * getSQLiteDatabase().query(&quot;Person&quot;, &quot;name&quot;, &quot;age &gt; ?&quot;, new String[] { &quot;14&quot; }, null, null, &quot;age&quot;,
	 * 		&quot;2,1&quot;);
	 * </pre>
	 *
	 * Obviously, the first way is much more semantic.<br>
	 * Note that the associated models won't be loaded by default considering
	 * the efficiency, but you can do that by using
	 * {@link FluentQuery#find(Class, boolean)}.
	 *
	 * @param modelClass
	 *            Which table to query and the object type to return as a list.
	 * @return An object list with founded data from database, or an empty list.
	 */
	public <T> List<T> find(Class<T> modelClass) {
        return find(modelClass, false);
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindMultiExecutor<T> findAsync(final Class<T> modelClass) {
        return findAsync(modelClass, false);
    }

	/**
	 * It is mostly same as {@link FluentQuery#find(Class)} but an isEager
	 * parameter. If set true the associated models will be loaded as well.
     * <br>
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
	 *
	 * @param modelClass
	 *            Which table to query and the object type to return as a list.
	 * @param isEager
	 *            True to load the associated models, false not.
	 * @return An object list with founded data from database, or an empty list.
	 */
	public <T> List<T> find(Class<T> modelClass, boolean isEager) {
        synchronized (LitePalSupport.class) {
            QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());
            String limit;
            if (mOffset == null) {
                limit = mLimit;
            } else {
                if (mLimit == null) {
                    mLimit = "0";
                }
                limit = mOffset + "," + mLimit;
            }
            return queryHandler.onFind(modelClass, mColumns, mConditions, mOrderBy, limit, isEager);
        }
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindMultiExecutor<T> findAsync(final Class<T> modelClass, final boolean isEager) {
        final FindMultiExecutor<T> executor = new FindMultiExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final List<T> t = find(modelClass, isEager);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Finds the first record by the cluster parameters. You can use the below
     * way to finish a complicated query:
     *
     * <pre>
     * LitePal.select(&quot;name&quot;).where(&quot;age &gt; ?&quot;, &quot;14&quot;).order(&quot;age&quot;).limit(10).offset(2)
     * 		.findFirst(Person.class);
     * </pre>
     *
     * Note that the associated models won't be loaded by default considering
     * the efficiency, but you can do that by using
     * {@link FluentQuery#findFirst(Class, boolean)}.
     *
     * @param modelClass
     *            Which table to query and the object type to return.
     * @return An object with founded data from database, or null.
     */
    public <T> T findFirst(Class<T> modelClass) {
        return findFirst(modelClass, false);
    }

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindExecutor<T> findFirstAsync(Class<T> modelClass) {
        return findFirstAsync(modelClass, false);
    }

    /**
     * It is mostly same as {@link FluentQuery#findFirst(Class)} but an isEager
     * parameter. If set true the associated models will be loaded as well.
     * <br>
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
     *
     * @param modelClass
     *            Which table to query and the object type to return.
     * @param isEager
     *            True to load the associated models, false not.
     * @return An object with founded data from database, or null.
     */
    public <T> T findFirst(Class<T> modelClass, boolean isEager) {
        synchronized (LitePalSupport.class) {
        	String limitTemp = mLimit;
        	if (!"0".equals(mLimit)) { // If mLimit not equals to 0, set mLimit to 1 to find the first record.
        		mLimit = "1";
			}
            List<T> list = find(modelClass, isEager);
        	mLimit = limitTemp; // Don't forget to change it back after finding operation.
            if (list.size() > 0) {
				if (list.size() != 1) throw new LitePalSupportException("Found multiple records while only one record should be found at most.");
                return list.get(0);
            }
            return null;
        }
    }

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindExecutor<T> findFirstAsync(final Class<T> modelClass, final boolean isEager) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = findFirst(modelClass, isEager);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Finds the last record by the cluster parameters. You can use the below
     * way to finish a complicated query:
     *
     * <pre>
     * LitePal.select(&quot;name&quot;).where(&quot;age &gt; ?&quot;, &quot;14&quot;).order(&quot;age&quot;).limit(10).offset(2)
     * 		.findLast(Person.class);
     * </pre>
     *
     * Note that the associated models won't be loaded by default considering
     * the efficiency, but you can do that by using
     * {@link FluentQuery#findLast(Class, boolean)}.
     *
     * @param modelClass
     *            Which table to query and the object type to return.
     * @return An object with founded data from database, or null.
     */
    public <T> T findLast(Class<T> modelClass) {
        return findLast(modelClass, false);
    }

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindExecutor<T> findLastAsync(Class<T> modelClass) {
        return findLastAsync(modelClass, false);
    }

    /**
     * It is mostly same as {@link FluentQuery#findLast(Class)} but an isEager
     * parameter. If set true the associated models will be loaded as well.
     * <br>
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
     *
     * @param modelClass
     *            Which table to query and the object type to return.
     * @param isEager
     *            True to load the associated models, false not.
     * @return An object with founded data from database, or null.
     */
    public <T> T findLast(Class<T> modelClass, boolean isEager) {
        synchronized (LitePalSupport.class) {
			String orderByTemp = mOrderBy;
			String limitTemp = mLimit;
        	if (TextUtils.isEmpty(mOffset) && TextUtils.isEmpty(mLimit)) { // If mOffset or mLimit is specified, we can't use the strategy in this block to speed up finding.
				if (TextUtils.isEmpty(mOrderBy)) {
					// If mOrderBy is null, we can use id desc order, then the first record will be the record value where want to find.
					mOrderBy = "id desc";
				} else {
					// If mOrderBy is not null, check if it ends with desc.
					if (mOrderBy.endsWith(" desc")) {
						// If mOrderBy ends with desc, then the last record of desc order will be the first record of asc order, so we remove the desc.
						mOrderBy = mOrderBy.replace(" desc", "");
					} else {
						// If mOrderBy not ends with desc, then the last record of asc order will be the first record of desc order, so we add the desc.
						mOrderBy += " desc";
					}
				}
				if (!"0".equals(mLimit)) {
					mLimit = "1";
				}
			}
            List<T> list = find(modelClass, isEager);
        	mOrderBy = orderByTemp;
        	mLimit = limitTemp;
            int size = list.size();
            if (size > 0) {
                return list.get(size - 1);
            }
            return null;
        }
    }

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindExecutor<T> findLastAsync(final Class<T> modelClass, final boolean isEager) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = findLast(modelClass, isEager);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

	/**
	 * Count the records.
	 *
	 * <pre>
	 * LitePal.count(Person.class);
	 * </pre>
	 *
	 * This will count all rows in person table.<br>
	 * You can also specify a where clause when counting.
	 *
	 * <pre>
	 * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).count(Person.class);
	 * </pre>
	 *
	 * @param modelClass
	 *            Which table to query from by class.
	 * @return Count of the specified table.
	 */
	public int count(Class<?> modelClass) {
        return count(BaseUtility.changeCase(modelClass.getSimpleName()));
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public CountExecutor countAsync(Class<?> modelClass) {
        return countAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())));
    }

	/**
	 * Count the records.
	 *
	 * <pre>
	 * LitePal.count(&quot;person&quot;);
	 * </pre>
	 *
	 * This will count all rows in person table.<br>
	 * You can also specify a where clause when counting.
	 *
	 * <pre>
	 * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).count(&quot;person&quot;);
	 * </pre>
	 *
	 * @param tableName
	 *            Which table to query from.
	 * @return Count of the specified table.
	 */
	public int count(String tableName) {
        synchronized (LitePalSupport.class) {
            QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());
            return queryHandler.onCount(tableName, mConditions);
        }
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public CountExecutor countAsync(final String tableName) {
        final CountExecutor executor = new CountExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final int count = count(tableName);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(count);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

	/**
	 * Calculates the average value on a given column.
	 *
	 * <pre>
	 * LitePal.average(Person.class, &quot;age&quot;);
	 * </pre>
	 *
	 * You can also specify a where clause when calculating.
	 *
	 * <pre>
	 * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).average(Person.class, &quot;age&quot;);
	 * </pre>
	 *
	 * @param modelClass
	 *            Which table to query from by class.
	 * @param column
	 *            The based on column to calculate.
	 * @return The average value on a given column.
	 */
	public double average(Class<?> modelClass, String column) {
        return average(BaseUtility.changeCase(modelClass.getSimpleName()), column);
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public AverageExecutor averageAsync(final Class<?> modelClass, final String column) {
        return averageAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), column);
    }

	/**
	 * Calculates the average value on a given column.
	 *
	 * <pre>
	 * LitePal.average(&quot;person&quot;, &quot;age&quot;);
	 * </pre>
	 *
	 * You can also specify a where clause when calculating.
	 *
	 * <pre>
	 * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).average(&quot;person&quot;, &quot;age&quot;);
	 * </pre>
	 *
	 * @param tableName
	 *            Which table to query from.
	 * @param column
	 *            The based on column to calculate.
	 * @return The average value on a given column.
	 */
	public double average(String tableName, String column) {
        synchronized (LitePalSupport.class) {
            QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());
            return queryHandler.onAverage(tableName, column, mConditions);
        }
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public AverageExecutor averageAsync(final String tableName, final String column) {
        final AverageExecutor executor = new AverageExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final double average = average(tableName, column);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(average);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

	/**
	 * Calculates the maximum value on a given column. The value is returned
	 * with the same data type of the column.
	 *
	 * <pre>
	 * LitePal.max(Person.class, &quot;age&quot;, int.class);
	 * </pre>
	 *
	 * You can also specify a where clause when calculating.
	 *
	 * <pre>
	 * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).max(Person.class, &quot;age&quot;, Integer.TYPE);
	 * </pre>
	 *
	 * @param modelClass
	 *            Which table to query from by class.
	 * @param columnName
	 *            The based on column to calculate.
	 * @param columnType
	 *            The type of the based on column.
	 * @return The maximum value on a given column.
	 */
	public <T> T max(Class<?> modelClass, String columnName, Class<T> columnType) {
        return max(BaseUtility.changeCase(modelClass.getSimpleName()), columnName, columnType);
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindExecutor<T> maxAsync(final Class<?> modelClass, final String columnName, final Class<T> columnType) {
        return maxAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), columnName, columnType);
    }

	/**
	 * Calculates the maximum value on a given column. The value is returned
	 * with the same data type of the column.
	 *
	 * <pre>
	 * LitePal.max(&quot;person&quot;, &quot;age&quot;, int.class);
	 * </pre>
	 *
	 * You can also specify a where clause when calculating.
	 *
	 * <pre>
	 * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).max(&quot;person&quot;, &quot;age&quot;, Integer.TYPE);
	 * </pre>
	 *
	 * @param tableName
	 *            Which table to query from.
	 * @param columnName
	 *            The based on column to calculate.
	 * @param columnType
	 *            The type of the based on column.
	 * @return The maximum value on a given column.
	 */
	public <T> T max(String tableName, String columnName, Class<T> columnType) {
        synchronized (LitePalSupport.class) {
            QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());
            return queryHandler.onMax(tableName, columnName, mConditions, columnType);
        }
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindExecutor<T> maxAsync(final String tableName, final String columnName, final Class<T> columnType) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = max(tableName, columnName, columnType);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

	/**
	 * Calculates the minimum value on a given column. The value is returned
	 * with the same data type of the column.
	 *
	 * <pre>
	 * LitePal.min(Person.class, &quot;age&quot;, int.class);
	 * </pre>
	 *
	 * You can also specify a where clause when calculating.
	 *
	 * <pre>
	 * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).min(Person.class, &quot;age&quot;, Integer.TYPE);
	 * </pre>
	 *
	 * @param modelClass
	 *            Which table to query from by class.
	 * @param columnName
	 *            The based on column to calculate.
	 * @param columnType
	 *            The type of the based on column.
	 * @return The minimum value on a given column.
	 */
	public <T> T min(Class<?> modelClass, String columnName, Class<T> columnType) {
        return min(BaseUtility.changeCase(modelClass.getSimpleName()), columnName, columnType);
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindExecutor<T> minAsync(final Class<?> modelClass, final String columnName, final Class<T> columnType) {
        return minAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), columnName, columnType);
    }

	/**
	 * Calculates the minimum value on a given column. The value is returned
	 * with the same data type of the column.
	 *
	 * <pre>
	 * LitePal.min(&quot;person&quot;, &quot;age&quot;, int.class);
	 * </pre>
	 *
	 * You can also specify a where clause when calculating.
	 *
	 * <pre>
	 * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).min(&quot;person&quot;, &quot;age&quot;, Integer.TYPE);
	 * </pre>
	 *
	 * @param tableName
	 *            Which table to query from.
	 * @param columnName
	 *            The based on column to calculate.
	 * @param columnType
	 *            The type of the based on column.
	 * @return The minimum value on a given column.
	 */
	public <T> T min(String tableName, String columnName, Class<T> columnType) {
        synchronized (LitePalSupport.class) {
            QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());
            return queryHandler.onMin(tableName, columnName, mConditions, columnType);
        }
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindExecutor<T> minAsync(final String tableName, final String columnName, final Class<T> columnType) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = min(tableName, columnName, columnType);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

	/**
	 * Calculates the sum of values on a given column. The value is returned
	 * with the same data type of the column.
	 *
	 * <pre>
	 * LitePal.sum(Person.class, &quot;age&quot;, int.class);
	 * </pre>
	 *
	 * You can also specify a where clause when calculating.
	 *
	 * <pre>
	 * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).sum(Person.class, &quot;age&quot;, Integer.TYPE);
	 * </pre>
	 *
	 * @param modelClass
	 *            Which table to query from by class.
	 * @param columnName
	 *            The based on column to calculate.
	 * @param columnType
	 *            The type of the based on column.
	 * @return The sum value on a given column.
	 */
	public <T> T sum(Class<?> modelClass, String columnName, Class<T> columnType) {
        return sum(BaseUtility.changeCase(modelClass.getSimpleName()), columnName, columnType);
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindExecutor<T> sumAsync(final Class<?> modelClass, final String columnName, final Class<T> columnType) {
        return sumAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), columnName, columnType);
    }

    /**
	 * Calculates the sum of values on a given column. The value is returned
	 * with the same data type of the column.
	 *
	 * <pre>
	 * LitePal.sum(&quot;person&quot;, &quot;age&quot;, int.class);
	 * </pre>
	 *
	 * You can also specify a where clause when calculating.
	 *
	 * <pre>
	 * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).sum(&quot;person&quot;, &quot;age&quot;, Integer.TYPE);
	 * </pre>
	 *
	 * @param tableName
	 *            Which table to query from.
	 * @param columnName
	 *            The based on column to calculate.
	 * @param columnType
	 *            The type of the based on column.
	 * @return The sum value on a given column.
	 */
	public <T> T sum(String tableName, String columnName, Class<T> columnType) {
        synchronized (LitePalSupport.class) {
            QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());
            return queryHandler.onSum(tableName, columnName, mConditions, columnType);
        }
	}

	/**
	 * This method is deprecated and will be removed in the future releases.
	 * Handle async db operation in your own logic instead.
	 */
	@Deprecated
    public <T> FindExecutor<T> sumAsync(final String tableName, final String columnName, final Class<T> columnType) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = sum(tableName, columnName, columnType);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

}

================================================
FILE: core/src/main/java/org/litepal/LitePal.kt
================================================
/*
 * Copyright (C)  Tony Green, LitePal Framework Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.litepal

import android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import org.litepal.crud.LitePalSupport
import org.litepal.tablemanager.callback.DatabaseListener

/**
 * LitePal is an Android library that allows developers to use SQLite database extremely easy.
 * You can initialized it by calling {@link #initialize(Context)} method to make LitePal ready to
 * work. Also you can switch the using database by calling {@link #use(LitePalDB)} and {@link #useDefault()}
 * methods.
 *
 * @author Tony Green
 * @since 2.0
 */
object LitePal {

    /**
     * Initialize to make LitePal ready to work. If you didn't configure LitePalApplication
     * in the AndroidManifest.xml, make sure you call this method as soon as possible. In
     * Application's onCreate() method will be fine.
     *
     * @param context
     * Application context.
     */
    @JvmStatic
    fun initialize(context: Context) {
        Operator.initialize(context)
    }

    /**
     * Get a writable SQLiteDatabase.
     *
     * @return A writable SQLiteDatabase instance
     */
    @JvmStatic
    fun getDatabase(): SQLiteDatabase = Operator.getDatabase()

    /**
     * Begins a transaction in EXCLUSIVE mode.
     */
    @JvmStatic
    fun beginTransaction() = Operator.beginTransaction()

    /**
     * End a transaction.
     */
    @JvmStatic
    fun endTransaction() = Operator.endTransaction()

    /**
     * Marks the current transaction as successful. Do not do any more database work between calling this and calling endTransaction.
     * Do as little non-database work as possible in that situation too.
     * If any errors are encountered between this and endTransaction the transaction will still be committed.
     */
    @JvmStatic
    fun setTransactionSuccessful() = Operator.setTransactionSuccessful()

    /**
     * Switch the using database to the one specified by parameter.
     * @param litePalDB
     * The database to switch to.
     */
    @JvmStatic
    fun use(litePalDB: LitePalDB) {
        Operator.use(litePalDB)
    }


    /**
     * Switch the using database to default with configuration by litepal.xml.
     */
    @JvmStatic
    fun useDefault() {
        Operator.useDefault()
    }

    /**
     * Delete the specified database.
     * @param dbName
     * Name of database to delete.
     * @return True if delete success, false otherwise.
     */
    @JvmStatic
    fun deleteDatabase(dbName: String) = Operator.deleteDatabase(dbName)

    @JvmStatic
    fun aesKey(key: String) {
        Operator.aesKey(key)
    }

    /**
     * Declaring to query which columns in table.
     *
     * LitePal.select(&quot;name&quot;, &quot;age&quot;).find(Person.class);
     *
     * This will find all rows with name and age columns in Person table.
     *
     * @param columns
     * A String array of which columns to return. Passing null will
     * return all columns.
     *
     * @return A FluentQuery instance.
     */
    @JvmStatic
    fun select(vararg columns: String?) = Operator.select(*columns)

    /**
     * Declaring to query which rows in table.
     *
     * LitePal.where(&quot;name = ? or age &gt; ?&quot;, &quot;Tom&quot;, &quot;14&quot;).find(Person.class);
     *
     * This will find rows which name is Tom or age greater than 14 in Person
     * table.
     *
     * @param conditions
     * A filter declaring which rows to return, formatted as an SQL
     * WHERE clause. Passing null will return all rows.
     * @return A FluentQuery instance.
     */
    @JvmStatic
    fun where(vararg conditions: String?) = Operator.where(*conditions)

    /**
     * Declaring how to order the rows queried from table.
     *
     * LitePal.order(&quot;name desc&quot;).find(Person.class);
     *
     * This will find all rows in Person table sorted by name with inverted
     * order.
     *
     * @param column
     * How to order the rows, formatted as an SQL ORDER BY clause.
     * Passing null will use the default sort order, which may be
     * unordered.
     * @return A FluentQuery instance.
     */
    @JvmStatic
    fun order(column: String?) = Operator.order(column)

    /**
     * Limits the number of rows returned by the query.
     *
     * LitePal.limit(2).find(Person.class);
     *
     * This will find the top 2 rows in Person table.
     *
     * @param value
     * Limits the number of rows returned by the query, formatted as
     * LIMIT clause.
     * @return A FluentQuery instance.
     */
    @JvmStatic
    fun limit(value: Int) = Operator.limit(value)

    /**
     * Declaring the offset of rows returned by the query. This method must be
     * used with [LitePal.limit], or nothing will return.
     *
     * LitePal.limit(1).offset(2).find(Person.class);
     *
     * This will find the third row in Person table.
     *
     * @param value
     * The offset amount of rows returned by the query.
     * @return A FluentQuery instance.
     */
    @JvmStatic
    fun offset(value: Int) = Operator.offset(value)

    /**
     * Count the records.
     *
     * LitePal.count(Person.class);
     *
     * This will count all rows in person table.
     *
     * You can also specify a where clause when counting.
     *
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).count(Person.class);
     *
     * @param modelClass
     * Which table to query from by class.
     * @return Count of the specified table.
     */
    @JvmStatic
    fun count(modelClass: Class<*>) = Operator.count(modelClass)

    /**
     * Basically same as [LitePal.count] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query from by class.
     * @return A CountExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun countAsync(modelClass: Class<*>) = Operator.countAsync(modelClass)

    /**
     * Count the records.
     *
     * LitePal.count(&quot;person&quot;);
     *
     * This will count all rows in person table.
     *
     * You can also specify a where clause when counting.
     *
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).count(&quot;person&quot;);
     *
     * @param tableName
     * Which table to query from.
     * @return Count of the specified table.
     */
    @JvmStatic
    fun count(tableName: String) = Operator.count(tableName)

    /**
     * Basically same as [LitePal.count] but pending to a new thread for executing.
     *
     * @param tableName
     * Which table to query from.
     * @return A CountExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun countAsync(tableName: String) = Operator.countAsync(tableName)

    /**
     * Calculates the average value on a given column.
     *
     * LitePal.average(Person.class, &quot;age&quot;);
     *
     * You can also specify a where clause when calculating.
     *
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).average(Person.class, &quot;age&quot;);
     *
     * @param modelClass
     * Which table to query from by class.
     * @param column
     * The based on column to calculate.
     * @return The average value on a given column.
     */
    @JvmStatic
    fun average(modelClass: Class<*>, column: String) = Operator.average(modelClass, column)

    /**
     * Basically same as [LitePal.average] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query from by class.
     * @param column
     * The based on column to calculate.
     * @return A AverageExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun averageAsync(modelClass: Class<*>, column: String) = Operator.averageAsync(modelClass, column)

    /**
     * Calculates the average value on a given column.
     *
     * LitePal.average(&quot;person&quot;, &quot;age&quot;);
     *
     * You can also specify a where clause when calculating.
     *
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).average(&quot;person&quot;, &quot;age&quot;);
     *
     * @param tableName
     * Which table to query from.
     * @param column
     * The based on column to calculate.
     * @return The average value on a given column.
     */
    @JvmStatic
    fun average(tableName: String, column: String) = Operator.average(tableName, column)

    /**
     * Basically same as [LitePal.average] but pending to a new thread for executing.
     *
     * @param tableName
     * Which table to query from.
     * @param column
     * The based on column to calculate.
     * @return A AverageExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun averageAsync(tableName: String, column: String) = Operator.averageAsync(tableName, column)

    /**
     * Calculates the maximum value on a given column. The value is returned
     * with the same data type of the column.
     *
     * LitePal.max(Person.class, &quot;age&quot;, int.class);
     *
     * You can also specify a where clause when calculating.
     *
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).max(Person.class, &quot;age&quot;, Integer.TYPE);
     *
     * @param modelClass
     * Which table to query from by class.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return The maximum value on a given column.
     */
    @JvmStatic
    fun <T> max(modelClass: Class<*>, columnName: String, columnType: Class<T>) = Operator.max(modelClass, columnName, columnType)

    /**
     * Basically same as [LitePal.max] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query from by class.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> maxAsync(modelClass: Class<*>, columnName: String, columnType: Class<T>) = Operator.maxAsync(modelClass, columnName, columnType)

    /**
     * Calculates the maximum value on a given column. The value is returned
     * with the same data type of the column.
     *
     * LitePal.max(&quot;person&quot;, &quot;age&quot;, int.class);
     *
     * You can also specify a where clause when calculating.
     *
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).max(&quot;person&quot;, &quot;age&quot;, Integer.TYPE);
     *
     * @param tableName
     * Which table to query from.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return The maximum value on a given column.
     */
    @JvmStatic
    fun <T> max(tableName: String, columnName: String, columnType: Class<T>) = Operator.max(tableName, columnName, columnType)

    /**
     * Basically same as [LitePal.max] but pending to a new thread for executing.
     *
     * @param tableName
     * Which table to query from.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> maxAsync(tableName: String, columnName: String, columnType: Class<T>) = Operator.maxAsync(tableName, columnName, columnType)

    /**
     * Calculates the minimum value on a given column. The value is returned
     * with the same data type of the column.
     *
     * LitePal.min(Person.class, &quot;age&quot;, int.class);
     *
     * You can also specify a where clause when calculating.
     *
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).min(Person.class, &quot;age&quot;, Integer.TYPE);
     *
     * @param modelClass
     * Which table to query from by class.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return The minimum value on a given column.
     */
    @JvmStatic
    fun <T> min(modelClass: Class<*>, columnName: String, columnType: Class<T>) = Operator.min(modelClass, columnName, columnType)

    /**
     * Basically same as [LitePal.min] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query from by class.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> minAsync(modelClass: Class<*>, columnName: String, columnType: Class<T>) = Operator.minAsync(modelClass, columnName, columnType)

    /**
     * Calculates the minimum value on a given column. The value is returned
     * with the same data type of the column.
     *
     * LitePal.min(&quot;person&quot;, &quot;age&quot;, int.class);
     *
     * You can also specify a where clause when calculating.
     *
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).min(&quot;person&quot;, &quot;age&quot;, Integer.TYPE);
     *
     * @param tableName
     * Which table to query from.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return The minimum value on a given column.
     */
    @JvmStatic
    fun <T> min(tableName: String, columnName: String, columnType: Class<T>) = Operator.min(tableName, columnName, columnType)

    /**
     * Basically same as [LitePal.min] but pending to a new thread for executing.
     *
     * @param tableName
     * Which table to query from.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> minAsync(tableName: String, columnName: String, columnType: Class<T>) = Operator.minAsync(tableName, columnName, columnType)

    /**
     * Calculates the sum of values on a given column. The value is returned
     * with the same data type of the column.
     *
     * LitePal.sum(Person.class, &quot;age&quot;, int.class);
     *
     * You can also specify a where clause when calculating.
     *
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).sum(Person.class, &quot;age&quot;, Integer.TYPE);
     *
     * @param modelClass
     * Which table to query from by class.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return The sum value on a given column.
     */
    @JvmStatic
    fun <T> sum(modelClass: Class<*>, columnName: String, columnType: Class<T>) = Operator.sum(modelClass, columnName, columnType)

    /**
     * Basically same as [LitePal.sum] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query from by class.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> sumAsync(modelClass: Class<*>, columnName: String, columnType: Class<T>) = Operator.sumAsync(modelClass, columnName, columnType)

    /**
     * Calculates the sum of values on a given column. The value is returned
     * with the same data type of the column.
     *
     * LitePal.sum(&quot;person&quot;, &quot;age&quot;, int.class);
     *
     * You can also specify a where clause when calculating.
     *
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).sum(&quot;person&quot;, &quot;age&quot;, Integer.TYPE);
     *
     * @param tableName
     * Which table to query from.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return The sum value on a given column.
     */
    @JvmStatic
    fun <T> sum(tableName: String, columnName: String, columnType: Class<T>) = Operator.sum(tableName, columnName, columnType)

    /**
     * Basically same as [LitePal.sum] but pending to a new thread for executing.
     *
     * @param tableName
     * Which table to query from.
     * @param columnName
     * The based on column to calculate.
     * @param columnType
     * The type of the based on column.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> sumAsync(tableName: String, columnName: String, columnType: Class<T>) = Operator.sumAsync(tableName, columnName, columnType)

    /**
     * Finds the record by a specific id.
     *
     * Person p = LitePal.find(Person.class, 1);
     *
     * The modelClass determines which table to query and the object type to
     * return. If no record can be found, then return null.
     *
     * Note that the associated models won't be loaded by default considering
     * the efficiency, but you can do that by using
     * [LitePal.find].
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @param id
     * Which record to query.
     * @return An object with found data from database, or null.
     */
    @JvmStatic
    fun <T> find(modelClass: Class<T>, id: Long) = Operator.find(modelClass, id)

    /**
     * Basically same as [LitePal.find] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @param id
     * Which record to query.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> findAsync(modelClass: Class<T>, id: Long) = Operator.findAsync(modelClass, id)

    /**
     * It is mostly same as [LitePal.find] but an isEager
     * parameter. If set true the associated models will be loaded as well.
     *
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @param id
     * Which record to query.
     * @param isEager
     * True to load the associated models, false not.
     * @return An object with found data from database, or null.
     */
    @JvmStatic
    fun <T> find(modelClass: Class<T>, id: Long, isEager: Boolean) = Operator.find(modelClass, id, isEager)

    /**
     * Basically same as [LitePal.find] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @param id
     * Which record to query.
     * @param isEager
     * True to load the associated models, false not.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> findAsync(modelClass: Class<T>, id: Long, isEager: Boolean) = Operator.findAsync(modelClass, id, isEager)

    /**
     * Finds the first record of a single table.
     *
     * Person p = LitePal.findFirst(Person.class);
     *
     * Note that the associated models won't be loaded by default considering
     * the efficiency, but you can do that by using
     * [LitePal.findFirst].
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @return An object with data of first row, or null.
     */
    @JvmStatic
    fun <T> findFirst(modelClass: Class<T>) = Operator.findFirst(modelClass)

    /**
     * Basically same as [LitePal.findFirst] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> findFirstAsync(modelClass: Class<T>) = Operator.findFirstAsync(modelClass)

    /**
     * It is mostly same as [LitePal.findFirst] but an isEager
     * parameter. If set true the associated models will be loaded as well.
     *
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @param isEager
     * True to load the associated models, false not.
     * @return An object with data of first row, or null.
     */
    @JvmStatic
    fun <T> findFirst(modelClass: Class<T>, isEager: Boolean) = Operator.findFirst(modelClass, isEager)

    /**
     * Basically same as [LitePal.findFirst] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @param isEager
     * True to load the associated models, false not.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> findFirstAsync(modelClass: Class<T>, isEager: Boolean) = Operator.findFirstAsync(modelClass, isEager)

    /**
     * Finds the last record of a single table.
     *
     * Person p = LitePal.findLast(Person.class);
     *
     * Note that the associated models won't be loaded by default considering
     * the efficiency, but you can do that by using
     * [LitePal.findLast].
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @return An object with data of last row, or null.
     */
    @JvmStatic
    fun <T> findLast(modelClass: Class<T>) = Operator.findLast(modelClass)

    /**
     * Basically same as [LitePal.findLast] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> findLastAsync(modelClass: Class<T>) = Operator.findLastAsync(modelClass)

    /**
     * It is mostly same as [LitePal.findLast] but an isEager
     * parameter. If set true the associated models will be loaded as well.
     *
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @param isEager
     * True to load the associated models, false not.
     * @return An object with data of last row, or null.
     */
    @JvmStatic
    fun <T> findLast(modelClass: Class<T>, isEager: Boolean) = Operator.findLast(modelClass, isEager)

    /**
     * Basically same as [LitePal.findLast] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query and the object type to return.
     * @param isEager
     * True to load the associated models, false not.
     * @return A FindExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> findLastAsync(modelClass: Class<T>, isEager: Boolean) = Operator.findLastAsync(modelClass, isEager)

    /**
     * Finds multiple records by an id array.
     *
     * List&lt;Person&gt; people = LitePal.findAll(Person.class, 1, 2, 3);
     *
     * long[] bookIds = { 10, 18 };
     * List&lt;Book&gt; books = LitePal.findAll(Book.class, bookIds);
     *
     * Of course you can find all records by passing nothing to the ids
     * parameter.
     *
     * List&lt;Book&gt; allBooks = LitePal.findAll(Book.class);
     *
     * Note that the associated models won't be loaded by default considering
     * the efficiency, but you can do that by using
     * [LitePal.findAll].
     *
     * The modelClass determines which table to query and the object type to
     * return.
     *
     * @param modelClass
     * Which table to query and the object type to return as a list.
     * @param ids
     * Which records to query. Or do not pass it to find all records.
     * @return An object list with found data from database, or an empty list.
     */
    @JvmStatic
    fun <T> findAll(modelClass: Class<T>, vararg ids: Long) = Operator.findAll(modelClass, *ids)

    /**
     * Basically same as [LitePal.findAll] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query and the object type to return as a list.
     * @param ids
     * Which records to query. Or do not pass it to find all records.
     * @return A FindMultiExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> findAllAsync(modelClass: Class<T>, vararg ids: Long) = Operator.findAllAsync(modelClass, *ids)

    /**
     * It is mostly same as [LitePal.findAll] but an
     * isEager parameter. If set true the associated models will be loaded as well.
     *
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
     *
     * @param modelClass
     * Which table to query and the object type to return as a list.
     * @param isEager
     * True to load the associated models, false not.
     * @param ids
     * Which records to query. Or do not pass it to find all records.
     * @return An object list with found data from database, or an empty list.
     */
    @JvmStatic
    fun <T> findAll(modelClass: Class<T>, isEager: Boolean, vararg ids: Long) = Operator.findAll(modelClass, isEager, *ids)

    /**
     * Basically same as [LitePal.findAll] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to query and the object type to return as a list.
     * @param isEager
     * True to load the associated models, false not.
     * @param ids
     * Which records to query. Or do not pass it to find all records.
     * @return A FindMultiExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T> findAllAsync(modelClass: Class<T>, isEager: Boolean, vararg ids: Long) = Operator.findAllAsync(modelClass, isEager, *ids)

    /**
     * Runs the provided SQL and returns a Cursor over the result set. You may
     * include ? in where clause in the query, which will be replaced by the
     * second to the last parameters, such as:
     *
     * Cursor cursor = LitePal.findBySQL(&quot;select * from person where name=? and age=?&quot;, &quot;Tom&quot;, &quot;14&quot;);
     *
     * @param sql
     * First parameter is the SQL clause to apply. Second to the last
     * parameters will replace the place holders.
     * @return A Cursor object, which is positioned before the first entry. Note
     * that Cursors are not synchronized, see the documentation for more
     * details.
     */
    @JvmStatic
    fun findBySQL(vararg sql: String) = Operator.findBySQL(*sql)

    /**
     * Deletes the record in the database by id.
     *
     * The data in other tables which is referenced with the record will be
     * removed too.
     *
     * LitePal.delete(Person.class, 1);
     *
     * This means that the record 1 in person table will be removed.
     *
     * @param modelClass
     * Which table to delete from by class.
     * @param id
     * Which record to delete.
     * @return The number of rows affected. Including cascade delete rows.
     */
    @JvmStatic
    fun delete(modelClass: Class<*>, id: Long) = Operator.delete(modelClass, id)

    /**
     * Basically same as [LitePal.delete] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to delete from by class.
     * @param id
     * Which record to delete.
     * @return A UpdateOrDeleteExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun deleteAsync(modelClass: Class<*>, id: Long) = Operator.deleteAsync(modelClass, id)

    /**
     * Deletes all records with details given if they match a set of conditions
     * supplied. This method constructs a single SQL DELETE statement and sends
     * it to the database.
     *
     * LitePal.deleteAll(Person.class, &quot;name = ? and age = ?&quot;, &quot;Tom&quot;, &quot;14&quot;);
     *
     * This means that all the records which name is Tom and age is 14 will be
     * removed.
     *
     * @param modelClass
     * Which table to delete from by class.
     * @param conditions
     * A string array representing the WHERE part of an SQL
     * statement. First parameter is the WHERE clause to apply when
     * deleting. The way of specifying place holders is to insert one
     * or more question marks in the SQL. The first question mark is
     * replaced by the second element of the array, the next question
     * mark by the third, and so on. Passing empty string will delete
     * all rows.
     * @return The number of rows affected.
     */
    @JvmStatic
    fun deleteAll(modelClass: Class<*>, vararg conditions: String?) = Operator.deleteAll(modelClass, *conditions)

    /**
     * Basically same as [LitePal.deleteAll] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to delete from by class.
     * @param conditions
     * A string array representing the WHERE part of an SQL
     * statement. First parameter is the WHERE clause to apply when
     * deleting. The way of specifying place holders is to insert one
     * or more question marks in the SQL. The first question mark is
     * replaced by the second element of the array, the next question
     * mark by the third, and so on. Passing empty string will delete
     * all rows.
     * @return A UpdateOrDeleteExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun deleteAllAsync(modelClass: Class<*>, vararg conditions: String?) = Operator.deleteAllAsync(modelClass, *conditions)

    /**
     * Deletes all records with details given if they match a set of conditions
     * supplied. This method constructs a single SQL DELETE statement and sends
     * it to the database.
     *
     * LitePal.deleteAll(&quot;person&quot;, &quot;name = ? and age = ?&quot;, &quot;Tom&quot;, &quot;14&quot;);
     *
     * This means that all the records which name is Tom and age is 14 will be
     * removed.
     *
     * Note that this method won't delete the referenced data in other tables.
     * You should remove those values by your own.
     *
     * @param tableName
     * Which table to delete from.
     * @param conditions
     * A string array representing the WHERE part of an SQL
     * statement. First parameter is the WHERE clause to apply when
     * deleting. The way of specifying place holders is to insert one
     * or more question marks in the SQL. The first question mark is
     * replaced by the second element of the array, the next question
     * mark by the third, and so on. Passing empty string will delete
     * all rows.
     * @return The number of rows affected.
     */
    @JvmStatic
    fun deleteAll(tableName: String, vararg conditions: String?) = Operator.deleteAll(tableName, *conditions)

    /**
     * Basically same as [LitePal.deleteAll] but pending to a new thread for executing.
     *
     * @param tableName
     * Which table to delete from.
     * @param conditions
     * A string array representing the WHERE part of an SQL
     * statement. First parameter is the WHERE clause to apply when
     * deleting. The way of specifying place holders is to insert one
     * or more question marks in the SQL. The first question mark is
     * replaced by the second element of the array, the next question
     * mark by the third, and so on. Passing empty string will delete
     * all rows.
     * @return A UpdateOrDeleteExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun deleteAllAsync(tableName: String, vararg conditions: String?) = Operator.deleteAllAsync(tableName, *conditions)

    /**
     * Updates the corresponding record by id with ContentValues. Returns the
     * number of affected rows.
     *
     * ContentValues cv = new ContentValues();
     *
     * cv.put(&quot;name&quot;, &quot;Jim&quot;);
     *
     * LitePal.update(Person.class, cv, 1);
     *
     * This means that the name of record 1 will be updated into Jim.
     *
     * @param modelClass
     * Which table to update by class.
     * @param values
     * A map from column names to new column values. null is a valid
     * value that will be translated to NULL.
     * @param id
     * Which record to update.
     * @return The number of rows affected.
     */
    @JvmStatic
    fun update(modelClass: Class<*>, values: ContentValues, id: Long) = Operator.update(modelClass, values, id)

    /**
     * Basically same as [LitePal.update] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to update by class.
     * @param values
     * A map from column names to new column values. null is a valid
     * value that will be translated to NULL.
     * @param id
     * Which record to update.
     * @return A UpdateOrDeleteExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun updateAsync(modelClass: Class<*>, values: ContentValues, id: Long) = Operator.updateAsync(modelClass, values, id)

    /**
     * Updates all records with details given if they match a set of conditions
     * supplied. This method constructs a single SQL UPDATE statement and sends
     * it to the database.
     *
     * ContentValues cv = new ContentValues();
     *
     * cv.put(&quot;name&quot;, &quot;Jim&quot;);
     *
     * LitePal.update(Person.class, cv, &quot;name = ?&quot;, &quot;Tom&quot;);
     *
     * This means that all the records which name is Tom will be updated into
     * Jim.
     *
     * @param modelClass
     * Which table to update by class.
     * @param values
     * A map from column names to new column values. null is a valid
     * value that will be translated to NULL.
     * @param conditions
     * A string array representing the WHERE part of an SQL
     * statement. First parameter is the WHERE clause to apply when
     * updating. The way of specifying place holders is to insert one
     * or more question marks in the SQL. The first question mark is
     * replaced by the second element of the array, the next question
     * mark by the third, and so on. Passing empty string will update
     * all rows.
     * @return The number of rows affected.
     */
    @JvmStatic
    fun updateAll(modelClass: Class<*>, values: ContentValues, vararg conditions: String?) = Operator.updateAll(modelClass, values, *conditions)

    /**
     * Basically same as [LitePal.updateAll] but pending to a new thread for executing.
     *
     * @param modelClass
     * Which table to update by class.
     * @param values
     * A map from column names to new column values. null is a valid
     * value that will be translated to NULL.
     * @param conditions
     * A string array representing the WHERE part of an SQL
     * statement. First parameter is the WHERE clause to apply when
     * updating. The way of specifying place holders is to insert one
     * or more question marks in the SQL. The first question mark is
     * replaced by the second element of the array, the next question
     * mark by the third, and so on. Passing empty string will update
     * all rows.
     * @return A UpdateOrDeleteExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun updateAllAsync(modelClass: Class<*>, values: ContentValues, vararg conditions: String?) = Operator.updateAllAsync(modelClass, values, *conditions)

    /**
     * Updates all records with details given if they match a set of conditions
     * supplied. This method constructs a single SQL UPDATE statement and sends
     * it to the database.
     *
     * ContentValues cv = new ContentValues();
     *
     * cv.put(&quot;name&quot;, &quot;Jim&quot;);
     *
     * LitePal.update(&quot;person&quot;, cv, &quot;name = ?&quot;, &quot;Tom&quot;);
     *
     * This means that all the records which name is Tom will be updated into
     * Jim.
     *
     * @param tableName
     * Which table to update.
     * @param values
     * A map from column names to new column values. null is a valid
     * value that will be translated to NULL.
     * @param conditions
     * A string array representing the WHERE part of an SQL
     * statement. First parameter is the WHERE clause to apply when
     * updating. The way of specifying place holders is to insert one
     * or more question marks in the SQL. The first question mark is
     * replaced by the second element of the array, the next question
     * mark by the third, and so on. Passing empty string will update
     * all rows.
     * @return The number of rows affected.
     */
    @JvmStatic
    fun updateAll(tableName: String, values: ContentValues, vararg conditions: String?) = Operator.updateAll(tableName, values, *conditions)

    /**
     * Basically same as [LitePal.updateAll] but pending to a new thread for executing.
     *
     * @param tableName
     * Which table to update.
     * @param values
     * A map from column names to new column values. null is a valid
     * value that will be translated to NULL.
     * @param conditions
     * A string array representing the WHERE part of an SQL
     * statement. First parameter is the WHERE clause to apply when
     * updating. The way of specifying place holders is to insert one
     * or more question marks in the SQL. The first question mark is
     * replaced by the second element of the array, the next question
     * mark by the third, and so on. Passing empty string will update
     * all rows.
     * @return A UpdateOrDeleteExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun updateAllAsync(tableName: String, values: ContentValues, vararg conditions: String?) = Operator.updateAllAsync(tableName, values, *conditions)

    /**
     * Saves the collection into database.
     *
     * LitePal.saveAll(people);
     *
     * If the model in collection is a new record gets created in the database,
     * otherwise the existing record gets updated.
     *
     * If saving process failed by any accident, the whole action will be
     * cancelled and your database will be **rolled back**.
     *
     * This method acts the same result as the below way, but **much more
     * efficient**.
     *
     * for (Person person : people) {
     *      person.save();
     * }
     *
     * So when your collection holds huge of models, saveAll(Collection) is the better choice.
     *
     * @param collection
     * Holds all models to save.
     * @return True if all records in collection are saved. False none record in collection is saved. There won't be partial saved condition.
     */
    @JvmStatic
    fun <T : LitePalSupport> saveAll(collection: Collection<T>) = Operator.saveAll(collection)

    /**
     * Basically same as [LitePal.saveAll] but pending to a new thread for executing.
     *
     * @param collection
     * Holds all models to save.
     * @return A SaveExecutor instance.
     */
    @JvmStatic
    @Deprecated("This method is deprecated and will be removed in the future releases.", ReplaceWith("Handle async db operation in your own logic instead."))
    fun <T : LitePalSupport> saveAllAsync(collection: Collection<T>) = Operator.saveAllAsync(collection)

    /**
     * Provide a way to mark all models in collection as deleted. This means these models' save
     * state is no longer exist anymore. If save them again, they will be treated as inserting new
     * data instead of updating the exist one.
     * @param collection
     * Collection of models which want to mark as deleted and clear their save state.
     */
    @JvmStatic
    fun <T : LitePalSupport> markAsDeleted(collection: Collection<T>) {
        Operator.markAsDeleted(collection)
    }

    /**
     * Check if the specified conditions data already exists in the table.
     * @param modelClass
     * Which table to check by class.
     * @param conditions
     * A filter declaring which data to check. Exactly same use as
     * [LitePal.where], except null conditions will result in false.
     * @return Return true if the specified conditions data already exists in the table.
     * False otherwise. Null conditions will result in false.
     */
    @JvmStatic
    fun <T> isExist(modelClass: Class<T>, vararg conditions: String?) = Operator.isExist(modelClass, *conditions)

    /**
     * Register a listener to listen database create and upgrade events.
     */
    @JvmStatic
    fun registerDatabaseListener(listener: DatabaseListener) {
        Operator.registerDatabaseListener(listener)
    }

}

================================================
FILE: core/src/main/java/org/litepal/LitePalApplication.java
================================================
/*
 * Copyright (C)  Tony Green, LitePal Framework Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.litepal;

import org.litepal.exceptions.GlobalException;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;

/**
 * Base class of LitePal to make things easier when developers need to use
 * context. When you need context, just use
 * <b>LitePalApplication.getContext()</b>. To make this function work, you need
 * to configure your AndroidManifest.xml. Specifying
 * <b>"org.litepal.LitePalApplication"</b> as the application name in your
 * &lt;application&gt; tag to enable LitePal get the context. Of course if you
 * need to write your own Application class, LitePal can still live with that.
 * But just remember make your own Application class inherited from
 * LitePalApplication instead of inheriting from Application directly. This can
 * make all things work without side effects. <br>
 * Besides if you don't want use the above way, you can also call the LitePal.initialize(Context)
 * method to do the same job. Just remember call this method as early as possible, in Application's onCreate()
 * method will be fine.
 * 
 * @author Tony Green
 * @since 1.0
 */
public class LitePalApplication extends Application {

	/**
	 * Global application context.
	 */
	@SuppressLint("StaticFieldLeak")
	public static Context sContext;

	public static Handler sHandler = new Handler(Looper.getMainLooper());

	/**
	 * Construct of LitePalApplication. Initialize application context.
	 */
	public LitePalApplication() {
		sContext = this;
	}

	/**
	 * Get the global application context.
	 * 
	 * @return Application context.
	 * @throws org.litepal.exceptions.GlobalException
	 */
	public static Context getContext() {
		if (sContext == null) {
			throw new GlobalException(GlobalException.APPLICATION_CONTEXT_IS_NULL);
		}
		return sContext;
	}

}


================================================
FILE: core/src/main/java/org/litepal/LitePalBase.java
================================================
/*
 * Copyright (C)  Tony Green, LitePal Framework Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.litepal;

import org.litepal.annotation.Column;
import org.litepal.crud.LitePalSupport;
import org.litepal.crud.model.AssociationsInfo;
import org.litepal.exceptions.DatabaseGenerateException;
import org.litepal.parser.LitePalAttr;
import org.litepal.tablemanager.model.AssociationsModel;
import org.litepal.tablemanager.model.ColumnModel;
import org.litepal.tablemanager.model.GenericModel;
import org.litepal.tablemanager.model.TableModel;
import org.litepal.tablemanager.typechange.BlobOrm;
import org.litepal.tablemanager.typechange.BooleanOrm;
import org.litepal.tablemanager.typechange.DateOrm;
import org.litepal.tablemanager.typechange.DecimalOrm;
import org.litepal.tablemanager.typechange.NumericOrm;
import org.litepal.tablemanager.typechange.OrmChange;
import org.litepal.tablemanager.typechange.TextOrm;
import org.litepal.util.BaseUtility;
import org.litepal.util.Const;
import org.litepal.util.DBUtility;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Base class of all the LitePal components. If each component need to
 * interactive with other components or they have some same logic with duplicate
 * codes, LitePalBase may be the solution.
 * 
 * @author Tony Green
 * @since 1.1
 */
public abstract class LitePalBase {

	public static final String TAG = "LitePalBase";

	/**
	 * Action to get associations.
	 */
	private static final int GET_ASSOCIATIONS_ACTION = 1;

	/**
	 * Action to get association info.
	 */
	private static final int GET_ASSOCIATION_INFO_ACTION = 2;

	/**
	 * All the supporting mapping types currently in the array.
	 */
	private OrmChange[] typeChangeRules = { new NumericOrm(), new TextOrm(), new BooleanOrm(),
			new DecimalOrm(), new DateOrm(), new BlobOrm()};

    /**
     * This is map of class name to fields list. Indicates that each class has which supported fields.
     */
    private Map<String, List<Field>> classFieldsMap = new HashMap<>();

	/**
	 * This is map of class name to generic fields list. Indicates that each class has which supported generic fields.
	 */
    private Map<String, List<Field>> classGenericFieldsMap = new HashMap<>();

	/**
	 * The collection contains all association models.
	 */
	private Collection<AssociationsModel> mAssociationModels;

	/**
	 * The collection contains all association info.
	 */
	private Collection<AssociationsInfo> mAssociationInfos;

    /**
     * The collection contains all generic models.
     */
    private Collection<GenericModel> mGenericModels;

	/**
	 * This method is used to get the table model by the class name passed
	 * in. The principle to generate table model is that each field in the class
	 * with non-static modifier and has a type among int/Integer, long/Long,
	 * short/Short, float/Float, double/Double, char/Character, boolean/Boolean
	 * or String, would generate a column with same name as corresponding field.
	 * If users don't want some of the fields map a column, declare an ignore
     * annotation with {@link Column#ignore()}.
	 * 
	 * @param className
	 *            The full name of the class to map in database.
	 * @return A table model with table name, class name and the map of column
	 *         name and column type.
	 */
	protected TableModel getTableModel(String className) {
		String tableName = DBUtility.getTableNameByClassName(className);
		TableModel tableModel = new TableModel();
		tableModel.setTableName(tableName);
		tableModel.setClassName(className);
		List<Field> supportedFields = getSupportedFields(className);
		for (Field field : supportedFields) {
            ColumnModel columnModel = convertFieldToColumnModel(field);
            tableModel.addColumnModel(columnModel);
		}
		return tableModel;
	}

	/**
	 * This method is used to get association models depends on the given class
	 * name list.
	 * 
	 * @param classNames
	 *            The names of the classes that want to get their associations.
	 * @return Collection of association models.
	 */
	protected Collection<AssociationsModel> getAssociations(List<String> classNames) {
		if (mAssociationModels == null) {
			mAssociationModels = new HashSet<>();
		}
        if (mGenericModels == null) {
            mGenericModels = new HashSet<>();
        }
		mAssociationModels.clear();
        mGenericModels.clear();
		for (String className : classNames) {
			analyzeClassFields(className, GET_ASSOCIATIONS_ACTION);
		}
		return mAssociationModels;
	}

    /**
     * Get all generic models for create generic tables.
     * @return All generic models.
     */
    protected Collection<GenericModel> getGenericModels() {
        return mGenericModels;
    }

	/**
	 * Get the association info model by the class name.
	 * 
	 * @param className
	 *            The class name to introspection.
	 * @return Collection of association info.
	 */
	protected Collection<AssociationsInfo> getAssociationInfo(String className) {
		if (mAssociationInfos == null) {
			mAssociationInfos = new HashSet<>();
		}
		mAssociationInfos.clear();
		analyzeClassFields(className, GET_ASSOCIATION_INFO_ACTION);
		return mAssociationInfos;
	}

	/**
	 * Find all the fields in the class. But not each field is supported to add
	 * a column to the table. Only the basic data types and String are
	 * supported. This method will intercept all the types which are not
	 * supported and return a new list of supported fields.
	 * 
	 * @param className
	 *            The full name of the class.
	 * @return A list of supported fields.
	 */
	protected List<Field> getSupportedFields(String className) {
        List<Field> fieldList = classFieldsMap.get(className);
        if (fieldList == null) {
            List<Field> supportedFields = new ArrayList<>();
            Class<?> clazz;
            try {
                clazz = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new DatabaseGenerateException(DatabaseGenerateException.CLASS_NOT_FOUND + className);
            }
            recursiveSupportedFields(clazz, supportedFields);
            classFieldsMap.put(className, supportedFields);
            return supportedFields;
        }
        return fieldList;
	}

    /**
     * Find all supported generic fields in the class. Supporting rule is in {@link BaseUtility#isGenericTypeSupported(String)}.
     * @param className
     *           The full name of the class.
     * @return A list of supported generic fields.
     */
	protected List<Field> getSupportedGenericFields(String className) {
        List<Field> genericFieldList = classGenericFieldsMap.get(className);
        if (genericFieldList == null) {
            List<Field> supportedGenericFields = new ArrayList<>();
            Class<?> clazz;
            try {
                clazz = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new DatabaseGenerateException(DatabaseGenerateException.CLASS_NOT_FOUND + className);
            }
            recursiveSupportedGenericFields(clazz, supportedGenericFields);
            classGenericFieldsMap.put(className, supportedGenericFields);
            return supportedGenericFields;
        }
        return genericFieldList;
	}

	/**
	 * If the field type implements from List or Set, regard it as a collection.
	 * 
	 * @param fieldType
	 *            The field type.
	 * @return True if the field type is collection, false otherwise.
	 */
	protected boolean isCollection(Class<?> fieldType) {
		return isList(fieldType) || isSet(fieldType);
	}

	/**
	 * If the field type implements from List, regard it as a list.
	 * 
	 * @param fieldType
	 *            The field type.
	 * @return True if the field type is List, false otherwise.
	 */
	protected boolean isList(Class<?> fieldType) {
		return List.class.isAssignableFrom(fieldType);
	}

	/**
	 * If the field type implements from Set, regard it as a set.
	 * 
	 * @param fieldType
	 *            The field type.
	 * @return True if the field type is Set, false otherwise.
	 */
	protected boolean isSet(Class<?> fieldType) {
		return Set.class.isAssignableFrom(fieldType);
	}

	/**
	 * Judge the passed in column is an id column or not. The column named id or
	 * _id will be considered as id column.
	 * 
	 * @param columnName
	 *            The name of column.
	 * @return Return true if it's id column, otherwise return false.
	 */
	protected boolean isIdColumn(String columnName) {
		return "_id".equalsIgnoreCase(columnName) || "id".equalsIgnoreCase(columnName);
	}

	/**
	 * If two tables are associated, one table have a foreign key column. The
	 * foreign key column name will be the associated table name with _id
	 * appended.
	 * 
	 * @param associatedTableName
	 *            The associated table name.
	 * @return The foreign key column name.
	 */
	protected String getForeignKeyColumnName(String associatedTableName) {
		return BaseUtility.changeCase(associatedTableName + "_id");
	}

    /**
     * Get the column type for creating table by field type.
     * @param fieldType
     *          Type of field.
     * @return The column type for creating table.
     */
    protected String getColumnType(String fieldType) {
        String columnType;
        for (OrmChange ormChange : typeChangeRules) {
            columnType = ormChange.object2Relation(fieldType);
            if (columnType != null) {
                return columnType;
            }
        }
        return null;
    }

    /**
     * Get the generic type class of List or Set. If there's no generic type of
     * List or Set return null.
     *
     * @param field
     *            A generic type field.
     * @return The generic type of List or Set.
     */
    protected Class<?> getGenericTypeClass(Field field) {
        Type genericType = field.getGenericType();
        if (genericType != null) {
            if (genericType instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) genericType;
                return (Class<?>) parameterizedType.getActualTypeArguments()[0];
            }
        }
        return null;
    }

    private void recursiveSupportedFields(Class<?> clazz, List<Field> supportedFields) {
        if (clazz == LitePalSupport.class || clazz == Object.class) {
            return;
        }
        Field[] fields = clazz.getDeclaredFields();
        if (fields.length > 0) {
            for (Field field : fields) {
                Column annotation = field.getAnnotation(Column.class);
                if (annotation != null && annotation.ignore()) {
                    continue;
                }
                int modifiers = field.getModifiers();
                if (!Modifier.isStatic(modifiers)) {
                    Class<?> fieldTypeClass = field.getType();
                    String fieldType = fieldTypeClass.getName();
                    if (BaseUtility.isFieldTypeSupported(fieldType)) {
                        supportedFields.add(field);
                    }
                }
            }
        }
        recursiveSupportedFields(clazz.getSuperclass(), supportedFields);
    }

    private void recursiveSupportedGenericFields(Class<?> clazz, List<Field> supportedGenericFields) {
        if (clazz == LitePalSupport.class || clazz == Object.class) {
            return;
        }
        Field[] fields = clazz.getDeclaredFields();
        if (fields.length > 0) {
            for (Field field : fields) {
                Column annotation = field.getAnnotation(Column.class);
                if (annotation != null && annotation.ignore()) {
                    continue;
                }
                int modifiers = field.getModifiers();
                if (!Modifier.isStatic(modifiers) && isCollection(field.getType())) {
                    String genericTypeName = getGenericTypeName(field);
                    if (BaseUtility.isGenericTypeSupported(genericTypeName) || clazz.getName().equalsIgnoreCase(genericTypeName)) {
                        supportedGenericFields.add(field);
                    }
                }
            }
        }
        recursiveSupportedGenericFields(clazz.getSuperclass(), supportedGenericFields);
    }

	/**
	 * Introspection of the passed in class. Analyze the fields of current class
	 * and find out the associations of it.
	 * 
	 * @param className
	 *            The class name to introspection.
	 * @param action
	 *            Between {@link org.litepal.LitePalBase#GET_ASSOCIATIONS_ACTION} and
	 *            {@link org.litepal.LitePalBase#GET_ASSOCIATION_INFO_ACTION}
	 */
	private void analyzeClassFields(String className, int action) {
		try {
            Class<?> dynamicClass = Class.forName(className);
			Field[] fields = dynamicClass.getDeclaredFields();
			for (Field field : fields) {
				if (isNonPrimitive(field)) {
                    Column annotation = field.getAnnotation(Column.class);
                    if (annotation != null && annotation.ignore()) {
                        continue;
                    }
					oneToAnyConditions(className, field, action);
					manyToAnyConditions(className, field, action);
				}
			}
		} catch (ClassNotFoundException ex) {
			ex.printStackTrace();
			throw new DatabaseGenerateException(DatabaseGenerateException.CLASS_NOT_FOUND + className);
		}
	}

	/**
	 * Check the field is a non primitive field or not.
	 * 
	 * @param field
	 *            The field to check.
	 * @return True if the field is non primitive, false otherwise.
	 */
	private boolean isNonPrimitive(Field field) {
		return !field.getType().isPrimitive();
	}

    /**
     * Check the field is a private field or not.
     *
     * @param field
     *            The field to check.
     * @return True if the field is private, false otherwise.
     */
	protected boolean isPrivate(Field field) {
        return Modifier.isPrivate(field.getModifiers());
    }

	/**
	 * Deals with one to any association conditions. e.g. Song and Album. An
	 * album have many songs, and a song belongs to one album. So if there's an
	 * Album model defined in Song with private modifier, and in Album there's a
	 * List or Set with generic type of Song and declared as private modifier,
	 * they are one2many association. If there's no List or Set defined in
	 * Album, they will become one2one associations. If there's also a Song
	 * model defined in Album with private modifier, maybe the album just have
	 * one song, they are one2one association too.
	 * 
	 * When it's many2one association, it's easy to just simply add a foreign id
	 * column to the many side model's table. But when it comes to many2many
	 * association, it can not be done without intermediate join table in
	 * database. LitePal assumes that this join table's name is the
	 * concatenation of the two target table names in alphabetical order.
	 * 
	 * @param className
	 *            Source class name.
	 * @param field
	 *            A field of source class.
	 * @param action
	 *            Between {@link org.litepal.LitePalBase#GET_ASSOCIATIONS_ACTION} and
	 *            {@link org.litepal.LitePalBase#GET_ASSOCIATION_INFO_ACTION}
	 */
	private void oneToAnyConditions(String className, Field field, int action) throws ClassNotFoundException {
		Class<?> fieldTypeClass = field.getType();
		// If the mapping list contains the class name
		// defined in one class.
		if (LitePalAttr.getInstance().getClassNames().contains(fieldTypeClass.getName())) {
			Class<?> reverseDynamicClass = Class.forName(fieldTypeClass.getName());
			Field[] reverseFields = reverseDynamicClass.getDeclaredFields();
			// Look up if there's a reverse association
			// definition in the reverse class.
			boolean reverseAssociations = false;
			// Begin to check the fields of the defined
			// class.
            for (Field reverseField : reverseFields) {
                if (!Modifier.isStatic(reverseField.getModifiers())) {
                    Class<?> reverseFieldTypeClass = reverseField.getType();
                    // If there's the from class name in the
                    // defined class, they are one2one bidirectional
                    // associations.
                    if (className.equals(reverseFieldTypeClass.getName())) {
                        if (action == GET_ASSOCIATIONS_ACTION) {
                            addIntoAssociationModelCollection(className, fieldTypeClass.getName(),
                                    fieldTypeClass.getName(), Const.Model.ONE_TO_ONE);
                        } else if (action == GET_ASSOCIATION_INFO_ACTION) {
                            addIntoAssociationInfoCollection(className, fieldTypeClass.getName(),
                                    fieldTypeClass.getName(), field, reverseField, Const.Model.ONE_TO_ONE);
                        }
                        reverseAssociations = true;
                    }
                    // If there's the from class Set or List in
                    // the defined class, they are many2one bidirectional
                    // associations.
                    else if (isCollection(reverseFieldTypeClass)) {
                        String genericTypeName = getGenericTypeName(reverseField);
                        if (className.equals(genericTypeName)) {
                            if (action == GET_ASSOCIATIONS_ACTION) {
                                addIntoAssociationModelCollection(className, fieldTypeClass.getName(),
                                        className, Const.Model.MANY_TO_ONE);
                            } else if (action == GET_ASSOCIATION_INFO_ACTION) {
                                addIntoAssociationInfoCollection(className, fieldTypeClass.getName(),
                                        className, field, reverseField, Const.Model.MANY_TO_ONE);
                            }
                            reverseAssociations = true;
                        }
                    }
                }
            }
            // If there's no from class in the defined class, they are
            // one2one unidirectional associations.
            if (!reverseAssociations) {
                if (action == GET_ASSOCIATIONS_ACTION) {
                    addIntoAssociationModelCollection(className, fieldTypeClass.getName(),
                            fieldTypeClass.getName(), Const.Model.ONE_TO_ONE);
                } else if (action == GET_ASSOCIATION_INFO_ACTION) {
                    addIntoAssociationInfoCollection(className, fieldTypeClass.getName(),
                            fieldTypeClass.getName(), field, null, Const.Model.ONE_TO_ONE);
                }
            }
		}
	}

	/**
	 * Deals with one to any association conditions. e.g. Song and Album. An
	 * album have many songs, and a song belongs to one album. So if there's an
	 * Album model defined in Song with private modifier, and in Album there's a
	 * List or Set with generic type of Song and declared as private modifier,
	 * they are one2many association. If there's no List or Set defined in
	 * Album, they will become one2one associations. If there's also a Song
	 * model defined in Album with private modifier, maybe the album just have
	 * one song, they are one2one association too.
	 * 
	 * When it's many2one association, it's easy to just simply add a foreign id
	 * column to the many side model's table. But when it comes to many2many
	 * association, it can not be done without intermediate join table in
	 * database. LitePal assumes that this join table's name is the
	 * concatenation of the two target table names in alphabetical order.
	 * 
	 * @param className
	 *            Source class name.
	 * @param field
	 *            A field of source class.
	 * @param action
	 *            Between {@link org.litepal.LitePalBase#GET_ASSOCIATIONS_ACTION} and
	 *            {@link org.litepal.LitePalBase#GET_ASSOCIATION_INFO_ACTION}
	 */
	private void manyToAnyConditions(String className, Field field, int action) throws ClassNotFoundException {
		if (isCollection(field.getType())) {
			String genericTypeName = getGenericTypeName(field);
			// If the mapping list contains the genericTypeName, begin to check
			// this genericTypeName class.
			if (LitePalAttr.getInstance().getClassNames().contains(genericTypeName)) {
				Class<?> reverseDynamicClass = Class.forName(genericTypeName);
				Field[] reverseFields = reverseDynamicClass.getDeclaredFields();
				// Look up if there's a reverse association
				// definition in the reverse class.
				boolean reverseAssociations = false;
                for (Field reverseField : reverseFields) {
                    // Only map private fields
                    if (!Modifier.isStatic(reverseField.getModifiers())) {
                        Class<?> reverseFieldTypeClass = reverseField.getType();
                        // If there's a from class name defined in the reverse
                        // class, they are many2one bidirectional
                        // associations.
                        if (className.equals(reverseFieldTypeClass.getName())) {
                            if (action == GET_ASSOCIATIONS_ACTION) {
                                addIntoAssociationModelCollection(className, genericTypeName,
                                        genericTypeName, Const.Model.MANY_TO_ONE);
                            } else if (action == GET_ASSOCIATION_INFO_ACTION) {
                                addIntoAssociationInfoCollection(className, genericTypeName, genericTypeName,
                                        field, reverseField, Const.Model.MANY_TO_ONE);
                            }
                            reverseAssociations = true;
                        }
                        // If there's a List or Set contains from class name
                        // defined in the reverse class, they are many2many
                        // association.
                        else if (isCollection(reverseFieldTypeClass)) {
                            String reverseGenericTypeName = getGenericTypeName(reverseField);
                            if (className.equals(reverseGenericTypeName)) {
                                if (action == GET_ASSOCIATIONS_ACTION) {
                                    if (className.equalsIgnoreCase(genericTypeName)) {
                                        // This is M2M self association condition. Regard as generic model condition.
                                        GenericModel genericModel = new GenericModel();
                                        genericModel.setTableName(DBUtility.getGenericTableName(className, field.getName()));
                                        genericModel.setValueColumnName(DBUtility.getM2MSelfRefColumnName(field));
                                        genericModel.setValueColumnType("integer");
                                        genericModel.setValueIdColumnName(DBUtility.getGenericValueIdColumnName(className));
                                        mGenericModels.add(genericModel);
                                    } else {
                                        addIntoAssociationModelCollection(className, genericTypeName, null,
                                                Const.Model.MANY_TO_MANY);
                                    }
                                } else if (action == GET_ASSOCIATION_INFO_ACTION) {
                                    if (!className.equalsIgnoreCase(genericTypeName)) {
                                        addIntoAssociationInfoCollection(className, genericTypeName, null, field,
                                                reverseField, Const.Model.MANY_TO_MANY);
                                    }
                                }
                                reverseAssociations = true;
                            }
                        }
                    }
                }
                // If there's no from class in the defined class, they
                // are many2one unidirectional associations.
                if (!reverseAssociations) {
                    if (action == GET_ASSOCIATIONS_ACTION) {
                        addIntoAssociationModelCollection(className, genericTypeName,
                                genericTypeName, Const.Model.MANY_TO_ONE);
                    } else if (action == GET_ASSOCIATION_INFO_ACTION) {
                        addIntoAssociationInfoCollection(className, genericTypeName, genericTypeName,
                                field, null, Const.Model.MANY_TO_ONE);
                    }
                }
			} else if(BaseUtility.isGenericTypeSupported(genericTypeName) && action == GET_ASSOCIATIONS_ACTION) {
                GenericModel genericModel = new GenericModel();
                genericModel.setTableName(DBUtility.getGenericTableName(className, field.getName()));
                genericModel.setValueColumnName(DBUtility.convertToValidColumnName(field.getName()));
                genericModel.setValueColumnType(getColumnType(genericTypeName));
                genericModel.setValueIdColumnName(DBUtility.getGenericValueIdColumnName(className));
                mGenericModels.add(genericModel);
            }
		}
	}

	/**
	 * Package a {@link org.litepal.tablemanager.model.AssociationsModel}, and add it into
	 * {@link #mAssociationModels} Collection.
	 * 
	 * @param className
	 *            The class name for {@link org.litepal.tablemanager.model.AssociationsModel}.
	 * @param associatedClassName
	 *            The associated class name for {@link org.litepal.tablemanager.model.AssociationsModel}.
	 * @param classHoldsForeignKey
	 *            The class which holds foreign key.
	 * @param associationType
	 *            The association type for {@link org.litepal.tablemanager.model.AssociationsModel}.
	 */
	private void addIntoAssociationModelCollection(String className, String associatedClassName,
			String classHoldsForeignKey, int associationType) {
		AssociationsModel associationModel = new AssociationsModel();
		associationModel.setTableName(DBUtility.getTableNameByClassName(className));
		associationModel.setAssociatedTableName(DBUtility.getTableNameByClassName(associatedClassName));
		associationModel.setTableHoldsForeignKey(DBUtility.getTableNameByClassName(classHoldsForeignKey));
		associationModel.setAssociationType(associationType);
		mAssociationModels.add(associationModel);
	}

	/**
	 * Package a {@link org.litepal.crud.model.AssociationsInfo}, and add it into
	 * {@link #mAssociationInfos} Collection.
	 * 
	 * @param selfClassName
	 *            The class name of self model.
	 * @param associatedClassName
	 *            The class name of the class which associated with self class.
	 * @param classHoldsForeignKey
	 *            The class which holds foreign key.
	 * @param associateOtherModelFromSelf
	 *            The field of self class to declare has association with other
	 *            class.
	 * @param associateSelfFromOtherModel
	 *            The field of the associated class to declare has association
	 *            with self class.
	 * @param associationType
	 *            The association type.
	 */
	private void addIntoAssociationInfoCollection(String selfClassName, String associatedClassName,
			String classHoldsForeignKey, Field associateOtherModelFromSelf,
			Field associateSelfFromOtherModel, int associationType) {
		AssociationsInfo associationInfo = new AssociationsInfo();
		associationInfo.setSelfClassName(selfClassName);
		associationInfo.setAssociatedClassName(associatedClassName);
		associationInfo.setClassHoldsForeignKey(classHoldsForeignKey);
		associationInfo.setAssociateOtherModelFromSelf(associateOtherModelFromSelf);
		associationInfo.setAssociateSelfFromOtherModel(associateSelfFromOtherModel);
		associationInfo.setAssociationType(associationType);
		mAssociationInfos.add(associationInfo);
	}

	/**
	 * Get the generic type name of List or Set. If there's no generic type of
	 * List or Set return null.
	 * 
	 * @param field
	 *            A generic type field.
	 * @return The name of generic type of List of Set.
	 */
	protected String getGenericTypeName(Field field) {
		Class<?> genericTypeClass = getGenericTypeClass(field);
        if (genericTypeClass != null) {
            return genericTypeClass.getName();
        }
        return null;
	}

    /**
     * Convert a field instance into A ColumnModel instance. ColumnModel can provide information
     * when creating table.
     * @param field
     *          A supported field to map into column.
     * @return ColumnModel instance contains column information.
     */
    private ColumnModel convertFieldToColumnModel(Field field) {
        String fieldType = field.getType().getName();
        String columnType = getColumnType(fieldType);
        boolean nullable = true;
        boolean unique = false;
        boolean hasIndex = false;
        String defaultValue = "";
        Column annotation = field.getAnnotation(Column.class);
        if (annotation != null) {
            nullable = annotation.nullable();
            unique = annotation.unique();
            defaultValue = annotation.defaultValue();
            hasIndex = annotation.index();
        }
        ColumnModel columnModel = new ColumnModel();
        columnModel.setColumnName(DBUtility.convertToValidColumnName(field.getName()));
        columnModel.setColumnType(columnType);
        columnModel.setNullable(nullable);
        columnModel.setUnique(unique);
        columnModel.setDefaultValue(defaultValue);
        columnModel.setHasIndex(hasIndex);
        return columnModel;
    }

}


================================================
FILE: core/src/main/java/org/litepal/LitePalDB.java
================================================
/*
 * Copyright (C)  Tony Green, LitePal Framework Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.litepal;

import org.litepal.parser.LitePalAttr;
import org.litepal.parser.LitePalConfig;
import org.litepal.parser.LitePalParser;

import java.util.ArrayList;
import java.util.List;

/**
 * Configuration of LitePal database. It's similar to litepal.xml configuration, but allows to
 * configure database details at runtime. This is very important when comes to support multiple
 * databases functionality.
 *
 * @author Tony Green
 * @since 1.4
 */
public class LitePalDB {

    /**
     * The version of database.
     */
    private int version;

    /**
     * The name of database.
     */
    private String dbName;

    /**
     * Define where the .db file should be. Option values: internal, external, or path in sdcard.
     */
    private String storage;

    /**
     * Indicates that the database file stores in external storage or not.
     */
    private boolean isExternalStorage = false;

    /**
     * All the model classes that want to map in the database. Each class should
     * be given the full name including package name.
     */
    private List<String> classNames;

    /**
     * Construct a LitePalDB instance from the default configuration by litepal.xml. But database
     * name must be different than the default.
     * @param dbName
     *          Name of database.
     * @return A LitePalDB instance which used the default configuration in litepal.xml but with a specified database name.
     */
    public static LitePalDB fromDefault(String dbName) {
        LitePalConfig config = LitePalParser.parseLitePalConfiguration();
        LitePalDB litePalDB = new LitePalDB(dbName, config.getVersion());
        litePalDB.setStorage(config.getStorage());
        litePalDB.setClassNames(config.getClassNames());
        return litePalDB;
    }

    /**
     * Construct a LitePalDB instance. Database name and version are necessary fields.
     * @param dbName
     *          Name of database.
     * @param version
     *          Version of database.
     */
    public LitePalDB(String dbName, int version) {
        this.dbName = dbName;
        this.version = version;
    }

    public int getVersion() {
        return version;
    }

    public String getDbName() {
        return dbName;
    }

    public String getStorage() {
        return storage;
    }

    public void setStorage(String storage) {
        this.storage = storage;
    }

    public boolean isExternalStorage() {
        return isExternalStorage;
    }

    public void setExternalStorage(boolean isExternalStorage) {
        this.isExternalStorage = isExternalStorage;
    }

    /**
     * Get the class name list. Always add table_schema as a value.
     *
     * @return The class name list.
     */
    public List<String> getClassNames() {
        if (classNames == null) {
            classNames = new ArrayList<String>();
            classNames.add("org.litepal.model.Table_Schema");
        } else if (classNames.isEmpty()) {
            classNames.add("org.litepal.model.Table_Schema");
        }
        return classNames;
    }

    /**
     * Add a class name into the current mapping model list.
     *
     * @param className
     *            Full package class name.
     */
    public void addClassName(String className) {
        getClassNames().add(className);
    }

    void setClassNames(List<String> className) {
        this.classNames = className;
    }

}

================================================
FILE: core/src/main/java/org/litepal/Operator.java
================================================
/*
 * Copyright (C)  Tony Green, LitePal Framework Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.litepal;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import org.litepal.crud.DeleteHandler;
import org.litepal.crud.LitePalSupport;
import org.litepal.crud.QueryHandler;
import org.litepal.crud.SaveHandler;
import org.litepal.crud.UpdateHandler;
import org.litepal.crud.async.AverageExecutor;
import org.litepal.crud.async.CountExecutor;
import org.litepal.crud.async.FindExecutor;
import org.litepal.crud.async.FindMultiExecutor;
import org.litepal.crud.async.SaveExecutor;
import org.litepal.crud.async.UpdateOrDeleteExecutor;
import org.litepal.exceptions.LitePalSupportException;
import org.litepal.parser.LitePalAttr;
import org.litepal.parser.LitePalConfig;
import org.litepal.parser.LitePalParser;
import org.litepal.tablemanager.Connector;
import org.litepal.tablemanager.callback.DatabaseListener;
import org.litepal.util.BaseUtility;
import org.litepal.util.Const;
import org.litepal.util.DBUtility;
import org.litepal.util.SharedUtil;
import org.litepal.util.cipher.CipherUtil;

import java.io.File;
import java.util.Collection;
import java.util.List;

/**
 * LitePal is an Android library that allows developers to use SQLite database extremely easy.
 * You can initialized it by calling {@link #initialize(Context)} method to make LitePal ready to
 * work. Also you can switch the using database by calling {@link #use(LitePalDB)} and {@link #useDefault()}
 * methods.
 *
 * @author Tony Green
 * @since 2.1
 */
public class Operator {

    private static Handler handler = new Handler(Looper.getMainLooper());

    private static DatabaseListener dbListener = null;

    /**
     * Get the main thread handler. You don't need this method. It's used by framework only.
     * @return Main thread handler.
     */
    public static Handler getHandler() {
        return handler;
    }

    /**
     * Initialize to make LitePal ready to work. If you didn't configure LitePalApplication
     * in the AndroidManifest.xml, make sure you call this method as soon as possible. In
     * Application's onCreate() method will be fine.
     *
     * @param context
     * 		Application context.
     */
    public static void initialize(Context context) {
        LitePalApplication.sContext = context;
    }

    /**
     * Get a writable SQLiteDatabase.
     *
     * @return A writable SQLiteDatabase instance
     */
    public static SQLiteDatabase getDatabase() {
        return Connector.getDatabase();
    }

    /**
     * Begins a transaction in EXCLUSIVE mode.
     */
    public static void beginTransaction() {
        getDatabase().beginTransaction();
    }

    /**
     * End a transaction.
     */
    public static void endTransaction() {
        getDatabase().endTransaction();
    }

    /**
     * Marks the current transaction as successful. Do not do any more database work between calling this and calling endTransaction.
     * Do as little non-database work as possible in that situation too.
     * If any errors are encountered between this and endTransaction the transaction will still be committed.
     */
    public static void setTransactionSuccessful() {
        getDatabase().setTransactionSuccessful();
    }

    /**
     * Switch the using database to the one specified by parameter.
     * @param litePalDB
     *          The database to switch to.
     */
    public static void use(LitePalDB litePalDB) {
        synchronized (LitePalSupport.class) {
            LitePalAttr litePalAttr = LitePalAttr.getInstance();
            litePalAttr.setDbName(litePalDB.getDbName());
            litePalAttr.setVersion(litePalDB.getVersion());
            litePalAttr.setStorage(litePalDB.getStorage());
            litePalAttr.setClassNames(litePalDB.getClassNames());
            // set the extra key name only when use database other than default or litepal.xml not exists
            if (!isDefaultDatabase(litePalDB.getDbName())) {
                litePalAttr.setExtraKeyName(litePalDB.getDbName());
                litePalAttr.setCases("lower");
            }
            Connector.clearLitePalOpenHelperInstance();
        }
    }

    /**
     * Switch the using database to default with configuration by litepal.xml.
     */
    public static void useDefault() {
        synchronized (LitePalSupport.class) {
            LitePalAttr.clearInstance();
            Connector.clearLitePalOpenHelperInstance();
        }
    }

    /**
     * Delete the specified database.
     * @param dbName
     *          Name of database to delete.
     * @return True if delete success, false otherwise.
     */
    public static boolean deleteDatabase(String dbName) {
        synchronized (LitePalSupport.class) {
            if (!TextUtils.isEmpty(dbName)) {
                if (!dbName.endsWith(Const.Config.DB_NAME_SUFFIX)) {
                    dbName = dbName + Const.Config.DB_NAME_SUFFIX;
                }
                File dbFile = LitePalApplication.getContext().getDatabasePath(dbName);
                if (dbFile.exists()) {
                    boolean result = dbFile.delete();
                    if (result) {
                        removeVersionInSharedPreferences(dbName);
                        Connector.clearLitePalOpenHelperInstance();
                    }
                    return result;
                }
                String path = LitePalApplication.getContext().getExternalFilesDir("") + "/databases/";
                dbFile = new File(path + dbName);
                boolean result = dbFile.delete();
                if (result) {
                    removeVersionInSharedPreferences(dbName);
                    Connector.clearLitePalOpenHelperInstance();
                }
                return result;
            }
            return false;
        }
    }

    public static void aesKey(String key) {
        CipherUtil.aesKey = key;
    }

    /**
     * Remove the database version in SharedPreferences file.
     * @param dbName
     *          Name of database to delete.
     */
    private static void removeVersionInSharedPreferences(String dbName) {
        if (isDefaultDatabase(dbName)) {
            SharedUtil.removeVersion(null);
        } else {
            SharedUtil.removeVersion(dbName);
        }
    }

    /**
     * Check the dbName is default database or not. If it's same as dbName in litepal.xml, then it is
     * default database.
     * @param dbName
     *          Name of database to check.
     * @return True if it's default database, false otherwise.
     */
    private static boolean isDefaultDatabase(String dbName) {
        if (BaseUtility.isLitePalXMLExists()) {
            if (!dbName.endsWith(Const.Config.DB_NAME_SUFFIX)) {
                dbName = dbName + Const.Config.DB_NAME_SUFFIX;
            }
            LitePalConfig config = LitePalParser.parseLitePalConfiguration();
            String defaultDbName = config.getDbName();
            if (!defaultDbName.endsWith(Const.Config.DB_NAME_SUFFIX)) {
                defaultDbName = defaultDbName + Const.Config.DB_NAME_SUFFIX;
            }
            return dbName.equalsIgnoreCase(defaultDbName);
        }
        return false;
    }

    /**
     * Declaring to query which columns in table.
     *
     * <pre>
     * LitePal.select(&quot;name&quot;, &quot;age&quot;).find(Person.class);
     * </pre>
     *
     * This will find all rows with name and age columns in Person table.
     *
     * @param columns
     *            A String array of which columns to return. Passing null will
     *            return all columns.
     *
     * @return A FluentQuery instance.
     */
    public static FluentQuery select(String... columns) {
        FluentQuery cQuery = new FluentQuery();
        cQuery.mColumns = columns;
        return cQuery;
    }

    /**
     * Declaring to query which rows in table.
     *
     * <pre>
     * LitePal.where(&quot;name = ? or age &gt; ?&quot;, &quot;Tom&quot;, &quot;14&quot;).find(Person.class);
     * </pre>
     *
     * This will find rows which name is Tom or age greater than 14 in Person
     * table.
     *
     * @param conditions
     *            A filter declaring which rows to return, formatted as an SQL
     *            WHERE clause. Passing null will return all rows.
     * @return A FluentQuery instance.
     */
    public static FluentQuery where(String... conditions) {
        FluentQuery cQuery = new FluentQuery();
        cQuery.mConditions = conditions;
        return cQuery;
    }

    /**
     * Declaring how to order the rows queried from table.
     *
     * <pre>
     * LitePal.order(&quot;name desc&quot;).find(Person.class);
     * </pre>
     *
     * This will find all rows in Person table sorted by name with inverted
     * order.
     *
     * @param column
     *            How to order the rows, formatted as an SQL ORDER BY clause.
     *            Passing null will use the default sort order, which may be
     *            unordered.
     * @return A FluentQuery instance.
     */
    public static FluentQuery order(String column) {
        FluentQuery cQuery = new FluentQuery();
        cQuery.mOrderBy = column;
        return cQuery;
    }

    /**
     * Limits the number of rows returned by the query.
     *
     * <pre>
     * LitePal.limit(2).find(Person.class);
     * </pre>
     *
     * This will find the top 2 rows in Person table.
     *
     * @param value
     *            Limits the number of rows returned by the query, formatted as
     *            LIMIT clause.
     * @return A FluentQuery instance.
     */
    public static FluentQuery limit(int value) {
        FluentQuery cQuery = new FluentQuery();
        cQuery.mLimit = String.valueOf(value);
        return cQuery;
    }

    /**
     * Declaring the offset of rows returned by the query. This method must be
     * used with {@link #limit(int)}, or nothing will return.
     *
     * <pre>
     * LitePal.limit(1).offset(2).find(Person.class);
     * </pre>
     *
     * This will find the third row in Person table.
     *
     * @param value
     *            The offset amount of rows returned by the query.
     * @return A FluentQuery instance.
     */
    public static FluentQuery offset(int value) {
        FluentQuery cQuery = new FluentQuery();
        cQuery.mOffset = String.valueOf(value);
        return cQuery;
    }

    /**
     * Count the records.
     *
     * <pre>
     * LitePal.count(Person.class);
     * </pre>
     *
     * This will count all rows in person table.<br>
     * You can also specify a where clause when counting.
     *
     * <pre>
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).count(Person.class);
     * </pre>
     *
     * @param modelClass
     *            Which table to query from by class.
     * @return Count of the specified table.
     */
    public static int count(Class<?> modelClass) {
        return count(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())));
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static CountExecutor countAsync(final Class<?> modelClass) {
        return countAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())));
    }

    /**
     * Count the records.
     *
     * <pre>
     * LitePal.count(&quot;person&quot;);
     * </pre>
     *
     * This will count all rows in person table.<br>
     * You can also specify a where clause when counting.
     *
     * <pre>
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).count(&quot;person&quot;);
     * </pre>
     *
     * @param tableName
     *            Which table to query from.
     * @return Count of the specified table.
     */
    public static int count(String tableName) {
        synchronized (LitePalSupport.class) {
            FluentQuery cQuery = new FluentQuery();
            return cQuery.count(tableName);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static CountExecutor countAsync(final String tableName) {
        final CountExecutor executor = new CountExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final int count = count(tableName);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(count);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Calculates the average value on a given column.
     *
     * <pre>
     * LitePal.average(Person.class, &quot;age&quot;);
     * </pre>
     *
     * You can also specify a where clause when calculating.
     *
     * <pre>
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).average(Person.class, &quot;age&quot;);
     * </pre>
     *
     * @param modelClass
     *            Which table to query from by class.
     * @param column
     *            The based on column to calculate.
     * @return The average value on a given column.
     */
    public static double average(Class<?> modelClass, String column) {
        return average(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), column);
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static AverageExecutor averageAsync(final Class<?> modelClass, final String column) {
        return averageAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), column);
    }

    /**
     * Calculates the average value on a given column.
     *
     * <pre>
     * LitePal.average(&quot;person&quot;, &quot;age&quot;);
     * </pre>
     *
     * You can also specify a where clause when calculating.
     *
     * <pre>
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).average(&quot;person&quot;, &quot;age&quot;);
     * </pre>
     *
     * @param tableName
     *            Which table to query from.
     * @param column
     *            The based on column to calculate.
     * @return The average value on a given column.
     */
    public static double average(String tableName, String column) {
        synchronized (LitePalSupport.class) {
            FluentQuery cQuery = new FluentQuery();
            return cQuery.average(tableName, column);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static AverageExecutor averageAsync(final String tableName, final String column) {
        final AverageExecutor executor = new AverageExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final double average = average(tableName, column);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(average);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Calculates the maximum value on a given column. The value is returned
     * with the same data type of the column.
     *
     * <pre>
     * LitePal.max(Person.class, &quot;age&quot;, int.class);
     * </pre>
     *
     * You can also specify a where clause when calculating.
     *
     * <pre>
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).max(Person.class, &quot;age&quot;, Integer.TYPE);
     * </pre>
     *
     * @param modelClass
     *            Which table to query from by class.
     * @param columnName
     *            The based on column to calculate.
     * @param columnType
     *            The type of the based on column.
     * @return The maximum value on a given column.
     */
    public static <T> T max(Class<?> modelClass, String columnName, Class<T> columnType) {
        return max(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), columnName, columnType);
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> maxAsync(final Class<?> modelClass, final String columnName, final Class<T> columnType) {
        return maxAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), columnName, columnType);
    }

    /**
     * Calculates the maximum value on a given column. The value is returned
     * with the same data type of the column.
     *
     * <pre>
     * LitePal.max(&quot;person&quot;, &quot;age&quot;, int.class);
     * </pre>
     *
     * You can also specify a where clause when calculating.
     *
     * <pre>
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).max(&quot;person&quot;, &quot;age&quot;, Integer.TYPE);
     * </pre>
     *
     * @param tableName
     *            Which table to query from.
     * @param columnName
     *            The based on column to calculate.
     * @param columnType
     *            The type of the based on column.
     * @return The maximum value on a given column.
     */
    public static <T> T max(String tableName, String columnName, Class<T> columnType) {
        synchronized (LitePalSupport.class) {
            FluentQuery cQuery = new FluentQuery();
            return cQuery.max(tableName, columnName, columnType);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> maxAsync(final String tableName, final String columnName, final Class<T> columnType) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = max(tableName, columnName, columnType);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Calculates the minimum value on a given column. The value is returned
     * with the same data type of the column.
     *
     * <pre>
     * LitePal.min(Person.class, &quot;age&quot;, int.class);
     * </pre>
     *
     * You can also specify a where clause when calculating.
     *
     * <pre>
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).min(Person.class, &quot;age&quot;, Integer.TYPE);
     * </pre>
     *
     * @param modelClass
     *            Which table to query from by class.
     * @param columnName
     *            The based on column to calculate.
     * @param columnType
     *            The type of the based on column.
     * @return The minimum value on a given column.
     */
    public static <T> T min(Class<?> modelClass, String columnName, Class<T> columnType) {
        return min(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), columnName, columnType);
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> minAsync(final Class<?> modelClass, final String columnName, final Class<T> columnType) {
        return minAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), columnName, columnType);
    }

    /**
     * Calculates the minimum value on a given column. The value is returned
     * with the same data type of the column.
     *
     * <pre>
     * LitePal.min(&quot;person&quot;, &quot;age&quot;, int.class);
     * </pre>
     *
     * You can also specify a where clause when calculating.
     *
     * <pre>
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).min(&quot;person&quot;, &quot;age&quot;, Integer.TYPE);
     * </pre>
     *
     * @param tableName
     *            Which table to query from.
     * @param columnName
     *            The based on column to calculate.
     * @param columnType
     *            The type of the based on column.
     * @return The minimum value on a given column.
     */
    public static <T> T min(String tableName, String columnName, Class<T> columnType) {
        synchronized (LitePalSupport.class) {
            FluentQuery cQuery = new FluentQuery();
            return cQuery.min(tableName, columnName, columnType);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> minAsync(final String tableName, final String columnName, final Class<T> columnType) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = min(tableName, columnName, columnType);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Calculates the sum of values on a given column. The value is returned
     * with the same data type of the column.
     *
     * <pre>
     * LitePal.sum(Person.class, &quot;age&quot;, int.class);
     * </pre>
     *
     * You can also specify a where clause when calculating.
     *
     * <pre>
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).sum(Person.class, &quot;age&quot;, Integer.TYPE);
     * </pre>
     *
     * @param modelClass
     *            Which table to query from by class.
     * @param columnName
     *            The based on column to calculate.
     * @param columnType
     *            The type of the based on column.
     * @return The sum value on a given column.
     */
    public static <T> T sum(Class<?> modelClass, String columnName, Class<T> columnType) {
        return sum(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), columnName, columnType);
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> sumAsync(final Class<?> modelClass, final String columnName, final Class<T> columnType) {
        return sumAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(modelClass.getName())), columnName, columnType);
    }

    /**
     * Calculates the sum of values on a given column. The value is returned
     * with the same data type of the column.
     *
     * <pre>
     * LitePal.sum(&quot;person&quot;, &quot;age&quot;, int.class);
     * </pre>
     *
     * You can also specify a where clause when calculating.
     *
     * <pre>
     * LitePal.where(&quot;age &gt; ?&quot;, &quot;15&quot;).sum(&quot;person&quot;, &quot;age&quot;, Integer.TYPE);
     * </pre>
     *
     * @param tableName
     *            Which table to query from.
     * @param columnName
     *            The based on column to calculate.
     * @param columnType
     *            The type of the based on column.
     * @return The sum value on a given column.
     */
    public static <T> T sum(String tableName, String columnName, Class<T> columnType) {
        synchronized (LitePalSupport.class) {
            FluentQuery cQuery = new FluentQuery();
            return cQuery.sum(tableName, columnName, columnType);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> sumAsync(final String tableName, final String columnName, final Class<T> columnType) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = sum(tableName, columnName, columnType);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Finds the record by a specific id.
     *
     * <pre>
     * Person p = LitePal.find(Person.class, 1);
     * </pre>
     *
     * The modelClass determines which table to query and the object type to
     * return. If no record can be found, then return null. <br>
     *
     * Note that the associated models won't be loaded by default considering
     * the efficiency, but you can do that by using
     * {@link Operator#find(Class, long, boolean)}.
     *
     * @param modelClass
     *            Which table to query and the object type to return.
     * @param id
     *            Which record to query.
     * @return An object with found data from database, or null.
     */
    public static <T> T find(Class<T> modelClass, long id) {
        return find(modelClass, id, false);
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> findAsync(Class<T> modelClass, long id) {
        return findAsync(modelClass, id, false);
    }

    /**
     * It is mostly same as {@link Operator#find(Class, long)} but an isEager
     * parameter. If set true the associated models will be loaded as well.
     * <br>
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
     *
     * @param modelClass
     *            Which table to query and the object type to return.
     * @param id
     *            Which record to query.
     * @param isEager
     *            True to load the associated models, false not.
     * @return An object with found data from database, or null.
     */
    public static <T> T find(Class<T> modelClass, long id, boolean isEager) {
        synchronized (LitePalSupport.class) {
            QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());
            return queryHandler.onFind(modelClass, id, isEager);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> findAsync(final Class<T> modelClass, final long id, final boolean isEager) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = find(modelClass, id, isEager);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Finds the first record of a single table.
     *
     * <pre>
     * Person p = LitePal.findFirst(Person.class);
     * </pre>
     *
     * Note that the associated models won't be loaded by default considering
     * the efficiency, but you can do that by using
     * {@link Operator#findFirst(Class, boolean)}.
     *
     * @param modelClass
     *            Which table to query and the object type to return.
     * @return An object with data of first row, or null.
     */
    public static <T> T findFirst(Class<T> modelClass) {
        return findFirst(modelClass, false);
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> findFirstAsync(Class<T> modelClass) {
        return findFirstAsync(modelClass, false);
    }

    /**
     * It is mostly same as {@link Operator#findFirst(Class)} but an isEager
     * parameter. If set true the associated models will be loaded as well.
     * <br>
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
     *
     * @param modelClass
     *            Which table to query and the object type to return.
     * @param isEager
     *            True to load the associated models, false not.
     * @return An object with data of first row, or null.
     */
    public static <T> T findFirst(Class<T> modelClass, boolean isEager) {
        synchronized (LitePalSupport.class) {
            QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());
            return queryHandler.onFindFirst(modelClass, isEager);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> findFirstAsync(final Class<T> modelClass, final boolean isEager) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = findFirst(modelClass, isEager);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Finds the last record of a single table.
     *
     * <pre>
     * Person p = LitePal.findLast(Person.class);
     * </pre>
     *
     * Note that the associated models won't be loaded by default considering
     * the efficiency, but you can do that by using
     * {@link Operator#findLast(Class, boolean)}.
     *
     * @param modelClass
     *            Which table to query and the object type to return.
     * @return An object with data of last row, or null.
     */
    public static <T> T findLast(Class<T> modelClass) {
        return findLast(modelClass, false);
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> findLastAsync(Class<T> modelClass) {
        return findLastAsync(modelClass, false);
    }

    /**
     * It is mostly same as {@link Operator#findLast(Class)} but an isEager
     * parameter. If set true the associated models will be loaded as well.
     * <br>
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
     *
     * @param modelClass
     *            Which table to query and the object type to return.
     * @param isEager
     *            True to load the associated models, false not.
     * @return An object with data of last row, or null.
     */
    public static <T> T findLast(Class<T> modelClass, boolean isEager) {
        synchronized (LitePalSupport.class) {
            QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());
            return queryHandler.onFindLast(modelClass, isEager);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindExecutor<T> findLastAsync(final Class<T> modelClass, final boolean isEager) {
        final FindExecutor<T> executor = new FindExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final T t = findLast(modelClass, isEager);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Finds multiple records by an id array.
     *
     * <pre>
     * List&lt;Person&gt; people = LitePal.findAll(Person.class, 1, 2, 3);
     *
     * long[] bookIds = { 10, 18 };
     * List&lt;Book&gt; books = LitePal.findAll(Book.class, bookIds);
     * </pre>
     *
     * Of course you can find all records by passing nothing to the ids
     * parameter.
     *
     * <pre>
     * List&lt;Book&gt; allBooks = LitePal.findAll(Book.class);
     * </pre>
     *
     * Note that the associated models won't be loaded by default considering
     * the efficiency, but you can do that by using
     * {@link Operator#findAll(Class, boolean, long...)}.
     *
     * The modelClass determines which table to query and the object type to
     * return.
     *
     * @param modelClass
     *            Which table to query and the object type to return as a list.
     * @param ids
     *            Which records to query. Or do not pass it to find all records.
     * @return An object list with found data from database, or an empty list.
     */
    public static <T> List<T> findAll(Class<T> modelClass, long... ids) {
        return findAll(modelClass, false, ids);
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindMultiExecutor<T> findAllAsync(Class<T> modelClass, long... ids) {
        return findAllAsync(modelClass, false, ids);
    }

    /**
     * It is mostly same as {@link Operator#findAll(Class, long...)} but an
     * isEager parameter. If set true the associated models will be loaded as well.
     * <br>
     * Note that isEager will only work for one deep level relation, considering the query efficiency.
     * You have to implement on your own if you need to load multiple deepness of relation at once.
     *
     * @param modelClass
     *            Which table to query and the object type to return as a list.
     * @param isEager
     *            True to load the associated models, false not.
     * @param ids
     *            Which records to query. Or do not pass it to find all records.
     * @return An object list with found data from database, or an empty list.
     */
    public static <T> List<T> findAll(Class<T> modelClass, boolean isEager,
                                      long... ids) {
        synchronized (LitePalSupport.class) {
            QueryHandler queryHandler = new QueryHandler(Connector.getDatabase());
            return queryHandler.onFindAll(modelClass, isEager, ids);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static <T> FindMultiExecutor<T> findAllAsync(final Class<T> modelClass, final boolean isEager, final long... ids) {
        final FindMultiExecutor<T> executor = new FindMultiExecutor<>();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final List<T> t = findAll(modelClass, isEager, ids);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(t);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Runs the provided SQL and returns a Cursor over the result set. You may
     * include ? in where clause in the query, which will be replaced by the
     * second to the last parameters, such as:
     *
     * <pre>
     * Cursor cursor = LitePal.findBySQL(&quot;select * from person where name=? and age=?&quot;, &quot;Tom&quot;, &quot;14&quot;);
     * </pre>
     *
     * @param sql
     *            First parameter is the SQL clause to apply. Second to the last
     *            parameters will replace the place holders.
     * @return A Cursor object, which is positioned before the first entry. Note
     *         that Cursors are not synchronized, see the documentation for more
     *         details.
     */
    public static Cursor findBySQL(String... sql) {
        synchronized (LitePalSupport.class) {
            BaseUtility.checkConditionsCorrect(sql);
            if (sql == null) {
                return null;
            }
            if (sql.length <= 0) {
                return null;
            }
            String[] selectionArgs;
            if (sql.length == 1) {
                selectionArgs = null;
            } else {
                selectionArgs = new String[sql.length - 1];
                System.arraycopy(sql, 1, selectionArgs, 0, sql.length - 1);
            }
            return Connector.getDatabase().rawQuery(sql[0], selectionArgs);
        }
    }

    /**
     * Deletes the record in the database by id.<br>
     * The data in other tables which is referenced with the record will be
     * removed too.
     *
     * <pre>
     * LitePal.delete(Person.class, 1);
     * </pre>
     *
     * This means that the record 1 in person table will be removed.
     *
     * @param modelClass
     *            Which table to delete from by class.
     * @param id
     *            Which record to delete.
     * @return The number of rows affected. Including cascade delete rows.
     */
    public static int delete(Class<?> modelClass, long id) {
        synchronized (LitePalSupport.class) {
            int rowsAffected;
            SQLiteDatabase db = Connector.getDatabase();
            db.beginTransaction();
            try {
                DeleteHandler deleteHandler = new DeleteHandler(db);
                rowsAffected = deleteHandler.onDelete(modelClass, id);
                db.setTransactionSuccessful();
                return rowsAffected;
            } finally {
                db.endTransaction();
            }
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static UpdateOrDeleteExecutor deleteAsync(final Class<?> modelClass, final long id) {
        final UpdateOrDeleteExecutor executor = new UpdateOrDeleteExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final int rowsAffected = delete(modelClass, id);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(rowsAffected);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Deletes all records with details given if they match a set of conditions
     * supplied. This method constructs a single SQL DELETE statement and sends
     * it to the database.
     *
     * <pre>
     * LitePal.deleteAll(Person.class, &quot;name = ? and age = ?&quot;, &quot;Tom&quot;, &quot;14&quot;);
     * </pre>
     *
     * This means that all the records which name is Tom and age is 14 will be
     * removed.<br>
     *
     * @param modelClass
     *            Which table to delete from by class.
     * @param conditions
     *            A string array representing the WHERE part of an SQL
     *            statement. First parameter is the WHERE clause to apply when
     *            deleting. The way of specifying place holders is to insert one
     *            or more question marks in the SQL. The first question mark is
     *            replaced by the second element of the array, the next question
     *            mark by the third, and so on. Passing empty string will update
     *            all rows.
     * @return The number of rows affected.
     */
    public static int deleteAll(Class<?> modelClass, String... conditions) {
        synchronized (LitePalSupport.class) {
            int rowsAffected;
            SQLiteDatabase db = Connector.getDatabase();
            db.beginTransaction();
            try {
                DeleteHandler deleteHandler = new DeleteHandler(db);
                rowsAffected = deleteHandler.onDeleteAll(modelClass, conditions);
                db.setTransactionSuccessful();
                return rowsAffected;
            } finally {
                db.endTransaction();
            }
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static UpdateOrDeleteExecutor deleteAllAsync(final Class<?> modelClass, final String... conditions) {
        final UpdateOrDeleteExecutor executor = new UpdateOrDeleteExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final int rowsAffected = deleteAll(modelClass, conditions);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(rowsAffected);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Deletes all records with details given if they match a set of conditions
     * supplied. This method constructs a single SQL DELETE statement and sends
     * it to the database.
     *
     * <pre>
     * LitePal.deleteAll(&quot;person&quot;, &quot;name = ? and age = ?&quot;, &quot;Tom&quot;, &quot;14&quot;);
     * </pre>
     *
     * This means that all the records which name is Tom and age is 14 will be
     * removed.<br>
     *
     * Note that this method won't delete the referenced data in other tables.
     * You should remove those values by your own.
     *
     * @param tableName
     *            Which table to delete from.
     * @param conditions
     *            A string array representing the WHERE part of an SQL
     *            statement. First parameter is the WHERE clause to apply when
     *            deleting. The way of specifying place holders is to insert one
     *            or more question marks in the SQL. The first question mark is
     *            replaced by the second element of the array, the next question
     *            mark by the third, and so on. Passing empty string will update
     *            all rows.
     * @return The number of rows affected.
     */
    public static int deleteAll(String tableName, String... conditions) {
        synchronized (LitePalSupport.class) {
            DeleteHandler deleteHandler = new DeleteHandler(Connector.getDatabase());
            return deleteHandler.onDeleteAll(tableName, conditions);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static UpdateOrDeleteExecutor deleteAllAsync(final String tableName, final String... conditions) {
        final UpdateOrDeleteExecutor executor = new UpdateOrDeleteExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final int rowsAffected = deleteAll(tableName, conditions);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(rowsAffected);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Updates the corresponding record by id with ContentValues. Returns the
     * number of affected rows.
     *
     * <pre>
     * ContentValues cv = new ContentValues();
     * cv.put(&quot;name&quot;, &quot;Jim&quot;);
     * LitePal.update(Person.class, cv, 1);
     * </pre>
     *
     * This means that the name of record 1 will be updated into Jim.<br>
     *
     * @param modelClass
     *            Which table to update by class.
     * @param values
     *            A map from column names to new column values. null is a valid
     *            value that will be translated to NULL.
     * @param id
     *            Which record to update.
     * @return The number of rows affected.
     */
    public static int update(Class<?> modelClass, ContentValues values, long id) {
        synchronized (LitePalSupport.class) {
            UpdateHandler updateHandler = new UpdateHandler(Connector.getDatabase());
            return updateHandler.onUpdate(modelClass, id, values);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static UpdateOrDeleteExecutor updateAsync(final Class<?> modelClass, final ContentValues values, final long id) {
        final UpdateOrDeleteExecutor executor = new UpdateOrDeleteExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final int rowsAffected = update(modelClass, values, id);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(rowsAffected);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Updates all records with details given if they match a set of conditions
     * supplied. This method constructs a single SQL UPDATE statement and sends
     * it to the database.
     *
     * <pre>
     * ContentValues cv = new ContentValues();
     * cv.put(&quot;name&quot;, &quot;Jim&quot;);
     * LitePal.update(Person.class, cv, &quot;name = ?&quot;, &quot;Tom&quot;);
     * </pre>
     *
     * This means that all the records which name is Tom will be updated into
     * Jim.
     *
     * @param modelClass
     *            Which table to update by class.
     * @param values
     *            A map from column names to new column values. null is a valid
     *            value that will be translated to NULL.
     * @param conditions
     *            A string array representing the WHERE part of an SQL
     *            statement. First parameter is the WHERE clause to apply when
     *            updating. The way of specifying place holders is to insert one
     *            or more question marks in the SQL. The first question mark is
     *            replaced by the second element of the array, the next question
     *            mark by the third, and so on. Passing empty string will update
     *            all rows.
     * @return The number of rows affected.
     */
    public static int updateAll(Class<?> modelClass, ContentValues values,
                                String... conditions) {
        return updateAll(BaseUtility.changeCase(DBUtility.getTableNameByClassName(
                modelClass.getName())), values, conditions);
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static UpdateOrDeleteExecutor updateAllAsync(Class<?> modelClass, ContentValues values, String... conditions) {
        return updateAllAsync(BaseUtility.changeCase(DBUtility.getTableNameByClassName(
                modelClass.getName())), values, conditions);
    }

    /**
     * Updates all records with details given if they match a set of conditions
     * supplied. This method constructs a single SQL UPDATE statement and sends
     * it to the database.
     *
     * <pre>
     * ContentValues cv = new ContentValues();
     * cv.put(&quot;name&quot;, &quot;Jim&quot;);
     * LitePal.update(&quot;person&quot;, cv, &quot;name = ?&quot;, &quot;Tom&quot;);
     * </pre>
     *
     * This means that all the records which name is Tom will be updated into
     * Jim.
     *
     * @param tableName
     *            Which table to update.
     * @param values
     *            A map from column names to new column values. null is a valid
     *            value that will be translated to NULL.
     * @param conditions
     *            A string array representing the WHERE part of an SQL
     *            statement. First parameter is the WHERE clause to apply when
     *            updating. The way of specifying place holders is to insert one
     *            or more question marks in the SQL. The first question mark is
     *            replaced by the second element of the array, the next question
     *            mark by the third, and so on. Passing empty string will update
     *            all rows.
     * @return The number of rows affected.
     */
    public static int updateAll(String tableName, ContentValues values,
                                String... conditions) {
        synchronized (LitePalSupport.class) {
            UpdateHandler updateHandler = new UpdateHandler(Connector.getDatabase());
            return updateHandler.onUpdateAll(tableName, values, conditions);
        }
    }

    /**
     * This method is deprecated and will be removed in the future releases.
     * Handle async db operation in your own logic instead.
     */
    @Deprecated
    public static UpdateOrDeleteExecutor updateAllAsync(final String tableName, final ContentValues values, final String... conditions) {
        final UpdateOrDeleteExecutor executor = new UpdateOrDeleteExecutor();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                synchronized (LitePalSupport.class) {
                    final int rowsAffected = updateAll(tableName, values, conditions);
                    if (executor.getListener() != null) {
                        Operator.getHandler().post(new Runnable() {
                            @Override
                            public void run() {
                                executor.getListener().onFinish(rowsAffected);
                            }
                        });
                    }
                }
            }
        };
        executor.submit(runnable);
        return executor;
    }

    /**
     * Saves the collection into database. <br>
     *
     * <pre>
     * LitePal.saveAll(people);
     * </pre>
     *
     * If the model in collection is a new record gets created in the database,
     * otherwise the existing record gets updated.<br>
     * If saving process failed by any accident, the whole action will be
     * cancelled and your database will be <b>rolled back</b>. <br>
     * This method acts the same result as the below way, but <b>much more
     * efficient</b>.
     *
     * <pre>
     * for (Person person : people) {
     * 	person.save();
     * }
     * </pre>
     *
     * So when your collection holds huge of models, saveAll(Collection) is the better choice.
     *
     * @param collection
     *            Holds all models to save.
     * @return True if all records in collection are saved. False none record in collection is saved. There wo
Download .txt
gitextract__kl11lqh/

├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── core/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── org/
│           │       └── litepal/
│           │           ├── FluentQuery.java
│           │           ├── LitePal.kt
│           │           ├── LitePalApplication.java
│           │           ├── LitePalBase.java
│           │           ├── LitePalDB.java
│           │           ├── Operator.java
│           │           ├── annotation/
│           │           │   ├── Column.java
│           │           │   └── Encrypt.java
│           │           ├── crud/
│           │           │   ├── AssociationsAnalyzer.java
│           │           │   ├── DataHandler.java
│           │           │   ├── DeleteHandler.java
│           │           │   ├── DynamicExecutor.java
│           │           │   ├── LitePalSupport.java
│           │           │   ├── Many2ManyAnalyzer.java
│           │           │   ├── Many2OneAnalyzer.java
│           │           │   ├── One2OneAnalyzer.java
│           │           │   ├── QueryHandler.java
│           │           │   ├── SaveHandler.java
│           │           │   ├── UpdateHandler.java
│           │           │   ├── async/
│           │           │   │   ├── AsyncExecutor.java
│           │           │   │   ├── AverageExecutor.java
│           │           │   │   ├── CountExecutor.java
│           │           │   │   ├── FindExecutor.java
│           │           │   │   ├── FindMultiExecutor.java
│           │           │   │   ├── SaveExecutor.java
│           │           │   │   └── UpdateOrDeleteExecutor.java
│           │           │   ├── callback/
│           │           │   │   ├── AverageCallback.java
│           │           │   │   ├── CountCallback.java
│           │           │   │   ├── FindCallback.java
│           │           │   │   ├── FindMultiCallback.java
│           │           │   │   ├── SaveCallback.java
│           │           │   │   └── UpdateOrDeleteCallback.java
│           │           │   └── model/
│           │           │       └── AssociationsInfo.java
│           │           ├── exceptions/
│           │           │   ├── DataSupportException.java
│           │           │   ├── DatabaseGenerateException.java
│           │           │   ├── GlobalException.java
│           │           │   ├── InvalidAttributesException.java
│           │           │   ├── LitePalSupportException.java
│           │           │   └── ParseConfigurationFileException.java
│           │           ├── extension/
│           │           │   ├── FluentQuery.kt
│           │           │   └── LitePal.kt
│           │           ├── model/
│           │           │   └── Table_Schema.java
│           │           ├── parser/
│           │           │   ├── LitePalAttr.java
│           │           │   ├── LitePalConfig.java
│           │           │   ├── LitePalContentHandler.java
│           │           │   └── LitePalParser.java
│           │           ├── tablemanager/
│           │           │   ├── AssociationCreator.java
│           │           │   ├── AssociationUpdater.java
│           │           │   ├── Connector.java
│           │           │   ├── Creator.java
│           │           │   ├── Dropper.java
│           │           │   ├── Generator.java
│           │           │   ├── LitePalOpenHelper.java
│           │           │   ├── Upgrader.java
│           │           │   ├── callback/
│           │           │   │   └── DatabaseListener.java
│           │           │   ├── model/
│           │           │   │   ├── AssociationsModel.java
│           │           │   │   ├── ColumnModel.java
│           │           │   │   ├── GenericModel.java
│           │           │   │   └── TableModel.java
│           │           │   └── typechange/
│           │           │       ├── BlobOrm.java
│           │           │       ├── BooleanOrm.java
│           │           │       ├── DateOrm.java
│           │           │       ├── DecimalOrm.java
│           │           │       ├── NumericOrm.java
│           │           │       ├── OrmChange.java
│           │           │       └── TextOrm.java
│           │           └── util/
│           │               ├── BaseUtility.java
│           │               ├── Const.java
│           │               ├── DBUtility.java
│           │               ├── LitePalLog.java
│           │               ├── SharedUtil.java
│           │               └── cipher/
│           │                   ├── AESCrypt.java
│           │                   └── CipherUtil.java
│           └── res/
│               └── values/
│                   └── strings.xml
├── downloads/
│   ├── litepal-1.1.0-src.jar
│   ├── litepal-1.1.0.jar
│   ├── litepal-1.1.1-src.jar
│   ├── litepal-1.1.1.jar
│   ├── litepal-1.2.0-src.jar
│   ├── litepal-1.2.0.jar
│   ├── litepal-1.2.1-src.jar
│   ├── litepal-1.2.1.jar
│   ├── litepal-1.3.0-src.jar
│   ├── litepal-1.3.0.jar
│   ├── litepal-1.3.1-src.jar
│   ├── litepal-1.3.1.jar
│   ├── litepal-1.3.2-src.jar
│   ├── litepal-1.3.2.jar
│   ├── litepal-1.4.0-src.jar
│   ├── litepal-1.4.0.jar
│   ├── litepal-1.4.1-src.jar
│   ├── litepal-1.4.1.jar
│   ├── litepal-1.5.1-src.jar
│   ├── litepal-1.5.1.jar
│   ├── litepal-1.6.0-src.jar
│   ├── litepal-1.6.0.jar
│   ├── litepal-1.6.1-src.jar
│   ├── litepal-1.6.1.jar
│   ├── litepal-2.0.0-src.jar
│   └── litepal-2.0.0.jar
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── java/
│   ├── .gitignore
│   ├── bintray.gradle
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── org/
│           │       └── litepal/
│           │           └── LitePal.java
│           └── res/
│               └── values/
│                   └── strings.xml
├── kotlin/
│   ├── .gitignore
│   ├── bintray.gradle
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── org/
│           │       └── litepal/
│           │           ├── LitePal.kt
│           │           └── extension/
│           │               ├── FluentQuery.kt
│           │               └── LitePal.kt
│           └── res/
│               └── values/
│                   └── strings.xml
├── sample/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── litepaltest/
│       │               ├── model/
│       │               │   ├── Book.java
│       │               │   ├── Cellphone.java
│       │               │   ├── Classroom.java
│       │               │   ├── Computer.java
│       │               │   ├── Headset.java
│       │               │   ├── IdCard.java
│       │               │   ├── Message.java
│       │               │   ├── Product.java
│       │               │   ├── Student.java
│       │               │   ├── Teacher.java
│       │               │   ├── WeChatMessage.java
│       │               │   └── WeiboMessage.java
│       │               └── test/
│       │                   ├── LitePalTestCase.java
│       │                   ├── MultiDatabaseTest.java
│       │                   ├── annotation/
│       │                   │   └── ColumnTest.java
│       │                   ├── crud/
│       │                   │   ├── delete/
│       │                   │   │   ├── DeleteKotlinTest.kt
│       │                   │   │   └── DeleteTest.java
│       │                   │   ├── query/
│       │                   │   │   ├── QueryBasicKotlinTest.kt
│       │                   │   │   ├── QueryBasicTest.java
│       │                   │   │   ├── QueryBySQLTest.java
│       │                   │   │   ├── QueryClusterKotlinTest.kt
│       │                   │   │   ├── QueryClusterTest.java
│       │                   │   │   ├── QueryDateTest.java
│       │                   │   │   ├── QueryEagerKotlinTest.kt
│       │                   │   │   ├── QueryEagerTest.java
│       │                   │   │   ├── QueryMathKotlinTest.kt
│       │                   │   │   └── QueryMathTest.java
│       │                   │   ├── save/
│       │                   │   │   ├── Many2ManySaveTest.java
│       │                   │   │   ├── Many2OneBiSaveTest.java
│       │                   │   │   ├── Many2OneUniSaveTest.java
│       │                   │   │   ├── One2OneBiSaveTest.java
│       │                   │   │   ├── One2OneUniSaveTest.java
│       │                   │   │   ├── SaveAllKotlinTest.kt
│       │                   │   │   ├── SaveAllTest.java
│       │                   │   │   └── SaveTest.java
│       │                   │   ├── transaction/
│       │                   │   │   ├── TransactionKotlinTest.kt
│       │                   │   │   └── TransactionTest.java
│       │                   │   └── update/
│       │                   │       ├── UpdateUsingSaveMethodTest.java
│       │                   │       ├── UpdateUsingUpdateMethodKotlinTest.kt
│       │                   │       └── UpdateUsingUpdateMethodTest.java
│       │                   └── util/
│       │                       ├── BaseUtilityTest.java
│       │                       └── DBUtilityTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── assets/
│           │   └── litepal.xml
│           ├── java/
│           │   └── org/
│           │       └── litepal/
│           │           └── litepalsample/
│           │               ├── MyApplication.java
│           │               ├── activity/
│           │               │   ├── AggregateActivity.java
│           │               │   ├── AverageSampleActivity.java
│           │               │   ├── CRUDActivity.java
│           │               │   ├── CountSampleActivity.java
│           │               │   ├── DeleteSampleActivity.java
│           │               │   ├── MainActivity.java
│           │               │   ├── ManageTablesActivity.java
│           │               │   ├── MaxSampleActivity.java
│           │               │   ├── MinSampleActivity.java
│           │               │   ├── ModelListActivity.java
│           │               │   ├── ModelStructureActivity.java
│           │               │   ├── QuerySampleActivity.java
│           │               │   ├── SaveSampleActivity.java
│           │               │   ├── SumSampleActivity.java
│           │               │   ├── TableListActivity.java
│           │               │   ├── TableStructureActivity.java
│           │               │   └── UpdateSampleActivity.java
│           │               ├── adapter/
│           │               │   ├── DataArrayAdapter.java
│           │               │   └── StringArrayAdapter.java
│           │               ├── model/
│           │               │   ├── Album.java
│           │               │   ├── Singer.java
│           │               │   └── Song.java
│           │               └── util/
│           │                   └── Utility.java
│           └── res/
│               ├── layout/
│               │   ├── aggregate_layout.xml
│               │   ├── average_sample_layout.xml
│               │   ├── count_sample_layout.xml
│               │   ├── crud_layout.xml
│               │   ├── delete_sample_layout.xml
│               │   ├── main_layout.xml
│               │   ├── manage_tables_layout.xml
│               │   ├── max_sample_layout.xml
│               │   ├── min_sample_layout.xml
│               │   ├── model_list_layout.xml
│               │   ├── model_structure_item.xml
│               │   ├── model_structure_layout.xml
│               │   ├── query_sample_layout.xml
│               │   ├── save_sample_layout.xml
│               │   ├── simple_list_item.xml
│               │   ├── sum_sample_layout.xml
│               │   ├── table_list_layout.xml
│               │   ├── table_structure_item.xml
│               │   ├── table_structure_layout.xml
│               │   └── update_sample_layout.xml
│               └── values/
│                   ├── dimens.xml
│                   ├── strings.xml
│                   └── styles.xml
└── settings.gradle
Download .txt
SYMBOL INDEX (1212 symbols across 127 files)

FILE: core/src/main/java/org/litepal/FluentQuery.java
  class FluentQuery (line 40) | public class FluentQuery {
    method FluentQuery (line 70) | FluentQuery() {
    method select (line 88) | public FluentQuery select(String... columns) {
    method where (line 108) | public FluentQuery where(String... conditions) {
    method order (line 129) | public FluentQuery order(String column) {
    method limit (line 148) | public FluentQuery limit(int value) {
    method offset (line 167) | public FluentQuery offset(int value) {
    method find (line 197) | public <T> List<T> find(Class<T> modelClass) {
    method findAsync (line 205) | @Deprecated
    method find (line 223) | public <T> List<T> find(Class<T> modelClass, boolean isEager) {
    method findAsync (line 243) | @Deprecated
    method findFirst (line 283) | public <T> T findFirst(Class<T> modelClass) {
    method findFirstAsync (line 291) | @Deprecated
    method findFirst (line 309) | public <T> T findFirst(Class<T> modelClass, boolean isEager) {
    method findFirstAsync (line 329) | @Deprecated
    method findLast (line 369) | public <T> T findLast(Class<T> modelClass) {
    method findLastAsync (line 377) | @Deprecated
    method findLast (line 395) | public <T> T findLast(Class<T> modelClass, boolean isEager) {
    method findLastAsync (line 432) | @Deprecated
    method count (line 473) | public int count(Class<?> modelClass) {
    method countAsync (line 481) | @Deprecated
    method count (line 504) | public int count(String tableName) {
    method countAsync (line 515) | @Deprecated
    method average (line 557) | public double average(Class<?> modelClass, String column) {
    method averageAsync (line 565) | @Deprecated
    method average (line 589) | public double average(String tableName, String column) {
    method averageAsync (line 600) | @Deprecated
    method max (line 645) | public <T> T max(Class<?> modelClass, String columnName, Class<T> colu...
    method maxAsync (line 653) | @Deprecated
    method max (line 680) | public <T> T max(String tableName, String columnName, Class<T> columnT...
    method maxAsync (line 691) | @Deprecated
    method min (line 736) | public <T> T min(Class<?> modelClass, String columnName, Class<T> colu...
    method minAsync (line 744) | @Deprecated
    method min (line 771) | public <T> T min(String tableName, String columnName, Class<T> columnT...
    method minAsync (line 782) | @Deprecated
    method sum (line 827) | public <T> T sum(Class<?> modelClass, String columnName, Class<T> colu...
    method sumAsync (line 835) | @Deprecated
    method sum (line 862) | public <T> T sum(String tableName, String columnName, Class<T> columnT...
    method sumAsync (line 873) | @Deprecated

FILE: core/src/main/java/org/litepal/LitePalApplication.java
  class LitePalApplication (line 45) | public class LitePalApplication extends Application {
    method LitePalApplication (line 58) | public LitePalApplication() {
    method getContext (line 68) | public static Context getContext() {

FILE: core/src/main/java/org/litepal/LitePalBase.java
  class LitePalBase (line 59) | public abstract class LitePalBase {
    method getTableModel (line 118) | protected TableModel getTableModel(String className) {
    method getAssociations (line 139) | protected Collection<AssociationsModel> getAssociations(List<String> c...
    method getGenericModels (line 158) | protected Collection<GenericModel> getGenericModels() {
    method getAssociationInfo (line 169) | protected Collection<AssociationsInfo> getAssociationInfo(String class...
    method getSupportedFields (line 188) | protected List<Field> getSupportedFields(String className) {
    method getSupportedGenericFields (line 211) | protected List<Field> getSupportedGenericFields(String className) {
    method isCollection (line 235) | protected boolean isCollection(Class<?> fieldType) {
    method isList (line 246) | protected boolean isList(Class<?> fieldType) {
    method isSet (line 257) | protected boolean isSet(Class<?> fieldType) {
    method isIdColumn (line 269) | protected boolean isIdColumn(String columnName) {
    method getForeignKeyColumnName (line 282) | protected String getForeignKeyColumnName(String associatedTableName) {
    method getColumnType (line 292) | protected String getColumnType(String fieldType) {
    method getGenericTypeClass (line 311) | protected Class<?> getGenericTypeClass(Field field) {
    method recursiveSupportedFields (line 322) | private void recursiveSupportedFields(Class<?> clazz, List<Field> supp...
    method recursiveSupportedGenericFields (line 346) | private void recursiveSupportedGenericFields(Class<?> clazz, List<Fiel...
    method analyzeClassFields (line 379) | private void analyzeClassFields(String className, int action) {
    method isNonPrimitive (line 406) | private boolean isNonPrimitive(Field field) {
    method isPrivate (line 417) | protected boolean isPrivate(Field field) {
    method oneToAnyConditions (line 445) | private void oneToAnyConditions(String className, Field field, int act...
    method manyToAnyConditions (line 529) | private void manyToAnyConditions(String className, Field field, int ac...
    method addIntoAssociationModelCollection (line 622) | private void addIntoAssociationModelCollection(String className, Strin...
    method addIntoAssociationInfoCollection (line 651) | private void addIntoAssociationInfoCollection(String selfClassName, St...
    method getGenericTypeName (line 672) | protected String getGenericTypeName(Field field) {
    method convertFieldToColumnModel (line 687) | private ColumnModel convertFieldToColumnModel(Field field) {

FILE: core/src/main/java/org/litepal/LitePalDB.java
  class LitePalDB (line 34) | public class LitePalDB {
    method fromDefault (line 69) | public static LitePalDB fromDefault(String dbName) {
    method LitePalDB (line 84) | public LitePalDB(String dbName, int version) {
    method getVersion (line 89) | public int getVersion() {
    method getDbName (line 93) | public String getDbName() {
    method getStorage (line 97) | public String getStorage() {
    method setStorage (line 101) | public void setStorage(String storage) {
    method isExternalStorage (line 105) | public boolean isExternalStorage() {
    method setExternalStorage (line 109) | public void setExternalStorage(boolean isExternalStorage) {
    method getClassNames (line 118) | public List<String> getClassNames() {
    method addClassName (line 134) | public void addClassName(String className) {
    method setClassNames (line 138) | void setClassNames(List<String> className) {

FILE: core/src/main/java/org/litepal/Operator.java
  class Operator (line 63) | public class Operator {
    method getHandler (line 73) | public static Handler getHandler() {
    method initialize (line 85) | public static void initialize(Context context) {
    method getDatabase (line 94) | public static SQLiteDatabase getDatabase() {
    method beginTransaction (line 101) | public static void beginTransaction() {
    method endTransaction (line 108) | public static void endTransaction() {
    method setTransactionSuccessful (line 117) | public static void setTransactionSuccessful() {
    method use (line 126) | public static void use(LitePalDB litePalDB) {
    method useDefault (line 145) | public static void useDefault() {
    method deleteDatabase (line 158) | public static boolean deleteDatabase(String dbName) {
    method aesKey (line 186) | public static void aesKey(String key) {
    method removeVersionInSharedPreferences (line 195) | private static void removeVersionInSharedPreferences(String dbName) {
    method isDefaultDatabase (line 210) | private static boolean isDefaultDatabase(String dbName) {
    method select (line 240) | public static FluentQuery select(String... columns) {
    method where (line 261) | public static FluentQuery where(String... conditions) {
    method order (line 283) | public static FluentQuery order(String column) {
    method limit (line 303) | public static FluentQuery limit(int value) {
    method offset (line 323) | public static FluentQuery offset(int value) {
    method count (line 347) | public static int count(Class<?> modelClass) {
    method countAsync (line 355) | @Deprecated
    method count (line 378) | public static int count(String tableName) {
    method countAsync (line 389) | @Deprecated
    method average (line 431) | public static double average(Class<?> modelClass, String column) {
    method averageAsync (line 439) | @Deprecated
    method average (line 463) | public static double average(String tableName, String column) {
    method averageAsync (line 474) | @Deprecated
    method max (line 519) | public static <T> T max(Class<?> modelClass, String columnName, Class<...
    method maxAsync (line 527) | @Deprecated
    method max (line 554) | public static <T> T max(String tableName, String columnName, Class<T> ...
    method maxAsync (line 565) | @Deprecated
    method min (line 610) | public static <T> T min(Class<?> modelClass, String columnName, Class<...
    method minAsync (line 618) | @Deprecated
    method min (line 645) | public static <T> T min(String tableName, String columnName, Class<T> ...
    method minAsync (line 656) | @Deprecated
    method sum (line 701) | public static <T> T sum(Class<?> modelClass, String columnName, Class<...
    method sumAsync (line 709) | @Deprecated
    method sum (line 736) | public static <T> T sum(String tableName, String columnName, Class<T> ...
    method sumAsync (line 747) | @Deprecated
    method find (line 790) | public static <T> T find(Class<T> modelClass, long id) {
    method findAsync (line 798) | @Deprecated
    method find (line 818) | public static <T> T find(Class<T> modelClass, long id, boolean isEager) {
    method findAsync (line 829) | @Deprecated
    method findFirst (line 867) | public static <T> T findFirst(Class<T> modelClass) {
    method findFirstAsync (line 875) | @Deprecated
    method findFirst (line 893) | public static <T> T findFirst(Class<T> modelClass, boolean isEager) {
    method findFirstAsync (line 904) | @Deprecated
    method findLast (line 942) | public static <T> T findLast(Class<T> modelClass) {
    method findLastAsync (line 950) | @Deprecated
    method findLast (line 968) | public static <T> T findLast(Class<T> modelClass, boolean isEager) {
    method findLastAsync (line 979) | @Deprecated
    method findAll (line 1032) | public static <T> List<T> findAll(Class<T> modelClass, long... ids) {
    method findAllAsync (line 1040) | @Deprecated
    method findAll (line 1060) | public static <T> List<T> findAll(Class<T> modelClass, boolean isEager,
    method findAllAsync (line 1072) | @Deprecated
    method findBySQL (line 1111) | public static Cursor findBySQL(String... sql) {
    method delete (line 1148) | public static int delete(Class<?> modelClass, long id) {
    method deleteAsync (line 1168) | @Deprecated
    method deleteAll (line 1215) | public static int deleteAll(Class<?> modelClass, String... conditions) {
    method deleteAllAsync (line 1235) | @Deprecated
    method deleteAll (line 1285) | public static int deleteAll(String tableName, String... conditions) {
    method deleteAllAsync (line 1296) | @Deprecated
    method update (line 1340) | public static int update(Class<?> modelClass, ContentValues values, lo...
    method updateAsync (line 1351) | @Deprecated
    method updateAll (line 1403) | public static int updateAll(Class<?> modelClass, ContentValues values,
    method updateAllAsync (line 1413) | @Deprecated
    method updateAll (line 1448) | public static int updateAll(String tableName, ContentValues values,
    method updateAllAsync (line 1460) | @Deprecated
    method saveAll (line 1509) | public static <T extends LitePalSupport> boolean saveAll(Collection<T>...
    method saveAllAsync (line 1531) | @Deprecated
    method markAsDeleted (line 1568) | public static <T extends LitePalSupport> void markAsDeleted(Collection...
    method isExist (line 1584) | public static <T> boolean isExist(Class<T> modelClass, String... condi...
    method registerDatabaseListener (line 1591) | public static void registerDatabaseListener(DatabaseListener listener) {
    method getDBListener (line 1595) | public static DatabaseListener getDBListener() {

FILE: core/src/main/java/org/litepal/crud/AssociationsAnalyzer.java
  class AssociationsAnalyzer (line 36) | abstract class AssociationsAnalyzer extends DataHandler {
    method getReverseAssociatedModels (line 54) | @SuppressWarnings("unchecked")
    method setReverseAssociatedModels (line 79) | protected void setReverseAssociatedModels(LitePalSupport associatedModel,
    method checkAssociatedModelCollection (line 103) | protected Collection<LitePalSupport> checkAssociatedModelCollection(
    method buildBidirectionalAssociations (line 135) | protected void buildBidirectionalAssociations(LitePalSupport baseObj, ...
    method dealsAssociationsOnTheSideWithoutFK (line 153) | protected void dealsAssociationsOnTheSideWithoutFK(LitePalSupport base...
    method mightClearFKValue (line 178) | protected void mightClearFKValue(LitePalSupport baseObj, AssociationsI...
    method getForeignKeyName (line 189) | private String getForeignKeyName(AssociationsInfo associationInfo) {

FILE: core/src/main/java/org/litepal/crud/DataHandler.java
  class DataHandler (line 60) | abstract class DataHandler extends LitePalBase {
    method query (line 124) | @SuppressWarnings("unchecked")
    method mathQuery (line 180) | @SuppressWarnings("unchecked")
    method giveBaseObjIdValue (line 212) | protected void giveBaseObjIdValue(LitePalSupport baseObj, long id) thr...
    method putFieldsValue (line 231) | protected void putFieldsValue(LitePalSupport baseObj, List<Field> supp...
    method putContentValuesForSave (line 254) | protected void putContentValuesForSave(LitePalSupport baseObj, Field f...
    method putContentValuesForUpdate (line 305) | protected void putContentValuesForUpdate(LitePalSupport baseObj, Field...
    method encryptValue (line 334) | protected Object encryptValue(String algorithm, Object fieldValue) {
    method getFieldValue (line 354) | protected Object getFieldValue(LitePalSupport dataSupport, Field field)
    method setFieldValue (line 373) | protected void setFieldValue(LitePalSupport dataSupport, Field field, ...
    method analyzeAssociatedModels (line 387) | protected void analyzeAssociatedModels(LitePalSupport baseObj, Collect...
    method getAssociatedModel (line 412) | protected LitePalSupport getAssociatedModel(LitePalSupport baseObj, As...
    method getAssociatedModels (line 429) | @SuppressWarnings("unchecked")
    method getEmptyModel (line 444) | protected LitePalSupport getEmptyModel(LitePalSupport baseObj) {
    method getWhereClause (line 473) | protected String getWhereClause(String... conditions) {
    method getWhereArgs (line 493) | protected String[] getWhereArgs(String... conditions) {
    method isAffectAllLines (line 513) | protected boolean isAffectAllLines(Object... conditions) {
    method getWhereOfIdsWithOr (line 525) | protected String getWhereOfIdsWithOr(Collection<Long> ids) {
    method getWhereOfIdsWithOr (line 546) | protected String getWhereOfIdsWithOr(long... ids) {
    method shouldGetOrSet (line 571) | protected boolean shouldGetOrSet(LitePalSupport dataSupport, Field fie...
    method getIntermediateTableName (line 584) | protected String getIntermediateTableName(LitePalSupport baseObj, Stri...
    method getTableName (line 597) | protected String getTableName(Class<?> modelClass) {
    method createInstanceFromClass (line 611) | protected Object createInstanceFromClass(Class<?> modelClass) {
    method findBestSuitConstructor (line 629) | protected Constructor<?> findBestSuitConstructor(Class<?> modelClass) {
    method getConstructorParams (line 675) | protected Object[] getConstructorParams(Class<?> modelClass, Construct...
    method setValueToModel (line 700) | protected void setValueToModel(Object modelInstance, List<Field> suppo...
    method setGenericValueToModel (line 759) | protected void setGenericValueToModel(LitePalSupport baseObj, List<Fie...
    method getForeignKeyAssociations (line 816) | protected List<AssociationsInfo> getForeignKeyAssociations(String clas...
    method getParameterTypes (line 838) | protected Class<?>[] getParameterTypes(Field field, Object fieldValue,...
    method getObjectType (line 865) | private Class<?> getObjectType(Class<?> primitiveType) {
    method getInitParamValue (line 901) | private Object getInitParamValue(Class<?> modelClass, Class<?> paramTy...
    method isCharType (line 943) | private boolean isCharType(Field field) {
    method isPrimitiveBooleanType (line 958) | private boolean isPrimitiveBooleanType(Field field) {
    method putFieldsValueDependsOnSaveOrUpdate (line 976) | private void putFieldsValueDependsOnSaveOrUpdate(LitePalSupport baseOb...
    method isUpdating (line 994) | private boolean isUpdating() {
    method isSaving (line 1004) | private boolean isSaving() {
    method isFieldWithDefaultValue (line 1020) | private boolean isFieldWithDefaultValue(LitePalSupport baseObj, Field ...
    method makeGetterMethodName (line 1040) | protected String makeGetterMethodName(Field field) {
    method makeSetterMethodName (line 1065) | protected String makeSetterMethodName(Field field) {
    method genGetColumnMethod (line 1089) | private String genGetColumnMethod(Field field) {
    method genGetColumnMethod (line 1110) | private String genGetColumnMethod(Class<?> fieldType) {
    method getCustomizedColumns (line 1147) | private String[] getCustomizedColumns(String[] columns, List<Field> su...
    method analyzeAssociations (line 1213) | private void analyzeAssociations(String className) {
    method setAssociatedModel (line 1245) | @SuppressWarnings({ "rawtypes", "unchecked" })
    method setToModelByReflection (line 1319) | @SuppressWarnings("unchecked")
    method decryptValue (line 1382) | protected Object decryptValue(String algorithm, Object fieldValue) {
    class QueryInfoCache (line 1396) | static class QueryInfoCache {

FILE: core/src/main/java/org/litepal/crud/DeleteHandler.java
  class DeleteHandler (line 46) | public class DeleteHandler extends DataHandler {
    method DeleteHandler (line 61) | public DeleteHandler(SQLiteDatabase db) {
    method onDelete (line 77) | int onDelete(LitePalSupport baseObj) {
    method onDelete (line 104) | public int onDelete(Class<?> modelClass, long id) {
    method onDeleteAll (line 127) | public int onDeleteAll(String tableName, String... conditions) {
    method onDeleteAll (line 136) | @SuppressWarnings("unchecked")
    method analyzeAssociations (line 170) | private void analyzeAssociations(Class<?> modelClass) {
    method deleteCascade (line 207) | private int deleteCascade(Class<?> modelClass, long id) {
    method deleteAllCascade (line 217) | private int deleteAllCascade(Class<?> modelClass, String... conditions) {
    method buildConditionString (line 235) | private String buildConditionString(String... conditions) {
    method analyzeAssociations (line 251) | private Collection<AssociationsInfo> analyzeAssociations(LitePalSuppor...
    method clearAssociatedModelSaveState (line 272) | private void clearAssociatedModelSaveState(LitePalSupport baseObj,
    method deleteCascade (line 313) | private int deleteCascade(LitePalSupport baseObj) {
    method deleteAssociatedForeignKeyRows (line 328) | private int deleteAssociatedForeignKeyRows(LitePalSupport baseObj) {
    method deleteAssociatedJoinTableRows (line 348) | private int deleteAssociatedJoinTableRows(LitePalSupport baseObj) {
    method getForeignKeyTableToDelete (line 368) | private List<String> getForeignKeyTableToDelete() {
    method deleteGenericData (line 384) | private void deleteGenericData(Class<?> modelClass, List<Field> suppor...

FILE: core/src/main/java/org/litepal/crud/DynamicExecutor.java
  class DynamicExecutor (line 32) | class DynamicExecutor {
    method DynamicExecutor (line 37) | private DynamicExecutor() {
    method send (line 61) | static Object send(Object object, String methodName, Object[] paramete...
    method set (line 80) | static void set(Object object, String fieldName, Object value, Class<?...
    method setField (line 104) | static void setField(Object object, String fieldName, Object value, Cl...
    method getField (line 132) | static Object getField(Object object, String fieldName, Class<?> objec...

FILE: core/src/main/java/org/litepal/crud/LitePalSupport.java
  class LitePalSupport (line 66) | public class LitePalSupport {
    method delete (line 140) | public int delete() {
    method deleteAsync (line 160) | @Deprecated
    method update (line 204) | public int update(long id) {
    method updateAsync (line 226) | @Deprecated
    method updateAll (line 278) | public int updateAll(String... conditions) {
    method updateAllAsync (line 300) | @Deprecated
    method save (line 347) | public boolean save() {
    method saveAsync (line 361) | @Deprecated
    method saveThrows (line 408) | public void saveThrows() {
    method saveOrUpdate (line 456) | @SuppressWarnings("unchecked")
    method saveOrUpdateAsync (line 491) | @Deprecated
    method isSaved (line 519) | public boolean isSaved() {
    method clearSavedState (line 526) | public void clearSavedState() {
    method setToDefault (line 538) | public void setToDefault(String fieldName) {
    method assignBaseObjId (line 548) | public void assignBaseObjId(long baseObjId) {
    method LitePalSupport (line 556) | protected LitePalSupport() {
    method getBaseObjId (line 565) | protected long getBaseObjId() {
    method getClassName (line 574) | protected String getClassName() {
    method getTableName (line 583) | protected String getTableName() {
    method getFieldsToSetToDefault (line 594) | List<String> getFieldsToSetToDefault() {
    method addAssociatedModelWithFK (line 611) | void addAssociatedModelWithFK(String associatedTableName, long associa...
    method getAssociatedModelsMapWithFK (line 630) | Map<String, Set<Long>> getAssociatedModelsMapWithFK() {
    method addAssociatedModelForJoinTable (line 645) | void addAssociatedModelForJoinTable(String associatedModelName, long a...
    method addEmptyModelForJoinTable (line 665) | void addEmptyModelForJoinTable(String associatedModelName) {
    method getAssociatedModelsMapForJoinTable (line 682) | Map<String, List<Long>> getAssociatedModelsMapForJoinTable() {
    method addAssociatedModelWithoutFK (line 700) | void addAssociatedModelWithoutFK(String associatedTableName, long asso...
    method getAssociatedModelsMapWithoutFK (line 711) | Map<String, Long> getAssociatedModelsMapWithoutFK() {
    method addFKNameToClearSelf (line 724) | void addFKNameToClearSelf(String foreignKeyName) {
    method getListToClearSelfFK (line 737) | List<String> getListToClearSelfFK() {
    method addAssociatedTableNameToClearFK (line 750) | void addAssociatedTableNameToClearFK(String associatedTableName) {
    method getListToClearAssociatedFK (line 763) | List<String> getListToClearAssociatedFK() {
    method clearAssociatedData (line 773) | void clearAssociatedData() {
    method clearIdOfModelWithFK (line 783) | private void clearIdOfModelWithFK() {
    method clearIdOfModelWithoutFK (line 793) | private void clearIdOfModelWithoutFK() {
    method clearIdOfModelForJoinTable (line 800) | private void clearIdOfModelForJoinTable() {
    method clearFKNameList (line 810) | private void clearFKNameList() {

FILE: core/src/main/java/org/litepal/crud/Many2ManyAnalyzer.java
  class Many2ManyAnalyzer (line 38) | public class Many2ManyAnalyzer extends AssociationsAnalyzer {
    method analyze (line 60) | void analyze(LitePalSupport baseObj, AssociationsInfo associationInfo)...
    method declareAssociations (line 88) | private void declareAssociations(LitePalSupport baseObj, AssociationsI...
    method addNewModelForAssociatedModel (line 102) | private void addNewModelForAssociatedModel(Collection<LitePalSupport> ...
    method dealAssociatedModel (line 120) | private void dealAssociatedModel(LitePalSupport baseObj, LitePalSuppor...
    method getAssociatedTableName (line 135) | private String getAssociatedTableName(AssociationsInfo associationInfo) {
    method isDataExists (line 153) | @SuppressWarnings("unused")
    method getSelection (line 183) | private String getSelection(LitePalSupport baseObj, LitePalSupport ass...
    method getSelectionArgs (line 202) | private String[] getSelectionArgs(LitePalSupport baseObj, LitePalSuppo...
    method getJoinTableName (line 216) | private String getJoinTableName(LitePalSupport baseObj, LitePalSupport...

FILE: core/src/main/java/org/litepal/crud/Many2OneAnalyzer.java
  class Many2OneAnalyzer (line 33) | class Many2OneAnalyzer extends AssociationsAnalyzer {
    method analyze (line 56) | void analyze(LitePalSupport baseObj, AssociationsInfo associationInfo)...
    method analyzeManySide (line 86) | private void analyzeManySide(LitePalSupport baseObj, AssociationsInfo ...
    method analyzeOneSide (line 122) | private void analyzeOneSide(LitePalSupport baseObj, AssociationsInfo a...
    method dealAssociatedModelOnManySide (line 152) | private void dealAssociatedModelOnManySide(Collection<LitePalSupport> ...
    method dealAssociatedModelOnOneSide (line 172) | private void dealAssociatedModelOnOneSide(LitePalSupport baseObj, Lite...

FILE: core/src/main/java/org/litepal/crud/One2OneAnalyzer.java
  class One2OneAnalyzer (line 32) | public class One2OneAnalyzer extends AssociationsAnalyzer {
    method analyze (line 55) | void analyze(LitePalSupport baseObj, AssociationsInfo associationInfo)...
    method dealAssociatedModel (line 83) | private void dealAssociatedModel(LitePalSupport baseObj, LitePalSuppor...
    method bidirectionalCondition (line 104) | private void bidirectionalCondition(LitePalSupport baseObj, LitePalSup...
    method unidirectionalCondition (line 123) | private void unidirectionalCondition(LitePalSupport baseObj, LitePalSu...

FILE: core/src/main/java/org/litepal/crud/QueryHandler.java
  class QueryHandler (line 33) | public class QueryHandler extends DataHandler {
    method QueryHandler (line 42) | public QueryHandler(SQLiteDatabase db) {
    method onFind (line 58) | public <T> T onFind(Class<T> modelClass, long id, boolean isEager) {
    method onFindFirst (line 77) | public <T> T onFindFirst(Class<T> modelClass, boolean isEager) {
    method onFindLast (line 96) | public <T> T onFindLast(Class<T> modelClass, boolean isEager) {
    method onFindAll (line 117) | public <T> List<T> onFindAll(Class<T> modelClass, boolean isEager, lon...
    method onFind (line 152) | public <T> List<T> onFind(Class<T> modelClass, String[] columns, Strin...
    method onCount (line 175) | public int onCount(String tableName, String[] conditions) {
    method onAverage (line 196) | public double onAverage(String tableName, String column, String[] cond...
    method onMax (line 220) | public <T> T onMax(String tableName, String column, String[] condition...
    method onMin (line 243) | public <T> T onMin(String tableName, String column, String[] condition...
    method onSum (line 266) | public <T> T onSum(String tableName, String column, String[] condition...

FILE: core/src/main/java/org/litepal/crud/SaveHandler.java
  class SaveHandler (line 48) | public class SaveHandler extends DataHandler {
    method SaveHandler (line 59) | public SaveHandler(SQLiteDatabase db) {
    method onSave (line 75) | void onSave(LitePalSupport baseObj) throws SecurityException, IllegalA...
    method onSaveAll (line 102) | public <T extends LitePalSupport> void onSaveAll(Collection<T> collect...
    method doSaveAction (line 142) | private void doSaveAction(LitePalSupport baseObj, List<Field> supporte...
    method beforeSave (line 163) | private void beforeSave(LitePalSupport baseObj, List<Field> supportedF...
    method saving (line 180) | private long saving(LitePalSupport baseObj, ContentValues values) {
    method afterSave (line 199) | private void afterSave(LitePalSupport baseObj, List<Field> supportedFi...
    method doUpdateAction (line 218) | private void doUpdateAction(LitePalSupport baseObj, List<Field> suppor...
    method beforeUpdate (line 240) | private void beforeUpdate(LitePalSupport baseObj, List<Field> supporte...
    method updating (line 260) | private void updating(LitePalSupport baseObj, ContentValues values) {
    method afterUpdate (line 275) | private void afterUpdate(LitePalSupport baseObj, List<Field> supported...
    method getIdField (line 290) | private Field getIdField(List<Field> supportedFields) {
    method throwIfSaveFailed (line 305) | private void throwIfSaveFailed(long id) {
    method assignIdValue (line 326) | private void assignIdValue(LitePalSupport baseObj, Field idField, long...
    method giveModelIdValue (line 350) | private void giveModelIdValue(LitePalSupport baseObj, String idName, C...
    method putForeignKeyValue (line 373) | private void putForeignKeyValue(ContentValues values, LitePalSupport b...
    method updateAssociatedTableWithFK (line 387) | private void updateAssociatedTableWithFK(LitePalSupport baseObj) {
    method clearFKValueInAssociatedTable (line 408) | private void clearFKValueInAssociatedTable(LitePalSupport baseObj) {
    method insertIntermediateJoinTableValue (line 428) | private void insertIntermediateJoinTableValue(LitePalSupport baseObj, ...
    method getWhereForJoinTableToDelete (line 457) | private String getWhereForJoinTableToDelete(LitePalSupport baseObj) {
    method shouldGiveModelIdValue (line 478) | private boolean shouldGiveModelIdValue(String idName, Class<?> idType,...
    method updateGenericTables (line 492) | private void updateGenericTables(LitePalSupport baseObj, List<Field> s...

FILE: core/src/main/java/org/litepal/crud/UpdateHandler.java
  class UpdateHandler (line 48) | public class UpdateHandler extends DataHandler {
    method UpdateHandler (line 57) | public UpdateHandler(SQLiteDatabase db) {
    method onUpdate (line 77) | int onUpdate(LitePalSupport baseObj, long id) throws SecurityException...
    method onUpdate (line 105) | public int onUpdate(Class<?> modelClass, long id, ContentValues values) {
    method onUpdateAll (line 131) | @SuppressWarnings("unchecked")
    method onUpdateAll (line 175) | public int onUpdateAll(String tableName, ContentValues values, String....
    method doUpdateAllAction (line 199) | private int doUpdateAllAction(String tableName, ContentValues values, ...
    method putFieldsToDefaultValue (line 219) | private void putFieldsToDefaultValue(LitePalSupport baseObj, ContentVa...
    method doUpdateAssociations (line 262) | @SuppressWarnings("unused")
    method analyzeAssociations (line 279) | private void analyzeAssociations(LitePalSupport baseObj) {
    method updateSelfTableForeignKey (line 292) | private void updateSelfTableForeignKey(LitePalSupport baseObj, Content...
    method updateAssociatedTableForeignKey (line 303) | private int updateAssociatedTableForeignKey(LitePalSupport baseObj, lo...
    method updateGenericTables (line 332) | private void updateGenericTables(LitePalSupport baseObj, List<Field> s...
    method convertContentValues (line 383) | private void convertContentValues(ContentValues values) {

FILE: core/src/main/java/org/litepal/crud/async/AsyncExecutor.java
  class AsyncExecutor (line 24) | public abstract class AsyncExecutor {
    method submit (line 36) | public void submit(Runnable task) {
    method execute (line 43) | void execute() {

FILE: core/src/main/java/org/litepal/crud/async/AverageExecutor.java
  class AverageExecutor (line 26) | public class AverageExecutor extends AsyncExecutor {
    method listen (line 35) | public void listen(AverageCallback callback) {
    method getListener (line 40) | public AverageCallback getListener() {

FILE: core/src/main/java/org/litepal/crud/async/CountExecutor.java
  class CountExecutor (line 26) | public class CountExecutor extends AsyncExecutor {
    method listen (line 35) | public void listen(CountCallback callback) {
    method getListener (line 40) | public CountCallback getListener() {

FILE: core/src/main/java/org/litepal/crud/async/FindExecutor.java
  class FindExecutor (line 26) | public class FindExecutor<T> extends AsyncExecutor {
    method listen (line 35) | public void listen(FindCallback<T> callback) {
    method getListener (line 40) | public FindCallback<T> getListener() {

FILE: core/src/main/java/org/litepal/crud/async/FindMultiExecutor.java
  class FindMultiExecutor (line 26) | public class FindMultiExecutor<T> extends AsyncExecutor {
    method listen (line 35) | public void listen(FindMultiCallback<T> callback) {
    method getListener (line 40) | public FindMultiCallback<T> getListener() {

FILE: core/src/main/java/org/litepal/crud/async/SaveExecutor.java
  class SaveExecutor (line 26) | public class SaveExecutor extends AsyncExecutor {
    method listen (line 35) | public void listen(SaveCallback callback) {
    method getListener (line 40) | public SaveCallback getListener() {

FILE: core/src/main/java/org/litepal/crud/async/UpdateOrDeleteExecutor.java
  class UpdateOrDeleteExecutor (line 26) | public class UpdateOrDeleteExecutor extends AsyncExecutor {
    method listen (line 35) | public void listen(UpdateOrDeleteCallback callback) {
    method getListener (line 40) | public UpdateOrDeleteCallback getListener() {

FILE: core/src/main/java/org/litepal/crud/callback/AverageCallback.java
  type AverageCallback (line 24) | public interface AverageCallback {
    method onFinish (line 26) | void onFinish(double average);

FILE: core/src/main/java/org/litepal/crud/callback/CountCallback.java
  type CountCallback (line 24) | public interface CountCallback {
    method onFinish (line 26) | void onFinish(int count);

FILE: core/src/main/java/org/litepal/crud/callback/FindCallback.java
  type FindCallback (line 24) | public interface FindCallback<T> {
    method onFinish (line 26) | void onFinish(T t);

FILE: core/src/main/java/org/litepal/crud/callback/FindMultiCallback.java
  type FindMultiCallback (line 26) | public interface FindMultiCallback<T> {
    method onFinish (line 28) | void onFinish(List<T> list);

FILE: core/src/main/java/org/litepal/crud/callback/SaveCallback.java
  type SaveCallback (line 24) | public interface SaveCallback {
    method onFinish (line 26) | void onFinish(boolean success);

FILE: core/src/main/java/org/litepal/crud/callback/UpdateOrDeleteCallback.java
  type UpdateOrDeleteCallback (line 24) | public interface UpdateOrDeleteCallback {
    method onFinish (line 26) | void onFinish(int rowsAffected);

FILE: core/src/main/java/org/litepal/crud/model/AssociationsInfo.java
  class AssociationsInfo (line 28) | public class AssociationsInfo {
    method getSelfClassName (line 66) | public String getSelfClassName() {
    method setSelfClassName (line 76) | public void setSelfClassName(String selfClassName) {
    method getAssociatedClassName (line 85) | public String getAssociatedClassName() {
    method setAssociatedClassName (line 95) | public void setAssociatedClassName(String associatedClassName) {
    method getClassHoldsForeignKey (line 104) | public String getClassHoldsForeignKey() {
    method setClassHoldsForeignKey (line 114) | public void setClassHoldsForeignKey(String classHoldsForeignKey) {
    method getAssociateOtherModelFromSelf (line 124) | public Field getAssociateOtherModelFromSelf() {
    method setAssociateOtherModelFromSelf (line 136) | public void setAssociateOtherModelFromSelf(Field associateOtherModelFr...
    method getAssociateSelfFromOtherModel (line 147) | public Field getAssociateSelfFromOtherModel() {
    method setAssociateSelfFromOtherModel (line 159) | public void setAssociateSelfFromOtherModel(Field associateSelfFromOthe...
    method getAssociationType (line 168) | public int getAssociationType() {
    method setAssociationType (line 178) | public void setAssociationType(int associationType) {
    method equals (line 187) | @Override

FILE: core/src/main/java/org/litepal/exceptions/DataSupportException.java
  class DataSupportException (line 27) | public class DataSupportException extends RuntimeException {
    method DataSupportException (line 36) | public DataSupportException(String errorMessage) {
    method DataSupportException (line 48) | public DataSupportException(String errorMessage, Throwable throwable) {

FILE: core/src/main/java/org/litepal/exceptions/DatabaseGenerateException.java
  class DatabaseGenerateException (line 25) | public class DatabaseGenerateException extends RuntimeException {
    method DatabaseGenerateException (line 65) | public DatabaseGenerateException(String errorMessage) {

FILE: core/src/main/java/org/litepal/exceptions/GlobalException.java
  class GlobalException (line 25) | public class GlobalException extends RuntimeException {
    method GlobalException (line 39) | public GlobalException(String errorMessage) {

FILE: core/src/main/java/org/litepal/exceptions/InvalidAttributesException.java
  class InvalidAttributesException (line 27) | public class InvalidAttributesException extends RuntimeException {
    method InvalidAttributesException (line 56) | public InvalidAttributesException(String errorMessage) {

FILE: core/src/main/java/org/litepal/exceptions/LitePalSupportException.java
  class LitePalSupportException (line 26) | public class LitePalSupportException extends DataSupportException {
    method LitePalSupportException (line 67) | public LitePalSupportException(String errorMessage) {
    method LitePalSupportException (line 79) | public LitePalSupportException(String errorMessage, Throwable throwabl...
    method noSuchMethodException (line 93) | public static String noSuchMethodException(String className, String me...
    method noSuchFieldExceptioin (line 108) | public static String noSuchFieldExceptioin(String className, String fi...

FILE: core/src/main/java/org/litepal/exceptions/ParseConfigurationFileException.java
  class ParseConfigurationFileException (line 26) | public class ParseConfigurationFileException extends RuntimeException {
    method ParseConfigurationFileException (line 55) | public ParseConfigurationFileException(String errorMessage) {

FILE: core/src/main/java/org/litepal/model/Table_Schema.java
  class Table_Schema (line 30) | public class Table_Schema {
    method getName (line 47) | public String getName() {
    method setName (line 57) | public void setName(String name) {
    method getType (line 66) | public int getType() {
    method setType (line 76) | public void setType(int type) {

FILE: core/src/main/java/org/litepal/parser/LitePalAttr.java
  class LitePalAttr (line 37) | public final class LitePalAttr {
    method LitePalAttr (line 78) | private LitePalAttr() {
    method getInstance (line 85) | public static LitePalAttr getInstance() {
    method loadLitePalXMLConfiguration (line 97) | private static void loadLitePalXMLConfiguration() {
    method clearInstance (line 111) | public static void clearInstance() {
    method getVersion (line 115) | public int getVersion() {
    method setVersion (line 119) | public void setVersion(int version) {
    method getDbName (line 123) | public String getDbName() {
    method setDbName (line 127) | public void setDbName(String dbName) {
    method getStorage (line 131) | public String getStorage() {
    method setStorage (line 135) | public void setStorage(String storage) {
    method getExtraKeyName (line 139) | public String getExtraKeyName() {
    method setExtraKeyName (line 143) | public void setExtraKeyName(String extraKeyName) {
    method getClassNames (line 152) | public List<String> getClassNames() {
    method addClassName (line 168) | public void addClassName(String className) {
    method setClassNames (line 172) | public void setClassNames(List<String> classNames) {
    method getCases (line 176) | public String getCases() {
    method setCases (line 180) | public void setCases(String cases) {
    method checkSelfValid (line 193) | public void checkSelfValid() {

FILE: core/src/main/java/org/litepal/parser/LitePalConfig.java
  class LitePalConfig (line 27) | public class LitePalConfig {
    method getVersion (line 55) | public int getVersion() {
    method setVersion (line 59) | public void setVersion(int version) {
    method getDbName (line 63) | public String getDbName() {
    method setDbName (line 67) | public void setDbName(String dbName) {
    method getStorage (line 71) | public String getStorage() {
    method setStorage (line 75) | public void setStorage(String storage) {
    method getClassNames (line 84) | public List<String> getClassNames() {
    method addClassName (line 100) | public void addClassName(String className) {
    method setClassNames (line 104) | public void setClassNames(List<String> classNames) {
    method getCases (line 108) | public String getCases() {
    method setCases (line 112) | public void setCases(String cases) {

FILE: core/src/main/java/org/litepal/parser/LitePalContentHandler.java
  class LitePalContentHandler (line 31) | public class LitePalContentHandler extends DefaultHandler {
    method characters (line 42) | @Override
    method endDocument (line 49) | @Override
    method endElement (line 56) | @Override
    method startDocument (line 63) | @Override
    method startElement (line 73) | @Override

FILE: core/src/main/java/org/litepal/parser/LitePalParser.java
  class LitePalParser (line 46) | public class LitePalParser {
    method parseLitePalConfiguration (line 98) | public static LitePalConfig parseLitePalConfiguration() {
    method useSAXParser (line 114) | private void useSAXParser() {
    method usePullParse (line 144) | private LitePalConfig usePullParse() {
    method getConfigInputStream (line 195) | private InputStream getConfigInputStream() throws IOException {

FILE: core/src/main/java/org/litepal/tablemanager/AssociationCreator.java
  class AssociationCreator (line 49) | public abstract class AssociationCreator extends Generator {
    method createOrUpgradeTable (line 51) | protected abstract void createOrUpgradeTable(SQLiteDatabase db, boolea...
    method addOrUpdateAssociation (line 58) | @Override
    method generateCreateTableSQL (line 78) | protected String generateCreateTableSQL(String tableName, Collection<C...
    method generateCreateIndexSQLs (line 124) | protected List<String> generateCreateIndexSQLs(String tableName, Colle...
    method generateDropTableSQL (line 141) | protected String generateDropTableSQL(String tableName) {
    method generateAddColumnSQL (line 153) | protected String generateAddColumnSQL(String tableName, ColumnModel co...
    method generateCreateIndexSQL (line 192) | protected String generateCreateIndexSQL(String tableName, ColumnModel ...
    method isForeignKeyColumnFormat (line 217) | protected boolean isForeignKeyColumnFormat(String columnName) {
    method giveTableSchemaACopy (line 235) | protected void giveTableSchemaACopy(String tableName, int tableType, S...
    method isNeedtoGiveACopy (line 269) | private boolean isNeedtoGiveACopy(Cursor cursor, String tableName) {
    method isValueExists (line 282) | private boolean isValueExists(Cursor cursor, String tableName) {
    method isSpecialTable (line 305) | private boolean isSpecialTable(String tableName) {
    method addAssociations (line 324) | private void addAssociations(Collection<AssociationsModel> associatedM...
    method createIntermediateTable (line 357) | private void createIntermediateTable(String tableName, String associat...
    method createGenericTable (line 394) | private void createGenericTable(GenericModel genericModel, SQLiteDatab...
    method addForeignKeyColumn (line 436) | protected void addForeignKeyColumn(String tableName, String associated...
    method isContainsOnlyIdField (line 473) | private boolean isContainsOnlyIdField(Collection<ColumnModel> columnMo...

FILE: core/src/main/java/org/litepal/tablemanager/AssociationUpdater.java
  class AssociationUpdater (line 44) | public abstract class AssociationUpdater extends Creator {
    method createOrUpgradeTable (line 63) | @Override
    method addOrUpdateAssociation (line 71) | @Override
    method getForeignKeyColumns (line 87) | protected List<String> getForeignKeyColumns(TableModel tableModel) {
    method isForeignKeyColumn (line 114) | protected boolean isForeignKeyColumn(TableModel tableModel, String col...
    method getTableModelFromDB (line 128) | protected TableModel getTableModelFromDB(String tableName) {
    method dropTables (line 140) | protected void dropTables(List<String> dropTableNames, SQLiteDatabase ...
    method removeColumns (line 159) | protected void removeColumns(Collection<String> removeColumnNames, Str...
    method clearCopyInTableSchema (line 173) | protected void clearCopyInTableSchema(List<String> tableNames) {
    method removeAssociations (line 198) | private void removeAssociations() {
    method removeForeignKeyColumns (line 208) | private void removeForeignKeyColumns() {
    method removeIntermediateTables (line 219) | private void removeIntermediateTables() {
    method removeGenericTables (line 229) | private void removeGenericTables() {
    method findForeignKeyToRemove (line 244) | private List<String> findForeignKeyToRemove(TableModel tableModel) {
    method findIntermediateTablesToDrop (line 267) | private List<String> findIntermediateTablesToDrop() {
    method findGenericTablesToDrop (line 299) | private List<String> findGenericTablesToDrop() {
    method generateAlterToTempTableSQL (line 327) | protected String generateAlterToTempTableSQL(String tableName) {
    method generateCreateNewTableSQL (line 344) | private String generateCreateNewTableSQL(Collection<String> removeColu...
    method generateDataMigrationSQL (line 358) | protected String generateDataMigrationSQL(TableModel tableModel) {
    method generateDropTempTableSQL (line 396) | protected String generateDropTempTableSQL(String tableName) {
    method getTempTableName (line 408) | protected String getTempTableName(String tableName) {
    method getRemoveColumnSQLs (line 422) | private List<String> getRemoveColumnSQLs(Collection<String> removeColu...
    method shouldDropForeignKey (line 455) | private boolean shouldDropForeignKey(String selfTableName, String asso...
    method isRelationCorrect (line 493) | private boolean isRelationCorrect(AssociationsModel associationModel, ...

FILE: core/src/main/java/org/litepal/tablemanager/Connector.java
  class Connector (line 37) | public class Connector {
    method getWritableDatabase (line 56) | public synchronized static SQLiteDatabase getWritableDatabase() {
    method getDatabase (line 69) | public static SQLiteDatabase getDatabase() {
    method buildConnection (line 84) | private static LitePalOpenHelper buildConnection() {
    method clearLitePalOpenHelperInstance (line 109) | public static void clearLitePalOpenHelperInstance() {

FILE: core/src/main/java/org/litepal/tablemanager/Creator.java
  class Creator (line 39) | class Creator extends AssociationCreator {
    method createOrUpgradeTable (line 46) | @Override
    method createOrUpgradeTable (line 53) | protected void createOrUpgradeTable(TableModel tableModel, SQLiteDatab...
    method getCreateTableSQLs (line 72) | protected List<String> getCreateTableSQLs(TableModel tableModel, SQLit...
    method generateDropTableSQL (line 95) | private String generateDropTableSQL(TableModel tableModel) {
    method generateCreateTableSQL (line 109) | String generateCreateTableSQL(TableModel tableModel) {
    method generateCreateIndexSQLs (line 121) | List<String> generateCreateIndexSQLs(TableModel tableModel) {

FILE: core/src/main/java/org/litepal/tablemanager/Dropper.java
  class Dropper (line 42) | public class Dropper extends AssociationUpdater {
    method createOrUpgradeTable (line 53) | @Override
    method dropTables (line 64) | private void dropTables() {
    method findTablesToDrop (line 76) | private List<String> findTablesToDrop() {
    method pickTableNamesFromTableModels (line 109) | private List<String> pickTableNamesFromTableModels() {
    method shouldDropThisTable (line 131) | private boolean shouldDropThisTable(String tableName, int tableType) {

FILE: core/src/main/java/org/litepal/tablemanager/Generator.java
  class Generator (line 45) | public abstract class Generator extends LitePalBase {
    method getAllTableModels (line 67) | protected Collection<TableModel> getAllTableModels() {
    method getAllAssociations (line 86) | protected Collection<AssociationsModel> getAllAssociations() {
    method execute (line 103) | protected void execute(List<String> sqls, SQLiteDatabase db) {
    method addAssociation (line 128) | private static void addAssociation(SQLiteDatabase db, boolean force) {
    method updateAssociations (line 140) | private static void updateAssociations(SQLiteDatabase db) {
    method upgradeTables (line 152) | private static void upgradeTables(SQLiteDatabase db) {
    method create (line 167) | private static void create(SQLiteDatabase db, boolean force) {
    method drop (line 179) | private static void drop(SQLiteDatabase db) {
    method canUseCache (line 191) | private boolean canUseCache() {
    method create (line 206) | static void create(SQLiteDatabase db) {
    method upgrade (line 219) | static void upgrade(SQLiteDatabase db) {
    method createOrUpgradeTable (line 237) | protected abstract void createOrUpgradeTable(SQLiteDatabase db, boolea...
    method addOrUpdateAssociation (line 249) | protected abstract void addOrUpdateAssociation(SQLiteDatabase db, bool...

FILE: core/src/main/java/org/litepal/tablemanager/LitePalOpenHelper.java
  class LitePalOpenHelper (line 43) | class LitePalOpenHelper extends SQLiteOpenHelper {
    method LitePalOpenHelper (line 63) | LitePalOpenHelper(Context context, String name, CursorFactory factory,...
    method LitePalOpenHelper (line 79) | LitePalOpenHelper(String dbName, int version) {
    method onCreate (line 83) | @Override
    method onUpgrade (line 97) | @Override

FILE: core/src/main/java/org/litepal/tablemanager/Upgrader.java
  class Upgrader (line 42) | public class Upgrader extends AssociationUpdater {
    method createOrUpgradeTable (line 62) | @Override
    method upgradeTable (line 78) | private void upgradeTable() {
    method hasNewUniqueOrNotNullColumn (line 106) | private boolean hasNewUniqueOrNotNullColumn() {
    method findColumnsToAdd (line 130) | private List<ColumnModel> findColumnsToAdd() {
    method findColumnsToRemove (line 153) | private List<String> findColumnsToRemove() {
    method findColumnTypesToChange (line 175) | private List<ColumnModel> findColumnTypesToChange() {
    method isNeedToRemove (line 215) | private boolean isNeedToRemove(String columnName) {
    method isRemovedFromClass (line 228) | private boolean isRemovedFromClass(String columnName) {
    method generateAddColumnSQLs (line 239) | private List<String> generateAddColumnSQLs(ColumnModel columnModel) {
    method getAddColumnSQLs (line 256) | private List<String> getAddColumnSQLs(List<ColumnModel> columnModelLis...
    method removeColumns (line 271) | private void removeColumns(List<String> removeColumnNames) {
    method addColumns (line 286) | private void addColumns(List<ColumnModel> columnModelList) {
    method changeColumnsType (line 301) | private void changeColumnsType(List<ColumnModel> columnModelList) {
    method changeColumnsConstraints (line 317) | private void changeColumnsConstraints() {
    method getChangeColumnsConstraintsSQL (line 329) | private List<String> getChangeColumnsConstraintsSQL() {
    method generateAddForeignKeySQL (line 357) | private List<String> generateAddForeignKeySQL() {

FILE: core/src/main/java/org/litepal/tablemanager/callback/DatabaseListener.java
  type DatabaseListener (line 24) | public interface DatabaseListener {
    method onCreate (line 26) | void onCreate();
    method onUpgrade (line 28) | void onUpgrade(int oldVersion, int newVersion);

FILE: core/src/main/java/org/litepal/tablemanager/model/AssociationsModel.java
  class AssociationsModel (line 33) | public class AssociationsModel {
    method getTableName (line 61) | public String getTableName() {
    method setTableName (line 71) | public void setTableName(String tableName) {
    method getAssociatedTableName (line 80) | public String getAssociatedTableName() {
    method setAssociatedTableName (line 90) | public void setAssociatedTableName(String associatedTableName) {
    method getTableHoldsForeignKey (line 99) | public String getTableHoldsForeignKey() {
    method setTableHoldsForeignKey (line 109) | public void setTableHoldsForeignKey(String tableHoldsForeignKey) {
    method getAssociationType (line 118) | public int getAssociationType() {
    method setAssociationType (line 130) | public void setAssociationType(int associationType) {
    method equals (line 139) | @Override

FILE: core/src/main/java/org/litepal/tablemanager/model/ColumnModel.java
  class ColumnModel (line 27) | public class ColumnModel {
    method getColumnName (line 59) | public String getColumnName() {
    method setColumnName (line 63) | public void setColumnName(String columnName) {
    method getColumnType (line 67) | public String getColumnType() {
    method setColumnType (line 71) | public void setColumnType(String columnType) {
    method isNullable (line 75) | public boolean isNullable() {
    method setNullable (line 79) | public void setNullable(boolean isNullable) {
    method isUnique (line 83) | public boolean isUnique() {
    method setUnique (line 87) | public void setUnique(boolean isUnique) {
    method getDefaultValue (line 91) | public String getDefaultValue() {
    method hasIndex (line 95) | public boolean hasIndex() {
    method setHasIndex (line 99) | public void setHasIndex(boolean hasIndex) {
    method setDefaultValue (line 103) | public void setDefaultValue(String defaultValue) {
    method isIdColumn (line 117) | public boolean isIdColumn() {

FILE: core/src/main/java/org/litepal/tablemanager/model/GenericModel.java
  class GenericModel (line 27) | public class GenericModel {
    method getTableName (line 54) | public String getTableName() {
    method setTableName (line 58) | public void setTableName(String tableName) {
    method getValueColumnName (line 62) | public String getValueColumnName() {
    method setValueColumnName (line 66) | public void setValueColumnName(String valueColumnName) {
    method getValueColumnType (line 70) | public String getValueColumnType() {
    method setValueColumnType (line 74) | public void setValueColumnType(String valueColumnType) {
    method getValueIdColumnName (line 78) | public String getValueIdColumnName() {
    method setValueIdColumnName (line 82) | public void setValueIdColumnName(String valueIdColumnName) {
    method getGetMethodName (line 86) | public String getGetMethodName() {
    method setGetMethodName (line 90) | public void setGetMethodName(String getMethodName) {

FILE: core/src/main/java/org/litepal/tablemanager/model/TableModel.java
  class TableModel (line 32) | public class TableModel {
    method getTableName (line 54) | public String getTableName() {
    method setTableName (line 64) | public void setTableName(String tableName) {
    method getClassName (line 73) | public String getClassName() {
    method setClassName (line 83) | public void setClassName(String className) {
    method addColumnModel (line 93) | public void addColumnModel(ColumnModel columnModel) {
    method getColumnModels (line 101) | public Collection<ColumnModel> getColumnModels() {
    method getColumnModelByName (line 111) | public ColumnModel getColumnModelByName(String columnName) {
    method removeColumnModelByName (line 120) | public void removeColumnModelByName(String columnName) {
    method containsColumn (line 130) | public boolean containsColumn(String columnName) {

FILE: core/src/main/java/org/litepal/tablemanager/typechange/BlobOrm.java
  class BlobOrm (line 9) | public class BlobOrm extends OrmChange{
    method object2Relation (line 15) | @Override

FILE: core/src/main/java/org/litepal/tablemanager/typechange/BooleanOrm.java
  class BooleanOrm (line 25) | public class BooleanOrm extends OrmChange {
    method object2Relation (line 31) | @Override

FILE: core/src/main/java/org/litepal/tablemanager/typechange/DateOrm.java
  class DateOrm (line 25) | public class DateOrm extends OrmChange {
    method object2Relation (line 31) | @Override

FILE: core/src/main/java/org/litepal/tablemanager/typechange/DecimalOrm.java
  class DecimalOrm (line 25) | public class DecimalOrm extends OrmChange {
    method object2Relation (line 31) | @Override

FILE: core/src/main/java/org/litepal/tablemanager/typechange/NumericOrm.java
  class NumericOrm (line 25) | public class NumericOrm extends OrmChange {
    method object2Relation (line 31) | @Override

FILE: core/src/main/java/org/litepal/tablemanager/typechange/OrmChange.java
  class OrmChange (line 28) | public abstract class OrmChange {
    method object2Relation (line 37) | public abstract String object2Relation(String fieldType);

FILE: core/src/main/java/org/litepal/tablemanager/typechange/TextOrm.java
  class TextOrm (line 25) | public class TextOrm extends OrmChange {
    method object2Relation (line 31) | @Override

FILE: core/src/main/java/org/litepal/util/BaseUtility.java
  class BaseUtility (line 39) | public class BaseUtility {
    method BaseUtility (line 44) | private BaseUtility() {
    method changeCase (line 56) | public static String changeCase(String string) {
    method containsIgnoreCases (line 84) | public static boolean containsIgnoreCases(Collection<String> collectio...
    method capitalize (line 108) | public static String capitalize(String string) {
    method count (line 124) | public static int count(String string, String mark) {
    method checkConditionsCorrect (line 148) | public static void checkConditionsCorrect(String... conditions) {
    method isFieldTypeSupported (line 169) | public static boolean isFieldTypeSupported(String fieldType) {
    method isGenericTypeSupported (line 205) | public static boolean isGenericTypeSupported(String genericType) {
    method isLitePalXMLExists (line 230) | public static boolean isLitePalXMLExists() {
    method isClassAndMethodExist (line 255) | public static boolean isClassAndMethodExist(String className, String m...

FILE: core/src/main/java/org/litepal/util/Const.java
  type Const (line 19) | public interface Const {
    type Model (line 21) | public interface Model {
    type Config (line 38) | public interface Config {
    type TableSchema (line 65) | public interface TableSchema {

FILE: core/src/main/java/org/litepal/util/DBUtility.java
  class DBUtility (line 45) | public class DBUtility {
    method DBUtility (line 62) | private DBUtility() {
    method getTableNameByClassName (line 75) | public static String getTableNameByClassName(String className) {
    method getIndexName (line 95) | public static String getIndexName(String tableName, String columnName) {
    method getTableNameListByClassNameList (line 111) | public static List<String> getTableNameListByClassNameList(List<String...
    method getTableNameByForeignColumn (line 129) | public static String getTableNameByForeignColumn(String foreignColumnN...
    method getIntermediateTableName (line 151) | public static String getIntermediateTableName(String tableName, String...
    method getGenericTableName (line 174) | public static String getGenericTableName(String className, String fiel...
    method getGenericValueIdColumnName (line 185) | public static String getGenericValueIdColumnName(String className) {
    method getM2MSelfRefColumnName (line 189) | public static String getM2MSelfRefColumnName(Field field) {
    method isIntermediateTable (line 201) | public static boolean isIntermediateTable(String tableName, SQLiteData...
    method isGenericTable (line 242) | public static boolean isGenericTable(String tableName, SQLiteDatabase ...
    method isTableExists (line 284) | public static boolean isTableExists(String tableName, SQLiteDatabase d...
    method isColumnExists (line 308) | public static boolean isColumnExists(String columnName, String tableNa...
    method findAllTableNames (line 346) | public static List<String> findAllTableNames(SQLiteDatabase db) {
    method findPragmaTableInfo (line 383) | public static TableModel findPragmaTableInfo(String tableName, SQLiteD...
    method findIndexedColumns (line 440) | public static Pair<Set<String>, Set<String>> findIndexedColumns(String...
    method isFieldNameConflictWithSQLiteKeywords (line 483) | public static boolean isFieldNameConflictWithSQLiteKeywords(String fie...
    method convertToValidColumnName (line 498) | public static String convertToValidColumnName(String columnName) {
    method convertWhereClauseToColumnName (line 511) | public static String convertWhereClauseToColumnName(String whereClause) {
    method convertSelectClauseToValidNames (line 540) | public static String[] convertSelectClauseToValidNames(String[] column...
    method convertOrderByClauseToValidName (line 558) | public static String convertOrderByClauseToValidName(String orderBy) {
    method convertOrderByItem (line 587) | private static String convertOrderByItem(String orderByItem) {

FILE: core/src/main/java/org/litepal/util/LitePalLog.java
  class LitePalLog (line 21) | public final class LitePalLog {
    method d (line 29) | public static void d(String tagName, String message) {
    method e (line 35) | public static void e(String tagName, Exception e){

FILE: core/src/main/java/org/litepal/util/SharedUtil.java
  class SharedUtil (line 33) | public class SharedUtil {
    method updateVersion (line 47) | public static void updateVersion(String extraKeyName, int newVersion) {
    method getLastVersion (line 67) | public static int getLastVersion(String extraKeyName) {
    method removeVersion (line 85) | public static void removeVersion(String extraKeyName) {

FILE: core/src/main/java/org/litepal/util/cipher/AESCrypt.java
  class AESCrypt (line 35) | public final class AESCrypt {
    method generateKey (line 59) | private static SecretKeySpec generateKey(final String password) throws...
    method encrypt (line 81) | public static String encrypt(final String password, String message)
    method encrypt (line 111) | public static byte[] encrypt(final SecretKeySpec key, final byte[] iv,...
    method decrypt (line 132) | public static String decrypt(final String password, String base64Encod...
    method decrypt (line 168) | public static byte[] decrypt(final SecretKeySpec key, final byte[] iv,...
    method log (line 183) | private static void log(String what, byte[] bytes) {
    method log (line 188) | private static void log(String what, String value) {
    method bytesToHex (line 199) | private static String bytesToHex(byte[] bytes) {
    method AESCrypt (line 212) | private AESCrypt() {

FILE: core/src/main/java/org/litepal/util/cipher/CipherUtil.java
  class CipherUtil (line 40) | public class CipherUtil {
    method aesEncrypt (line 52) | public static String aesEncrypt(String plainText) {
    method aesDecrypt (line 70) | public static String aesDecrypt(String encryptedText) {
    method md5Encrypt (line 88) | public static String md5Encrypt(String plainText) {
    method toHex (line 99) | private static char[] toHex(byte[] data) {

FILE: java/src/main/java/org/litepal/LitePal.java
  class LitePal (line 45) | public class LitePal {
    method initialize (line 55) | public static void initialize(Context context) {
    method getDatabase (line 64) | public static SQLiteDatabase getDatabase() {
    method use (line 73) | public static void use(LitePalDB litePalDB) {
    method useDefault (line 80) | public static void useDefault() {
    method deleteDatabase (line 90) | public static boolean deleteDatabase(String dbName) {
    method aesKey (line 94) | public static void aesKey(String key) {
    method select (line 113) | public static FluentQuery select(String... columns) {
    method where (line 132) | public static FluentQuery where(String... conditions) {
    method order (line 152) | public static FluentQuery order(String column) {
    method limit (line 170) | public static FluentQuery limit(int value) {
    method offset (line 188) | public static FluentQuery offset(int value) {
    method count (line 210) | public static int count(Class<?> modelClass) {
    method countAsync (line 221) | public static CountExecutor countAsync(final Class<?> modelClass) {
    method count (line 243) | public static int count(String tableName) {
    method countAsync (line 254) | public static CountExecutor countAsync(final String tableName) {
    method average (line 277) | public static double average(Class<?> modelClass, String column) {
    method averageAsync (line 290) | public static AverageExecutor averageAsync(final Class<?> modelClass, ...
    method average (line 313) | public static double average(String tableName, String column) {
    method averageAsync (line 326) | public static AverageExecutor averageAsync(final String tableName, fin...
    method max (line 352) | public static <T> T max(Class<?> modelClass, String columnName, Class<...
    method maxAsync (line 367) | public static <T> FindExecutor<T> maxAsync(final Class<?> modelClass, ...
    method max (line 393) | public static <T> T max(String tableName, String columnName, Class<T> ...
    method maxAsync (line 408) | public static <T> FindExecutor<T> maxAsync(final String tableName, fin...
    method min (line 434) | public static <T> T min(Class<?> modelClass, String columnName, Class<...
    method minAsync (line 449) | public static <T> FindExecutor<T> minAsync(final Class<?> modelClass, ...
    method min (line 475) | public static <T> T min(String tableName, String columnName, Class<T> ...
    method minAsync (line 490) | public static <T> FindExecutor<T> minAsync(final String tableName, fin...
    method sum (line 516) | public static <T> T sum(Class<?> modelClass, String columnName, Class<...
    method sumAsync (line 531) | public static <T> FindExecutor<T> sumAsync(final Class<?> modelClass, ...
    method sum (line 557) | public static <T> T sum(String tableName, String columnName, Class<T> ...
    method sumAsync (line 572) | public static <T> FindExecutor<T> sumAsync(final String tableName, fin...
    method find (line 596) | public static <T> T find(Class<T> modelClass, long id) {
    method findAsync (line 609) | public static <T> FindExecutor<T> findAsync(Class<T> modelClass, long ...
    method find (line 628) | public static <T> T find(Class<T> modelClass, long id, boolean isEager) {
    method findAsync (line 643) | public static <T> FindExecutor<T> findAsync(final Class<T> modelClass,...
    method findFirst (line 662) | public static <T> T findFirst(Class<T> modelClass) {
    method findFirstAsync (line 673) | public static <T> FindExecutor<T> findFirstAsync(Class<T> modelClass) {
    method findFirst (line 690) | public static <T> T findFirst(Class<T> modelClass, boolean isEager) {
    method findFirstAsync (line 703) | public static <T> FindExecutor<T> findFirstAsync(final Class<T> modelC...
    method findLast (line 722) | public static <T> T findLast(Class<T> modelClass) {
    method findLastAsync (line 733) | public static <T> FindExecutor<T> findLastAsync(Class<T> modelClass) {
    method findLast (line 750) | public static <T> T findLast(Class<T> modelClass, boolean isEager) {
    method findLastAsync (line 763) | public static <T> FindExecutor<T> findLastAsync(final Class<T> modelCl...
    method findAll (line 797) | public static <T> List<T> findAll(Class<T> modelClass, long... ids) {
    method findAllAsync (line 810) | public static <T> FindMultiExecutor<T> findAllAsync(Class<T> modelClas...
    method findAll (line 829) | public static <T> List<T> findAll(Class<T> modelClass, boolean isEager...
    method findAllAsync (line 844) | public static <T> FindMultiExecutor<T> findAllAsync(final Class<T> mod...
    method findBySQL (line 864) | public static Cursor findBySQL(String... sql) {
    method delete (line 885) | public static int delete(Class<?> modelClass, long id) {
    method deleteAsync (line 898) | public static UpdateOrDeleteExecutor deleteAsync(final Class<?> modelC...
    method deleteAll (line 926) | public static int deleteAll(Class<?> modelClass, String... conditions) {
    method deleteAllAsync (line 945) | public static UpdateOrDeleteExecutor deleteAllAsync(final Class<?> mod...
    method deleteAll (line 976) | public static int deleteAll(String tableName, String... conditions) {
    method deleteAllAsync (line 995) | public static UpdateOrDeleteExecutor deleteAllAsync(final String table...
    method update (line 1020) | public static int update(Class<?> modelClass, ContentValues values, lo...
    method updateAsync (line 1036) | public static UpdateOrDeleteExecutor updateAsync(final Class<?> modelC...
    method updateAll (line 1069) | public static int updateAll(Class<?> modelClass, ContentValues values,...
    method updateAllAsync (line 1091) | public static UpdateOrDeleteExecutor updateAllAsync(Class<?> modelClas...
    method updateAll (line 1124) | public static int updateAll(String tableName, ContentValues values, St...
    method updateAllAsync (line 1146) | public static UpdateOrDeleteExecutor updateAllAsync(final String table...
    method saveAll (line 1175) | public static <T extends LitePalSupport> void saveAll(Collection<T> co...
    method saveAllAsync (line 1186) | public static <T extends LitePalSupport> SaveExecutor saveAllAsync(fin...
    method markAsDeleted (line 1197) | public static <T extends LitePalSupport> void markAsDeleted(Collection...
    method isExist (line 1211) | public static <T> boolean isExist(Class<T> modelClass, String... condi...
    method registerDatabaseListener (line 1218) | public static void registerDatabaseListener(DatabaseListener listener) {

FILE: sample/src/androidTest/java/com/litepaltest/model/Book.java
  class Book (line 7) | public class Book extends LitePalSupport implements Serializable{
    method getId (line 27) | public long getId() {
    method setId (line 31) | public void setId(long id) {
    method getBookName (line 35) | public String getBookName() {
    method setBookName (line 39) | public void setBookName(String bookName) {
    method getPages (line 43) | public Integer getPages() {
    method setPages (line 47) | public void setPages(Integer pages) {
    method getPrice (line 51) | public double getPrice() {
    method setPrice (line 55) | public void setPrice(double price) {
    method getLevel (line 59) | public char getLevel() {
    method setLevel (line 63) | public void setLevel(char level) {
    method getIsbn (line 67) | public short getIsbn() {
    method setIsbn (line 71) | public void setIsbn(short isbn) {
    method isPublished (line 75) | public boolean isPublished() {
    method setPublished (line 79) | public void setPublished(boolean isPublished) {
    method getArea (line 83) | public float getArea() {
    method setArea (line 87) | public void setArea(float area) {

FILE: sample/src/androidTest/java/com/litepaltest/model/Cellphone.java
  class Cellphone (line 9) | public class Cellphone extends LitePalSupport {
    method getId (line 31) | public Long getId() {
    method setId (line 35) | public void setId(Long id) {
    method getBrand (line 39) | public String getBrand() {
    method setBrand (line 43) | public void setBrand(String brand) {
    method getInStock (line 47) | public Character getInStock() {
    method setInStock (line 51) | public void setInStock(Character inStock) {
    method getPrice (line 55) | public Double getPrice() {
    method setPrice (line 59) | public void setPrice(Double price) {
    method getSerial (line 63) | public String getSerial() {
    method setSerial (line 67) | public void setSerial(String serial) {
    method getMac (line 71) | public String getMac() {
    method setMac (line 75) | public void setMac(String mac) {
    method getUuid (line 79) | public String getUuid() {
    method setUuid (line 83) | public void setUuid(String uuid) {
    method getMessages (line 87) | public List<WeiboMessage> getMessages() {
    method setMessages (line 91) | public void setMessages(List<WeiboMessage> messages) {

FILE: sample/src/androidTest/java/com/litepaltest/model/Classroom.java
  class Classroom (line 10) | public class Classroom extends LitePalSupport {
    method get_id (line 26) | public int get_id() {
    method set_id (line 34) | public void set_id(int _id) {
    method getName (line 41) | public String getName() {
    method setName (line 49) | public void setName(String name) {
    method getStudentCollection (line 53) | public Set<Student> getStudentCollection() {
    method setStudentCollection (line 57) | public void setStudentCollection(Set<Student> studentCollection) {
    method getTeachers (line 61) | public List<Teacher> getTeachers() {
    method setTeachers (line 65) | public void setTeachers(List<Teacher> teachers) {
    method getNews (line 69) | public List<String> getNews() {
    method setNews (line 73) | public void setNews(List<String> news) {
    method getNumbers (line 77) | public List<Integer> getNumbers() {
    method setNumbers (line 81) | public void setNumbers(List<Integer> numbers) {

FILE: sample/src/androidTest/java/com/litepaltest/model/Computer.java
  class Computer (line 5) | public class Computer extends LitePalSupport {
    method Computer (line 13) | public Computer(String brand, double price) {
    method getId (line 18) | public long getId() {
    method getBrand (line 22) | public String getBrand() {
    method setBrand (line 26) | public void setBrand(String brand) {
    method getPrice (line 30) | public double getPrice() {
    method setPrice (line 34) | public void setPrice(double price) {

FILE: sample/src/androidTest/java/com/litepaltest/model/Headset.java
  class Headset (line 3) | public class Headset {
    method getId (line 15) | public int getId() {
    method setId (line 19) | public void setId(int id) {
    method getBrand (line 23) | public String getBrand() {
    method setBrand (line 27) | public void setBrand(String brand) {
    method getColor (line 31) | public String getColor() {
    method setColor (line 35) | public void setColor(String color) {
    method getType (line 39) | public int getType() {
    method setType (line 43) | public void setType(int type) {
    method getPrice (line 47) | public double getPrice() {
    method setPrice (line 51) | public void setPrice(double price) {

FILE: sample/src/androidTest/java/com/litepaltest/model/IdCard.java
  class IdCard (line 5) | public class IdCard extends LitePalSupport {
    method getId (line 16) | public int getId() {
    method setId (line 24) | public void setId(int id) {
    method getNumber (line 31) | public String getNumber() {
    method setNumber (line 39) | public void setNumber(String number) {
    method getAddress (line 46) | public String getAddress() {
    method setAddress (line 54) | public void setAddress(String address) {
    method getStudent (line 61) | public Student getStudent() {
    method setStudent (line 68) | public void setStudent(Student student) {
    method getSerial (line 72) | public long getSerial() {
    method setSerial (line 76) | public void setSerial(long serial) {

FILE: sample/src/androidTest/java/com/litepaltest/model/Message.java
  class Message (line 6) | public class Message extends LitePalSupport {
    method getContent (line 17) | public String getContent() {
    method setContent (line 21) | public void setContent(String content) {
    method getType (line 25) | public int getType() {
    method setType (line 29) | public void setType(int type) {
    method getTitle (line 33) | public String getTitle() {
    method setTitle (line 37) | public void setTitle(String title) {
    method getId (line 41) | public int getId() {
    method setId (line 45) | public void setId(int id) {

FILE: sample/src/androidTest/java/com/litepaltest/model/Product.java
  class Product (line 5) | public class Product extends LitePalSupport{
    method Product (line 15) | public Product() {
    method Product (line 18) | public Product(Product p) {
    method getId (line 21) | public int getId() {
    method setId (line 25) | public void setId(int id) {
    method getBrand (line 29) | public String getBrand() {
    method setBrand (line 33) | public void setBrand(String brand) {
    method getPrice (line 37) | public double getPrice() {
    method setPrice (line 41) | public void setPrice(double price) {
    method getPic (line 45) | public byte[] getPic() {
    method setPic (line 49) | public void setPic(byte[] pic) {

FILE: sample/src/androidTest/java/com/litepaltest/model/Student.java
  class Student (line 10) | public class Student extends LitePalSupport {
    method getName (line 38) | public String getName() {
    method getClassroom (line 45) | public Classroom getClassroom() {
    method setClassroom (line 53) | public void setClassroom(Classroom classroom) {
    method getId (line 60) | public int getId() {
    method setId (line 68) | public void setId(int id) {
    method setName (line 76) | public void setName(String name) {
    method getAge (line 83) | public int getAge() {
    method setAge (line 91) | public void setAge(int age) {
    method getBirthday (line 98) | public Date getBirthday() {
    method setBirthday (line 106) | public void setBirthday(Date birthday) {
    method getIdcard (line 113) | public IdCard getIdcard() {
    method setIdcard (line 121) | public void setIdcard(IdCard idcard) {
    method getTeachers (line 125) | public List<Teacher> getTeachers() {
    method setTeachers (line 129) | public void setTeachers(List<Teacher> teachers) {
    method getSchoolDate (line 148) | public Date getSchoolDate() {
    method setSchoolDate (line 152) | public void setSchoolDate(Date schoolDate) {

FILE: sample/src/androidTest/java/com/litepaltest/model/Teacher.java
  class Teacher (line 8) | public class Teacher extends LitePalSupport {
    method getTeacherName (line 43) | public String getTeacherName() {
    method getIdCard (line 50) | public IdCard getIdCard() {
    method setIdCard (line 58) | public void setIdCard(IdCard idCard) {
    method setTeacherName (line 66) | public void setTeacherName(String teacherName) {
    method getAge (line 73) | public int getAge() {
    method setAge (line 81) | public void setAge(int age) {
    method getTeachYears (line 88) | public int getTeachYears() {
    method setTeachYears (line 96) | public void setTeachYears(int teachYears) {
    method getId (line 103) | public int getId() {
    method setId (line 111) | public void setId(int id) {
    method isSex (line 118) | public boolean isSex() {
    method setSex (line 126) | public void setSex(boolean sex) {
    method getStudents (line 130) | public List<Student> getStudents() {
    method setStudents (line 134) | public void setStudents(List<Student> students) {

FILE: sample/src/androidTest/java/com/litepaltest/model/WeChatMessage.java
  class WeChatMessage (line 3) | public class WeChatMessage extends Message {
    method getFriend (line 7) | public String getFriend() {
    method setFriend (line 11) | public void setFriend(String friend) {

FILE: sample/src/androidTest/java/com/litepaltest/model/WeiboMessage.java
  class WeiboMessage (line 5) | public class WeiboMessage extends Message {
    method getFollower (line 14) | public String getFollower() {
    method setFollower (line 18) | public void setFollower(String follower) {
    method getNumber (line 22) | public int getNumber() {
    method setNumber (line 26) | public void setNumber(int number) {
    method getCellphone (line 30) | public Cellphone getCellphone() {
    method setCellphone (line 34) | public void setCellphone(Cellphone cellphone) {

FILE: sample/src/androidTest/java/com/litepaltest/test/LitePalTestCase.java
  class LitePalTestCase (line 25) | @SmallTest
    method assertM2M (line 28) | protected void assertM2M(String table1, String table2, long id1, long ...
    method assertM2MFalse (line 32) | protected void assertM2MFalse(String table1, String table2, long id1, ...
    method isFKInsertCorrect (line 48) | protected boolean isFKInsertCorrect(String table1, String table2, long...
    method isIntermediateDataCorrect (line 62) | protected boolean isIntermediateDataCorrect(String table1, String tabl...
    method getForeignKeyValue (line 82) | protected long getForeignKeyValue(String tableWithFK, String tableWith...
    method isDataExists (line 94) | protected boolean isDataExists(String table, long id) {
    method getTableName (line 105) | protected String getTableName(Object object) {
    method getTableName (line 109) | protected String getTableName(Class<?> c) {
    method getRowsCount (line 113) | protected int getRowsCount(String tableName) {
    method getBooks (line 121) | protected List<Book> getBooks(String[] columns, String selection, Stri...
    method getClassroom (line 155) | protected Classroom getClassroom(long id) {
    method getIdCard (line 168) | protected IdCard getIdCard(long id) {
    method getComputer (line 183) | protected Computer getComputer(long id) {
    method getCellPhone (line 198) | protected Cellphone getCellPhone(long id) {
    method getTeacher (line 215) | protected Teacher getTeacher(long id) {
    method getStudent (line 238) | protected Student getStudent(long id) {
    method getTeachers (line 253) | protected List<Teacher> getTeachers(int[] ids) {
    method getStudents (line 277) | protected List<Student> getStudents(int[] ids) {
    method getWhere (line 293) | private String getWhere(int[] ids) {

FILE: sample/src/androidTest/java/com/litepaltest/test/MultiDatabaseTest.java
  class MultiDatabaseTest (line 23) | @SmallTest
    method testMultiDatabase (line 26) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/annotation/ColumnTest.java
  class ColumnTest (line 21) | @SmallTest
    method setUp (line 24) | @Before
    method testUnique (line 29) | @Test
    method testNotNull (line 46) | @Test
    method testDefaultValue (line 57) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/delete/DeleteTest.java
  class DeleteTest (line 32) | @SmallTest
    method setUp (line 57) | @Before
    method createClassroomStudentsTeachers (line 63) | @Test
    method createStudentsTeachersWithIdCard (line 83) | @Test
    method createStudentsTeachersWithAssociations (line 99) | @Test
    method testDeleteWithNoParameter (line 114) | @Test
    method testDeleteById (line 124) | @Test
    method testDeleteNoSavedModelWithNoParameter (line 134) | @Test
    method testDeleteWithNotExistsRecordById (line 143) | @Test
    method testDeleteCascadeM2OAssociationsOnMSideWithNoParameter (line 149) | @Test
    method testDeleteCascadeM2OAssociationsOnMSideById (line 161) | @Test
    method testDeleteAllCascadeM2OAssociationsOnMSide (line 173) | @Test
    method testDeleteCascadeM2OAssociationsOnOSideWithNoParameter (line 185) | @Test
    method testDeleteCascadeM2OAssociationsOnOSideById (line 202) | @Test
    method testDeleteAllCascadeM2OAssociationsOnOSide (line 219) | @Test
    method testDeleteCascadeO2OAssociationsWithNoParameter (line 236) | @Test
    method testDeleteCascadeO2OAssociationsById (line 256) | @Test
    method testDeleteAllCascadeO2OAssociations (line 276) | @Test
    method testDeleteCascadeM2MAssociationsWithNoParameter (line 296) | @Test
    method testDeleteCascadeM2MAssociationsById (line 314) | @Test
    method testDeleteAllCascadeM2MAssociations (line 332) | @Test
    method testDeleteAllCascadeWithConditions (line 350) | @Test
    method testDeleteAll (line 380) | @Test
    method testDeleteAllRows (line 399) | @Test
    method testMarkAsDeleted (line 424) | @Test
    method testDeleteAllWithWrongConditions (line 448) | @Test
    method testDeleteWithGenericData (line 469) | @Test
    method initGameRoom (line 499) | private void initGameRoom() {
    method initJude (line 504) | private void initJude() {
    method initRose (line 515) | private void initRose() {
    method initJohn (line 525) | private void initJohn() {
    method initMike (line 536) | private void initMike() {

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryBasicTest.java
  class QueryBasicTest (line 18) | @SmallTest
    method testFind (line 21) | @Test
    method testFindMul (line 45) | @Test
    method testFindAll (line 95) | @Test
    method testFindFirst (line 115) | @Test
    method testFindLast (line 131) | @Test
    method testIsExist (line 147) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryBySQLTest.java
  class QueryBySQLTest (line 19) | @SmallTest
    method setUp (line 26) | @Before
    method testQueryBySQL (line 35) | @Test
    method testQueryBySQLWithPlaceHolder (line 42) | @Test
    method testQueryBySQLWithWrongParams (line 56) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryClusterTest.java
  class QueryClusterTest (line 19) | @SmallTest
    method testSelect (line 22) | @Test
    method testWhere (line 66) | @Test
    method testOrder (line 112) | @Test
    method testLimit (line 184) | @Test
    method testOffset (line 216) | @Test
    method testCluster (line 236) | @Test
    method testBooleanQuery (line 314) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryDateTest.java
  class QueryDateTest (line 16) | @SmallTest
    method testQueryDate (line 19) | @Test
    method testQueryDateBefore1970 (line 33) | @Test
    method testQueryDateWithDefaultValue (line 47) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryEagerTest.java
  class QueryEagerTest (line 24) | @SmallTest
    method setUp (line 41) | @Before
    method testEagerFind (line 86) | @Test
    method resetData (line 160) | public void resetData() {
    method testEagerFindFirst (line 168) | @Test
    method testEagerFindLast (line 177) | @Test
    method testEagerFindAll (line 186) | @Test
    method testEagerClusterQuery (line 219) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryMathTest.java
  class QueryMathTest (line 17) | @SmallTest
    method setUp (line 22) | @Before
    method testCount (line 27) | @Test
    method testAverage (line 51) | @Test
    method testMax (line 76) | @Test
    method testMin (line 95) | @Test
    method testSum (line 114) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/save/Many2ManySaveTest.java
  class Many2ManySaveTest (line 19) | @SmallTest
    method init (line 30) | private void init() {
    method buildBidirectionalAssociation (line 49) | private void buildBidirectionalAssociation() {
    method buildUnidirectionalAssociation (line 60) | private void buildUnidirectionalAssociation() {
    method getModelList (line 74) | private List<LitePalSupport> getModelList() {
    method saveAllByRandom (line 83) | private void saveAllByRandom() {
    method testCase1 (line 93) | @Test
    method testCase2 (line 108) | @Test
    method testCase3 (line 125) | @Test
    method testCase4 (line 141) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/save/Many2OneBiSaveTest.java
  class Many2OneBiSaveTest (line 16) | @SmallTest
    method init (line 25) | public void init() {
    method testCase1 (line 34) | @Test
    method testCase2 (line 47) | @Test
    method testCase3 (line 60) | @Test
    method testCase4 (line 73) | @Test
    method testCase5 (line 84) | @Test
    method testCase6 (line 95) | @Test
    method testCase7 (line 106) | @Test
    method testCase8 (line 121) | @Test
    method testCase9 (line 136) | @Test
    method testCase10 (line 151) | @Test
    method assertFK (line 172) | private void assertFK(Classroom c1, Student s1, Student s2) {

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/save/Many2OneUniSaveTest.java
  class Many2OneUniSaveTest (line 13) | @SmallTest
    method init (line 22) | public void init() {
    method testCase1 (line 33) | @Test
    method testCase2 (line 44) | @Test
    method testCase3 (line 55) | @Test
    method testCase4 (line 66) | @Test
    method assertFK (line 77) | private void assertFK(Classroom c1, Teacher t1, Teacher t2) {

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/save/One2OneBiSaveTest.java
  class One2OneBiSaveTest (line 13) | @SmallTest
    method init (line 20) | private void init() {
    method testO2OBiSaveStudentFirst (line 29) | @Test
    method testO2OBiSaveIdCardFirst (line 39) | @Test
    method testO2OBiBuildNullAssocations (line 49) | @Test
    method testO2OBiBuildUniAssociationsSaveStudentFirst (line 60) | @Test
    method testO2OBiBuildUniAssociationsSaveIdCardFirst (line 69) | @Test
    method assertFK (line 78) | private void assertFK(Student s, IdCard i) {

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/save/One2OneUniSaveTest.java
  class One2OneUniSaveTest (line 13) | @SmallTest
    method init (line 20) | private void init() {
    method testSaveIdCardFirst (line 30) | @Test
    method testSaveTeacherFirst (line 39) | @Test
    method testBuildNullAssociations (line 48) | @Test
    method assertFK (line 58) | private void assertFK(Teacher t, IdCard i) {

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/save/SaveAllTest.java
  class SaveAllTest (line 26) | @SmallTest
    method setUp (line 33) | @Before
    method testSaveAll (line 39) | @Test
    method testSaveAllWithM2OOnOneSide (line 55) | @Test
    method testSaveAllWithM2OOnManySide (line 73) | @Test
    method testSaveAllWithO2O (line 92) | @Test
    method testSaveAllWithM2M (line 115) | @Test
    method testSaveAllGenericData (line 157) | @Test
    method testSaveAllFailed (line 182) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/save/SaveTest.java
  class SaveTest (line 30) | @SmallTest
    method testSave (line 33) | @Test
    method testSaveWithConstructors (line 44) | @Test
    method testSaveAfterDelete (line 61) | @Test
    method testSaveInheritModels (line 147) | @Test
    method testSaveInheritModelsWithAssociations (line 172) | @Test
    method testSaveGenericData (line 214) | @Test
    method testSaveLongMaximumNumber (line 240) | @Test
    method testNullValue (line 250) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/transaction/TransactionTest.java
  class TransactionTest (line 23) | @SmallTest
    method testTransactionForSave (line 26) | @Test
    method testTransactionForSaveAll (line 51) | @Test
    method testTransactionForUpdate (line 81) | @Test
    method testTransactionForDelete (line 102) | @Test
    method testTransactionForCRUD (line 122) | @Test
    method testTransactionSuccessfulForCRUD (line 153) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/update/UpdateUsingSaveMethodTest.java
  class UpdateUsingSaveMethodTest (line 27) | @SmallTest
    method setUp (line 54) | @Before
    method init (line 62) | private void init() {
    method testUpdateBasicValues (line 93) | @Test
    method testUpdateGenericData (line 111) | @Test
    method testUpdateM2OAssociationsOnMSide (line 137) | @Test
    method testUpdateM2OAssociationsOnOSide (line 162) | @Test
    method testUpdateM2OAssociationsOnMSideWithNotSavedModel (line 178) | @Test
    method testUpdateM2OAssociationsOnOSideWithNotSavedModel (line 194) | @Test
    method testUpdateM2OAssociationsOnMSideWithNull (line 208) | @Test
    method testUpdateM2OAssociationsOnOSideWithNull (line 224) | @Test
    method testUpdateM2OAssociationsOnOSideWithEmptyCollection (line 238) | @Test
    method testUpdateO2OAssociations (line 252) | @Test
    method testUpdateO2OAssociationsWithNull (line 265) | @Test
    method testUpdateM2MAssociations (line 280) | @Test
    method testUpdateM2MAssociationsWithNull (line 319) | @Test
    method testUpdateM2MAssociationsWithRefreshedCollection (line 363) | @Test
    method testUpdateM2MAssociationsWithEmptyCollection (line 411) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/crud/update/UpdateUsingUpdateMethodTest.java
  class UpdateUsingUpdateMethodTest (line 29) | @SmallTest
    method setUp (line 54) | @Before
    method init (line 60) | private void init() {
    method initForAssociations (line 84) | private void initForAssociations() {
    method testUpdateWithStaticUpdate (line 108) | @Test
    method testUpdateWithStaticUpdateButWrongClass (line 122) | @Test
    method testUpdateWithStaticUpdateButWrongColumn (line 132) | @Test
    method testUpdateWithStaticUpdateButNotExistsRecord (line 143) | @Test
    method testUpdateWithInstanceUpdate (line 151) | @Test
    method testUpdateWithDefaultValueWithInstanceUpdate (line 166) | @Test
    method testUpdateToDefaultValueWithInstanceUpdate (line 190) | @Test
    method testUpdateToDefaultValueWithInstanceUpdateButWrongField (line 216) | @Test
    method testUpdateWithInstanceUpdateWithConstructor (line 230) | @Test
    method testUpdateWithInstanceUpdateButNotExistsRecord (line 243) | @Test
    method testUpdateAllWithStaticUpdate (line 382) | @Test
    method testUpdateAllRowsWithStaticUpdate (line 410) | @Test
    method testUpdateAllWithStaticUpdateButWrongConditions (line 425) | @Test
    method testUpdateAllWithInstanceUpdate (line 448) | @Test
    method testUpdateAllRowsWithInstanceUpdate (line 479) | @Test
    method testUpdateAllWithDefaultValueWithInstanceUpdate (line 490) | @Test
    method testUpdateAllToDefaultValueWithInstanceUpdate (line 519) | @Test
    method testUpdateAllToDefaultValueWithInstanceUpdateButWrongField (line 542) | @Test
    method testUpdateAllWithInstanceUpdateButWrongConditions (line 556) | @Test
    method testUpdateGenericData (line 579) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/util/BaseUtilityTest.java
  class BaseUtilityTest (line 12) | @SmallTest
    method testCount (line 15) | @Test

FILE: sample/src/androidTest/java/com/litepaltest/test/util/DBUtilityTest.java
  class DBUtilityTest (line 21) | @SmallTest
    method setUp (line 26) | @Before
    method testFindIndexedColumns (line 31) | @Test

FILE: sample/src/main/java/org/litepal/litepalsample/MyApplication.java
  class MyApplication (line 7) | public class MyApplication extends Application{
    method onCreate (line 9) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/AggregateActivity.java
  class AggregateActivity (line 29) | public class AggregateActivity extends AppCompatActivity implements OnCl...
    method actionStart (line 31) | public static void actionStart(Context context) {
    method onCreate (line 36) | @Override
    method onClick (line 52) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/AverageSampleActivity.java
  class AverageSampleActivity (line 33) | public class AverageSampleActivity extends AppCompatActivity implements ...
    method actionStart (line 39) | public static void actionStart(Context context) {
    method onCreate (line 44) | @Override
    method onClick (line 56) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/CRUDActivity.java
  class CRUDActivity (line 29) | public class CRUDActivity extends AppCompatActivity implements OnClickLi...
    method actionStart (line 31) | public static void actionStart(Context context) {
    method onCreate (line 36) | @Override
    method onClick (line 50) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/CountSampleActivity.java
  class CountSampleActivity (line 33) | public class CountSampleActivity extends AppCompatActivity implements On...
    method actionStart (line 39) | public static void actionStart(Context context) {
    method onCreate (line 44) | @Override
    method onClick (line 56) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/DeleteSampleActivity.java
  class DeleteSampleActivity (line 41) | public class DeleteSampleActivity extends AppCompatActivity implements O...
    method actionStart (line 55) | public static void actionStart(Context context) {
    method onCreate (line 60) | @Override
    method onClick (line 78) | @Override
    method populateDataFromDB (line 117) | private void populateDataFromDB() {

FILE: sample/src/main/java/org/litepal/litepalsample/activity/MainActivity.java
  class MainActivity (line 27) | public class MainActivity extends AppCompatActivity implements OnClickLi...
    method onCreate (line 31) | @Override
    method onClick (line 43) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/ManageTablesActivity.java
  class ManageTablesActivity (line 29) | public class ManageTablesActivity extends AppCompatActivity implements O...
    method actionStart (line 31) | public static void actionStart(Context context) {
    method onCreate (line 36) | @Override
    method onClick (line 46) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/MaxSampleActivity.java
  class MaxSampleActivity (line 33) | public class MaxSampleActivity extends AppCompatActivity implements OnCl...
    method actionStart (line 39) | public static void actionStart(Context context) {
    method onCreate (line 44) | @Override
    method onClick (line 56) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/MinSampleActivity.java
  class MinSampleActivity (line 33) | public class MinSampleActivity extends AppCompatActivity implements OnCl...
    method actionStart (line 39) | public static void actionStart(Context context) {
    method onCreate (line 44) | @Override
    method onClick (line 56) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/ModelListActivity.java
  class ModelListActivity (line 43) | public class ModelListActivity extends AppCompatActivity {
    method actionStart (line 47) | public static void actionStart(Context context) {
    method onCreate (line 52) | @Override
    method populateMappingClasses (line 68) | private void populateMappingClasses() {
    method getInputStream (line 97) | private InputStream getInputStream() throws IOException {

FILE: sample/src/main/java/org/litepal/litepalsample/activity/ModelStructureActivity.java
  class ModelStructureActivity (line 39) | public class ModelStructureActivity extends AppCompatActivity {
    method actionStart (line 47) | public static void actionStart(Context context, String className) {
    method onCreate (line 53) | @Override
    method analyzeModelStructure (line 65) | private void analyzeModelStructure() {
    class MyArrayAdapter (line 85) | class MyArrayAdapter extends ArrayAdapter<Field> {
      method MyArrayAdapter (line 87) | public MyArrayAdapter(Context context, int textViewResourceId, List<...
      method getView (line 91) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/QuerySampleActivity.java
  class QuerySampleActivity (line 26) | public class QuerySampleActivity extends AppCompatActivity {
    method actionStart (line 28) | public static void actionStart(Context context) {
    method onCreate (line 33) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/SaveSampleActivity.java
  class SaveSampleActivity (line 40) | public class SaveSampleActivity extends AppCompatActivity implements OnC...
    method actionStart (line 56) | public static void actionStart(Context context) {
    method onCreate (line 61) | @Override
    method onClick (line 77) | @Override
    method populateDataFromDB (line 100) | private void populateDataFromDB() {
    method refreshListView (line 148) | private void refreshListView(long id, String name, int age, int isMale) {

FILE: sample/src/main/java/org/litepal/litepalsample/activity/SumSampleActivity.java
  class SumSampleActivity (line 33) | public class SumSampleActivity extends AppCompatActivity implements OnCl...
    method actionStart (line 39) | public static void actionStart(Context context) {
    method onCreate (line 44) | @Override
    method onClick (line 56) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/TableListActivity.java
  class TableListActivity (line 37) | public class TableListActivity extends AppCompatActivity {
    method actionStart (line 45) | public static void actionStart(Context context) {
    method onCreate (line 50) | @Override
    method populateTables (line 67) | private void populateTables() {

FILE: sample/src/main/java/org/litepal/litepalsample/activity/TableStructureActivity.java
  class TableStructureActivity (line 41) | public class TableStructureActivity extends AppCompatActivity {
    method actionStart (line 49) | public static void actionStart(Context context, String tableName) {
    method onCreate (line 55) | @Override
    method analyzeTableStructure (line 67) | private void analyzeTableStructure() {
    class MyArrayAdapter (line 73) | class MyArrayAdapter extends ArrayAdapter<ColumnModel> {
      method MyArrayAdapter (line 75) | public MyArrayAdapter(Context context, int textViewResourceId, List<...
      method getView (line 79) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/activity/UpdateSampleActivity.java
  class UpdateSampleActivity (line 40) | public class UpdateSampleActivity extends AppCompatActivity implements O...
    method actionStart (line 58) | public static void actionStart(Context context) {
    method onCreate (line 63) | @Override
    method onClick (line 83) | @Override
    method populateDataFromDB (line 127) | private void populateDataFromDB() {

FILE: sample/src/main/java/org/litepal/litepalsample/adapter/DataArrayAdapter.java
  class DataArrayAdapter (line 32) | public class DataArrayAdapter extends ArrayAdapter<List<String>> {
    method DataArrayAdapter (line 34) | public DataArrayAdapter(Context context, int textViewResourceId, List<...
    method getView (line 38) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/adapter/StringArrayAdapter.java
  class StringArrayAdapter (line 30) | public class StringArrayAdapter extends ArrayAdapter<String> {
    method StringArrayAdapter (line 32) | public StringArrayAdapter(Context context, int textViewResourceId, Lis...
    method getView (line 36) | @Override

FILE: sample/src/main/java/org/litepal/litepalsample/model/Album.java
  class Album (line 25) | public class Album extends LitePalSupport {
    method getId (line 51) | public long getId() {
    method setId (line 55) | public void setId(long id) {
    method getName (line 59) | public String getName() {
    method setName (line 63) | public void setName(String name) {
    method getPublisher (line 67) | public String getPublisher() {
    method setPublisher (line 71) | public void setPublisher(String publisher) {
    method getPrice (line 75) | public double getPrice() {
    method setPrice (line 79) | public void setPrice(double price) {
    method getRelease (line 83) | public Date getRelease() {
    method setRelease (line 87) | public void setRelease(Date release) {
    method getSinger (line 91) | public Singer getSinger() {
    method setSinger (line 95) | public void setSinger(Singer singer) {
    method getSongs (line 99) | public List<Song> getSongs() {
    method setSongs (line 103) | public void setSongs(List<Song> songs) {
    method getSerial (line 107) | public String getSerial() {
    method setSerial (line 111) | public void setSerial(String serial) {
    method getSales (line 115) | public int getSales() {
    method setSales (line 119) | public void setSales(int sales) {

FILE: sample/src/main/java/org/litepal/litepalsample/model/Singer.java
  class Singer (line 24) | public class Singer extends LitePalSupport {
    method getId (line 36) | public long getId() {
    method setId (line 40) | public void setId(long id) {
    method getName (line 44) | public String getName() {
    method setName (line 48) | public void setName(String name) {
    method getAge (line 52) | public int getAge() {
    method setAge (line 56) | public void setAge(int age) {
    method isMale (line 60) | public boolean isMale() {
    method setMale (line 64) | public void setMale(boolean isMale) {
    method getAlbums (line 68) | public List<Album> getAlbums() {
    method setAlbums (line 72) | public void setAlbums(List<Album> albums) {

FILE: sample/src/main/java/org/litepal/litepalsample/model/Song.java
  class Song (line 22) | public class Song extends LitePalSupport {
    method getId (line 36) | public long getId() {
    method setId (line 40) | public void setId(long id) {
    method getName (line 44) | public String getName() {
    method setName (line 48) | public void setName(String name) {
    method getLyric (line 52) | public String getLyric() {
    method setLyric (line 56) | public void setLyric(String lyric) {
    method getDuration (line 60) | public String getDuration() {
    method setDuration (line 64) | public void setDuration(String duration) {
    method getAlbum (line 68) | public Album getAlbum() {
    method setAlbum (line 72) | public void setAlbum(Album album) {

FILE: sample/src/main/java/org/litepal/litepalsample/util/Utility.java
  class Utility (line 21) | public class Utility {
    method dp2px (line 23) | public static int dp2px(Context context, float dpValue) {
    method px2dp (line 28) | public static int px2dp(Context context, float pxValue) {
Condensed preview — 223 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,214K chars).
[
  {
    "path": ".gitignore",
    "chars": 387,
    "preview": ".gradle\ngradle.properties\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\nbin\ntmp\ngen\n\n########"
  },
  {
    "path": "LICENSE",
    "chars": 11325,
    "preview": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licens"
  },
  {
    "path": "README.md",
    "chars": 15768,
    "preview": "# LitePal for Android  \n![Logo](https://github.com/LitePalFramework/LitePal/blob/master/sample/src/main/logo/mini_logo.p"
  },
  {
    "path": "build.gradle",
    "chars": 509,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    e"
  },
  {
    "path": "core/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "core/build.gradle",
    "chars": 723,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\n\nandroid {\n    compileSdkVersion 31\n\n    defaultConfi"
  },
  {
    "path": "core/proguard-rules.pro",
    "chars": 653,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /h"
  },
  {
    "path": "core/src/main/AndroidManifest.xml",
    "chars": 85,
    "preview": "<manifest package=\"org.litepal\">\n\n    <application>\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "core/src/main/java/org/litepal/FluentQuery.java",
    "chars": 30566,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/LitePal.kt",
    "chars": 44637,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/LitePalApplication.java",
    "chars": 2505,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/LitePalBase.java",
    "chars": 30445,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/LitePalDB.java",
    "chars": 4046,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/Operator.java",
    "chars": 59913,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/annotation/Column.java",
    "chars": 1595,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/annotation/Encrypt.java",
    "chars": 1122,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/AssociationsAnalyzer.java",
    "chars": 7430,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/DataHandler.java",
    "chars": 54563,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/DeleteHandler.java",
    "chars": 15848,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/DynamicExecutor.java",
    "chars": 5143,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/LitePalSupport.java",
    "chars": 27612,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/Many2ManyAnalyzer.java",
    "chars": 8173,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/Many2OneAnalyzer.java",
    "chars": 7173,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/One2OneAnalyzer.java",
    "chars": 4835,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/QueryHandler.java",
    "chars": 10369,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/SaveHandler.java",
    "chars": 20871,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/UpdateHandler.java",
    "chars": 18189,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/async/AsyncExecutor.java",
    "chars": 1303,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/async/AverageExecutor.java",
    "chars": 1255,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/async/CountExecutor.java",
    "chars": 1241,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/async/FindExecutor.java",
    "chars": 1249,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/async/FindMultiExecutor.java",
    "chars": 1294,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/async/SaveExecutor.java",
    "chars": 1238,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/async/UpdateOrDeleteExecutor.java",
    "chars": 1312,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/callback/AverageCallback.java",
    "chars": 841,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/callback/CountCallback.java",
    "chars": 832,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/callback/FindCallback.java",
    "chars": 829,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/callback/FindMultiCallback.java",
    "chars": 876,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/callback/SaveCallback.java",
    "chars": 838,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/callback/UpdateOrDeleteCallback.java",
    "chars": 861,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/crud/model/AssociationsInfo.java",
    "chars": 5440,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/exceptions/DataSupportException.java",
    "chars": 1571,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/exceptions/DatabaseGenerateException.java",
    "chars": 2291,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/exceptions/GlobalException.java",
    "chars": 1388,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/exceptions/InvalidAttributesException.java",
    "chars": 2053,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/exceptions/LitePalSupportException.java",
    "chars": 3624,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/exceptions/ParseConfigurationFileException.java",
    "chars": 1851,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/extension/FluentQuery.kt",
    "chars": 9869,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/extension/LitePal.kt",
    "chars": 24264,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/model/Table_Schema.java",
    "chars": 1873,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/parser/LitePalAttr.java",
    "chars": 5906,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/parser/LitePalConfig.java",
    "chars": 2780,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/parser/LitePalContentHandler.java",
    "chars": 3580,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/parser/LitePalParser.java",
    "chars": 6994,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/AssociationCreator.java",
    "chars": 18090,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/AssociationUpdater.java",
    "chars": 18658,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/Connector.java",
    "chars": 4109,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/Creator.java",
    "chars": 4249,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/Dropper.java",
    "chars": 4354,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/Generator.java",
    "chars": 7826,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/LitePalOpenHelper.java",
    "chars": 4124,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/Upgrader.java",
    "chars": 15132,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/callback/DatabaseListener.java",
    "chars": 898,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/model/AssociationsModel.java",
    "chars": 4395,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/model/ColumnModel.java",
    "chars": 2823,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/model/GenericModel.java",
    "chars": 2434,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/model/TableModel.java",
    "chars": 3456,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/typechange/BlobOrm.java",
    "chars": 511,
    "preview": "package org.litepal.tablemanager.typechange;\n\n/**\n * This class deals with byte type.\n *\n * @author Tony Green\n * @since"
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/typechange/BooleanOrm.java",
    "chars": 1138,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/typechange/DateOrm.java",
    "chars": 1094,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/typechange/DecimalOrm.java",
    "chars": 1237,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/typechange/NumericOrm.java",
    "chars": 1347,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/typechange/OrmChange.java",
    "chars": 1309,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/tablemanager/typechange/TextOrm.java",
    "chars": 1203,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/util/BaseUtility.java",
    "chars": 8336,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/util/Const.java",
    "chars": 2171,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/util/DBUtility.java",
    "chars": 22796,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/util/LitePalLog.java",
    "chars": 1074,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/util/SharedUtil.java",
    "chars": 3531,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/java/org/litepal/util/cipher/AESCrypt.java",
    "chars": 7624,
    "preview": "/*\n *   Copyright (c) 2014 Scott Alexander-Bown\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n"
  },
  {
    "path": "core/src/main/java/org/litepal/util/cipher/CipherUtil.java",
    "chars": 3307,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "core/src/main/res/values/strings.xml",
    "chars": 70,
    "preview": "<resources>\n    <string name=\"app_name\">LitePal</string>\n</resources>\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 232,
    "preview": "#Fri Jan 29 20:32:21 CST 2021\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradlew",
    "chars": 5080,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2404,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "java/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "java/bintray.gradle",
    "chars": 2169,
    "preview": "group = PROJ_GROUP\nversion = PROJ_VERSION\nproject.archivesBaseName = PROJ_ARTIFACTID_JAVA\n\napply plugin: 'com.jfrog.bint"
  },
  {
    "path": "java/build.gradle",
    "chars": 492,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n    compileSdkVersion 28\n\n    defaultConfig {\n        minSdkVersion 15\n  "
  },
  {
    "path": "java/proguard-rules.pro",
    "chars": 653,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /h"
  },
  {
    "path": "java/src/main/AndroidManifest.xml",
    "chars": 90,
    "preview": "<manifest package=\"org.litepal.java\">\n\n    <application>\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "java/src/main/java/org/litepal/LitePal.java",
    "chars": 45659,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "java/src/main/res/values/strings.xml",
    "chars": 70,
    "preview": "<resources>\n    <string name=\"app_name\">LitePal</string>\n</resources>\n"
  },
  {
    "path": "kotlin/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "kotlin/bintray.gradle",
    "chars": 2163,
    "preview": "group = PROJ_GROUP\nversion = PROJ_VERSION\nproject.archivesBaseName = PROJ_ARTIFACTID_KT\n\napply plugin: 'com.jfrog.bintra"
  },
  {
    "path": "kotlin/build.gradle",
    "chars": 686,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-android-extensions'\napply plugi"
  },
  {
    "path": "kotlin/proguard-rules.pro",
    "chars": 653,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /h"
  },
  {
    "path": "kotlin/src/main/AndroidManifest.xml",
    "chars": 92,
    "preview": "<manifest package=\"org.litepal.kotlin\">\n\n    <application>\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "kotlin/src/main/java/org/litepal/LitePal.kt",
    "chars": 40401,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "kotlin/src/main/java/org/litepal/extension/FluentQuery.kt",
    "chars": 9967,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "kotlin/src/main/java/org/litepal/extension/LitePal.kt",
    "chars": 20274,
    "preview": "/*\n * Copyright (C)  Tony Green, LitePal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "kotlin/src/main/res/values/strings.xml",
    "chars": 70,
    "preview": "<resources>\n    <string name=\"app_name\">LitePal</string>\n</resources>\n"
  },
  {
    "path": "sample/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "sample/build.gradle",
    "chars": 1152,
    "preview": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\n\nandroid {\n    compileSdkVersion 31\n\n    defaultC"
  },
  {
    "path": "sample/proguard-rules.pro",
    "chars": 653,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /h"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/Book.java",
    "chars": 1341,
    "preview": "package com.litepaltest.model;\n\nimport org.litepal.crud.LitePalSupport;\n\nimport java.io.Serializable;\n\npublic class Book"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/Cellphone.java",
    "chars": 1610,
    "preview": "package com.litepaltest.model;\n\nimport org.litepal.annotation.Column;\nimport org.litepal.crud.LitePalSupport;\n\nimport ja"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/Classroom.java",
    "chars": 1517,
    "preview": "package com.litepaltest.model;\n\nimport org.litepal.crud.LitePalSupport;\n\nimport java.util.ArrayList;\nimport java.util.Ha"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/Computer.java",
    "chars": 551,
    "preview": "package com.litepaltest.model;\n\nimport org.litepal.crud.LitePalSupport;\n\npublic class Computer extends LitePalSupport {\n"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/Headset.java",
    "chars": 826,
    "preview": "package com.litepaltest.model;\n\npublic class Headset {\n\n    private int id;\n\n    private String brand;\n\n    private Stri"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/IdCard.java",
    "chars": 1187,
    "preview": "package com.litepaltest.model;\n\nimport org.litepal.crud.LitePalSupport;\n\npublic class IdCard extends LitePalSupport {\n\tp"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/Message.java",
    "chars": 798,
    "preview": "package com.litepaltest.model;\n\nimport org.litepal.annotation.Column;\nimport org.litepal.crud.LitePalSupport;\n\npublic cl"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/Product.java",
    "chars": 710,
    "preview": "package com.litepaltest.model;\n\nimport org.litepal.crud.LitePalSupport;\n\npublic class Product extends LitePalSupport{\n\t\n"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/Student.java",
    "chars": 2530,
    "preview": "package com.litepaltest.model;\n\nimport org.litepal.annotation.Column;\nimport org.litepal.crud.LitePalSupport;\n\nimport ja"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/Teacher.java",
    "chars": 2448,
    "preview": "package com.litepaltest.model;\n\nimport org.litepal.crud.LitePalSupport;\n\nimport java.util.ArrayList;\nimport java.util.Li"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/WeChatMessage.java",
    "chars": 249,
    "preview": "package com.litepaltest.model;\n\npublic class WeChatMessage extends Message {\n\n    private String friend;\n\n    public Str"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/model/WeiboMessage.java",
    "chars": 689,
    "preview": "package com.litepaltest.model;\n\nimport org.litepal.annotation.Column;\n\npublic class WeiboMessage extends Message {\n\n    "
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/LitePalTestCase.java",
    "chars": 10180,
    "preview": "package com.litepaltest.test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport org.litepal.tablemanager.Conne"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/MultiDatabaseTest.java",
    "chars": 4847,
    "preview": "package com.litepaltest.test;\n\nimport android.database.sqlite.SQLiteDatabase;\nimport androidx.test.filters.SmallTest;\n\ni"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/annotation/ColumnTest.java",
    "chars": 2041,
    "preview": "package com.litepaltest.test.annotation;\n\nimport androidx.test.filters.SmallTest;\n\nimport com.litepaltest.model.Cellphon"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/delete/DeleteKotlinTest.kt",
    "chars": 19655,
    "preview": "package com.litepaltest.test.crud.delete\n\nimport android.database.sqlite.SQLiteException\nimport androidx.test.filters.Sm"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/delete/DeleteTest.java",
    "chars": 18212,
    "preview": "package com.litepaltest.test.crud.delete;\n\nimport android.database.Cursor;\n\nimport android.database.sqlite.SQLiteExcepti"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryBasicKotlinTest.kt",
    "chars": 6148,
    "preview": "package com.litepaltest.test.crud.query\n\nimport androidx.test.filters.SmallTest\nimport com.litepaltest.model.Book\nimport"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryBasicTest.java",
    "chars": 6203,
    "preview": "package com.litepaltest.test.crud.query;\n\nimport androidx.test.filters.SmallTest;\n\nimport com.litepaltest.model.Book;\nim"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryBySQLTest.java",
    "chars": 1950,
    "preview": "package com.litepaltest.test.crud.query;\n\nimport android.database.Cursor;\nimport androidx.test.filters.SmallTest;\n\nimpor"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryClusterKotlinTest.kt",
    "chars": 12850,
    "preview": "package com.litepaltest.test.crud.query\n\nimport androidx.test.filters.SmallTest\nimport com.litepaltest.model.Book\nimport"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryClusterTest.java",
    "chars": 15376,
    "preview": "package com.litepaltest.test.crud.query;\n\nimport androidx.test.filters.SmallTest;\n\nimport java.util.List;\n\nimport org.ju"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryDateTest.java",
    "chars": 1707,
    "preview": "package com.litepaltest.test.crud.query;\n\nimport androidx.test.filters.SmallTest;\n\nimport com.litepaltest.model.Student;"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryEagerKotlinTest.kt",
    "chars": 7256,
    "preview": "package com.litepaltest.test.crud.query\n\nimport androidx.test.filters.SmallTest\nimport com.litepaltest.model.Classroom\ni"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryEagerTest.java",
    "chars": 6756,
    "preview": "package com.litepaltest.test.crud.query;\n\nimport androidx.test.filters.SmallTest;\n\nimport com.litepaltest.model.Classroo"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryMathKotlinTest.kt",
    "chars": 4211,
    "preview": "package com.litepaltest.test.crud.query\n\nimport androidx.test.filters.SmallTest\nimport com.litepaltest.model.Student\nimp"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/query/QueryMathTest.java",
    "chars": 3869,
    "preview": "package com.litepaltest.test.crud.query;\n\nimport android.database.Cursor;\nimport androidx.test.filters.SmallTest;\n\nimpor"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/save/Many2ManySaveTest.java",
    "chars": 4934,
    "preview": "package com.litepaltest.test.crud.save;\n\nimport androidx.test.filters.SmallTest;\n\nimport java.util.ArrayList;\nimport jav"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/save/Many2OneBiSaveTest.java",
    "chars": 3201,
    "preview": "package com.litepaltest.test.crud.save;\n\nimport androidx.test.filters.SmallTest;\n\nimport java.util.HashSet;\nimport java."
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/save/Many2OneUniSaveTest.java",
    "chars": 1603,
    "preview": "package com.litepaltest.test.crud.save;\n\nimport androidx.test.filters.SmallTest;\n\nimport com.litepaltest.model.Classroom"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/save/One2OneBiSaveTest.java",
    "chars": 1596,
    "preview": "package com.litepaltest.test.crud.save;\n\nimport androidx.test.filters.SmallTest;\n\nimport com.litepaltest.model.IdCard;\ni"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/save/One2OneUniSaveTest.java",
    "chars": 1171,
    "preview": "package com.litepaltest.test.crud.save;\n\nimport androidx.test.filters.SmallTest;\n\nimport com.litepaltest.model.IdCard;\ni"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/save/SaveAllKotlinTest.kt",
    "chars": 6433,
    "preview": "package com.litepaltest.test.crud.save\n\nimport androidx.test.filters.SmallTest\nimport com.litepaltest.model.*\nimport jun"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/save/SaveAllTest.java",
    "chars": 6476,
    "preview": "package com.litepaltest.test.crud.save;\n\nimport android.database.Cursor;\nimport androidx.test.filters.SmallTest;\n\nimport"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/save/SaveTest.java",
    "chars": 9706,
    "preview": "package com.litepaltest.test.crud.save;\n\nimport androidx.test.filters.SmallTest;\n\nimport com.litepaltest.model.Book;\nimp"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/transaction/TransactionKotlinTest.kt",
    "chars": 7638,
    "preview": "package com.litepaltest.test.crud.transaction\n\nimport android.content.ContentValues\nimport androidx.test.filters.SmallTe"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/transaction/TransactionTest.java",
    "chars": 7294,
    "preview": "package com.litepaltest.test.crud.transaction;\n\nimport android.content.ContentValues;\nimport androidx.test.filters.Small"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/update/UpdateUsingSaveMethodTest.java",
    "chars": 13909,
    "preview": "package com.litepaltest.test.crud.update;\n\nimport androidx.test.filters.SmallTest;\n\nimport java.util.ArrayList;\nimport j"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/update/UpdateUsingUpdateMethodKotlinTest.kt",
    "chars": 14008,
    "preview": "package com.litepaltest.test.crud.update\n\nimport android.content.ContentValues\nimport android.database.sqlite.SQLiteExce"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/crud/update/UpdateUsingUpdateMethodTest.java",
    "chars": 18297,
    "preview": "package com.litepaltest.test.crud.update;\n\nimport java.util.Date;\nimport java.util.List;\n\nimport org.junit.Before;\nimpor"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/util/BaseUtilityTest.java",
    "chars": 1391,
    "preview": "package com.litepaltest.test.util;\n\nimport androidx.test.filters.SmallTest;\n\nimport org.junit.Test;\nimport org.litepal.u"
  },
  {
    "path": "sample/src/androidTest/java/com/litepaltest/test/util/DBUtilityTest.java",
    "chars": 1468,
    "preview": "package com.litepaltest.test.util;\n\nimport android.database.sqlite.SQLiteDatabase;\nimport androidx.test.filters.SmallTes"
  },
  {
    "path": "sample/src/main/AndroidManifest.xml",
    "chars": 4935,
    "preview": "<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licensed under the Apache License, Version 2"
  },
  {
    "path": "sample/src/main/assets/litepal.xml",
    "chars": 3393,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<litepal>\r\n    <!--\r\n\t\tDefine the database name of your application. \r\n\t\tBy defa"
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/MyApplication.java",
    "chars": 258,
    "preview": "package org.litepal.litepalsample;\n\nimport android.app.Application;\n\nimport org.litepal.LitePal;\n\npublic class MyApplica"
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/AggregateActivity.java",
    "chars": 2403,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/AverageSampleActivity.java",
    "chars": 2330,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/CRUDActivity.java",
    "chars": 2217,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/CountSampleActivity.java",
    "chars": 2319,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/DeleteSampleActivity.java",
    "chars": 5180,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/MainActivity.java",
    "chars": 1813,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/ManageTablesActivity.java",
    "chars": 1900,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/MaxSampleActivity.java",
    "chars": 2335,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/MinSampleActivity.java",
    "chars": 2335,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/ModelListActivity.java",
    "chars": 3873,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/ModelStructureActivity.java",
    "chars": 3437,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/QuerySampleActivity.java",
    "chars": 1228,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/SaveSampleActivity.java",
    "chars": 4942,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/SumSampleActivity.java",
    "chars": 2335,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/TableListActivity.java",
    "chars": 2872,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/TableStructureActivity.java",
    "chars": 3990,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/activity/UpdateSampleActivity.java",
    "chars": 5619,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/adapter/DataArrayAdapter.java",
    "chars": 2016,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/adapter/StringArrayAdapter.java",
    "chars": 1515,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/model/Album.java",
    "chars": 2490,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/model/Singer.java",
    "chars": 1492,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/model/Song.java",
    "chars": 1527,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/java/org/litepal/litepalsample/util/Utility.java",
    "chars": 1091,
    "preview": "/*\n * Copyright (C)  Tony Green, Litepal Framework Open Source Project\n *\n * Licensed under the Apache License, Version "
  },
  {
    "path": "sample/src/main/res/layout/aggregate_layout.xml",
    "chars": 1849,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/average_sample_layout.xml",
    "chars": 4507,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/count_sample_layout.xml",
    "chars": 4519,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/crud_layout.xml",
    "chars": 1668,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/delete_sample_layout.xml",
    "chars": 7008,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/main_layout.xml",
    "chars": 1463,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/manage_tables_layout.xml",
    "chars": 1506,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/max_sample_layout.xml",
    "chars": 4507,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/min_sample_layout.xml",
    "chars": 4507,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/model_list_layout.xml",
    "chars": 1041,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/model_structure_item.xml",
    "chars": 1345,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/model_structure_layout.xml",
    "chars": 1943,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/query_sample_layout.xml",
    "chars": 5031,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/save_sample_layout.xml",
    "chars": 7010,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/simple_list_item.xml",
    "chars": 1083,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/sum_sample_layout.xml",
    "chars": 4507,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/table_list_layout.xml",
    "chars": 1247,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/table_structure_item.xml",
    "chars": 2281,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/table_structure_layout.xml",
    "chars": 3339,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/layout/update_sample_layout.xml",
    "chars": 10004,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licen"
  },
  {
    "path": "sample/src/main/res/values/dimens.xml",
    "chars": 211,
    "preview": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal"
  },
  {
    "path": "sample/src/main/res/values/strings.xml",
    "chars": 8226,
    "preview": "<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licensed under the Apache License, Version 2"
  },
  {
    "path": "sample/src/main/res/values/styles.xml",
    "chars": 1206,
    "preview": "<!--\n   Copyright (C) Tony Green, Litepal Framework Open Source Project\n\n   Licensed under the Apache License, Version 2"
  },
  {
    "path": "settings.gradle",
    "chars": 24,
    "preview": "include 'sample', 'core'"
  }
]

// ... and 27 more files (download for full content)

About this extraction

This page contains the full source code of the guolindev/LitePal GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 223 files (1.1 MB), approximately 272.3k tokens, and a symbol index with 1212 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!