[
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.idea\n.gradle\n*~\n*.iml\n**/build\nGenerateJsonRestModel/gen/*\nlocal.properties\n"
  },
  {
    "path": "app/build.generate-database.gradle",
    "content": "def dbSchemaPath = \"src/main/json/database/schema\"\ndef dbClassesPath = \"src/gen/java\"\nandroid.sourceSets.main.java.srcDirs += dbClassesPath\nandroid.sourceSets.main.java.srcDirs += \"src/main/json\"\n\ntask generateDatabaseFiles << {\n    def generatorVersion = \"1.9.2\"\n\n    // download android contentprovider generator\n    if (!file(\"$buildDir/android_contentprovider_generator-${generatorVersion}-bundle.jar\").exists()) {\n        download {\n            src \"https://github.com/BoD/android-contentprovider-generator/releases/download/v${generatorVersion}/android_contentprovider_generator-${generatorVersion}-bundle.jar\"\n            dest buildDir\n        }\n    }\n\n    // delete last generated files\n    // file(dbClassesPath).deleteDir()\n\n    // execute the generator\n    exec {\n        executable \"java\"\n        args = [\"-jar\", \"$buildDir/android_contentprovider_generator-${generatorVersion}-bundle.jar\", \"-i\", dbSchemaPath, \"-o\", dbClassesPath]\n    }\n}"
  },
  {
    "path": "app/build.generate-json-objects.gradle",
    "content": "apply plugin: 'jsonschema2pojo'\n\ndependencies {\n    compile 'com.fasterxml.jackson.core:jackson-databind:2.6.1'\n    compile 'javax.annotation:javax.annotation-api:1.2'\n}\n\njsonSchema2Pojo {\n    source = files(\"${project.projectDir}/src/main/json/network/schema\")\n    targetDirectory = file(\"${project.projectDir}/src/gen/java\")\n    targetPackage = 'com.example.project.network.json'\n    useCommonsLang3 = true\n}"
  },
  {
    "path": "app/build.gradle",
    "content": "buildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        // code generation support for android annotations\n        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'\n\n        // code generation for json string - object mapping\n        classpath 'org.jsonschema2pojo:jsonschema2pojo-gradle-plugin:0.4.14'\n    }\n}\n\nplugins {\n    // provide download task for gradle\n    id \"de.undercouch.download\" version \"1.2\"\n}\n\napply plugin: 'com.android.application'\n\n// code generation support for android annotations\napply plugin: 'android-apt'\n\n// code generation for json object mapping\napply from: 'build.generate-json-objects.gradle'\n\n// code generation database files\napply from: 'build.generate-database.gradle'\n\n// test support for android specific unit tests like database checks\napply from: 'build.robolectric.gradle'\n\n// support code coverage for the unit tests\napply from: 'build.jacoco-test-report.gradle'\n\n// replace target ip for REST calls to use local wiremock\napply from: \"build.wiremock-replace-ip.gradle\"\n\nandroid {\n    compileSdkVersion projectAndroidVersion\n    buildToolsVersion projectAndroidBuildToolsVersion\n\n    defaultConfig {\n        applicationId \"com.example.project\"\n        minSdkVersion projectAndroidMinVersion\n        targetSdkVersion projectAndroidVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled true\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n            buildConfigField \"String\", \"MODULE_PATH\", \"\\\"$projectDir\\\"\".replace('\\\\', '\\\\\\\\')\n            // avoid warning for \"Not all execution paths return a value\"\n            return true\n        }\n        debug {\n            buildConfigField \"String\", \"MODULE_PATH\", \"\\\"$projectDir\\\"\".replace('\\\\', '\\\\\\\\')\n            return true\n        }\n    }\n\n    lintOptions {\n        // GradleDependency Current we can't switch to support v23 tools because of robolectric\n        disable 'GradleDependency'\n    }\n\n    dexOptions {\n        if(isCi) {\n            // CircleCi allow max 4G memory for all processes together and dex does exceed it\n            // with his parallel execution. Shrink the javaMaxHeapSize does it only per dex process\n            // but the combination exceed the max memory and to less value let it run for long time.\n            // javaMaxHeapSize \"1024M\"\n\n            // Speed up build for CI by ignoring extra build steps which should speed up build for developers.\n            // Also reduce memory usage by avoiding multiple (pre) dex processes.\n            incremental false\n            preDexLibraries = false\n        }\n    }\n\n    // instrumentation test module need to access the expected variant, default is only release publish\n    publishNonDefault true\n\n    packagingOptions {\n        exclude 'META-INF/license.txt'\n        exclude 'META-INF/LICENSE.txt'\n        exclude 'META-INF/LICENSE'\n        exclude 'META-INF/notice.txt'\n        exclude 'META-INF/NOTICE.txt'\n        exclude 'META-INF/NOTICE'\n    }\n}\n\napt {\n    arguments {\n        androidManifestFile variant.outputs.collect()[0].processResources.manifestFile\n    }\n}\n\nrepositories {\n    jcenter()\n}\n\ndependencies {\n    // ui design and backward compatibility\n    compile \"com.android.support:appcompat-v7:$projectAndroidSupportToolsVersion\"\n    compile \"com.android.support:design:$projectAndroidSupportToolsVersion\"\n\n    // android annotations support\n    apt \"org.androidannotations:androidannotations:3.3.2\"\n    compile \"org.androidannotations:androidannotations-api:3.3.2\"\n\n    // network support with android annotations\n    compile \"org.springframework.android:spring-android-rest-template:2.0.0.M3\"\n\n    // better time handling with DateTime\n    compile 'net.danlew:android.joda:2.8.2'\n\n    // java language tools like StringUtils\n    compile 'org.apache.commons:commons-lang3:3.4'\n\n    // Use CountIdlingResource class to avoid flaky espresso tests.\n    // Interface is provided by own dependency but ready to use implementation comes with contrib library.\n    // Looks like contrib library was only intended to be used within test scope.\n    // Exclude transitiv dependencies to avoid conflicts with test support libraries.\n    compile('com.android.support.test.espresso:espresso-idling-resource:2.2')\n    compile('com.android.support.test.espresso:espresso-contrib:2.2') { exclude module: \"*\" }\n\n    // force test dependencies to use the same support-annotations version\n    testCompile \"com.android.support:support-annotations:$projectAndroidSupportToolsVersion\"\n\n    // basic unit tests support + mocks + fluent assertions + android assertions\n    testCompile 'junit:junit:4.12'\n    testCompile 'com.squareup.assertj:assertj-android:1.1.0'\n    testCompile 'org.mockito:mockito-all:2.0.2-beta'\n}\n\n"
  },
  {
    "path": "app/build.jacoco-test-report.gradle",
    "content": "apply plugin: \"jacoco\"\n\njacoco {\n    toolVersion = projectJacocoVersion\n}\n\ntask jacocoTestReport(type: JacocoReport /*, dependsOn: ['test'] */ ) {\n    description = \"Generates Jacoco coverage reports: XML and HTML\"\n    group = \"Reporting\"\n//                outputs.upToDateWhen { false }\n\n    // use hidden configuration, for details look into JacocoPlugin.groovy\n    jacocoClasspath = project.configurations['androidJacocoAnt']\n\n    // exclude auto-generated classes and tests\n    def fileFilter = ['**/R.class',\n                      '**/R$*.class',\n                      '**/BuildConfig.*',\n                      '**/Manifest*.*',\n                      '**/*Test*.*',\n                      'android/**/*.*']\n\n    def debugTree = fileTree(dir: \"${project.buildDir}/intermediates/classes/debug\", excludes: fileFilter)\n    def mainSrc = \"${project.projectDir}/src/main/java\"\n\n    sourceDirectories = files([mainSrc])\n    classDirectories = files([debugTree])\n    executionData = fileTree(dir: project.projectDir, includes: ['**/*.exec', '**/*.ec'])\n\n    reports {\n        xml {\n            enabled = true\n            destination = \"${project.buildDir}/reports/jacoco/test/jacocoTestReport.xml\"\n        }\n        csv.enabled false\n        html {\n            enabled = true\n            destination = \"${project.buildDir}/reports/jacoco\"\n        }\n    }\n}"
  },
  {
    "path": "app/build.robolectric.gradle",
    "content": "dependencies {\n    testCompile 'org.robolectric:shadows-support-v4:3.0'\n    testCompile 'org.robolectric:robolectric:3.0'\n}\n\nafterEvaluate {\n\n    def isLintRun = false\n    def isTestRun = false\n\n    gradle.startParameter.taskNames.each {\n        if (it.contains(\"lint\")) {\n            isLintRun = true\n        }\n        if (it.contains(\"test\")) {\n            isTestRun = true\n        }\n    }\n\n    if (isLintRun && isTestRun) {\n        println \"WARNING: tests for release type are disabled for supporting jacoco\"\n        println \"WARNING: run test and lint at same time is not supported\"\n        exit 1\n    }\n\n    if (isTestRun) {\n        tasks.each {\n            if (it.name.contains(\"Release\")) {\n                it.enabled = false\n            }\n        }\n    }\n}"
  },
  {
    "path": "app/build.wiremock-replace-ip.gradle",
    "content": "// may be used to check if wiremock is running\nProcess p1 = Runtime.getRuntime().exec(\"curl \" + obtainCurrentIpAddress() + \":1337/\");\nint returnVal = p1.waitFor();\nboolean reachable = (returnVal == 0);\nprintln \"\\n Wiremock is reachable $reachable\\n\"\n\n// replace the #const_wiremock_ip# with your current ip address for test with wiremock\nandroid.applicationVariants.all { variant ->\n    variant.mergeResources.doLast {\n        def String localIp = obtainCurrentIpAddress()\n        File valuesFile = file(\"${buildDir}/intermediates/res/merged/debug/values/values.xml\")\n        if (valuesFile.exists()) {\n            String content = valuesFile.getText('UTF-8')\n            content = content.replaceAll(\"#const_wiremock_ip#\", localIp)\n            valuesFile.write(content, 'UTF-8')\n        } else {\n            println \"Warning: value.xml not found for replace current ip\"\n        }\n    }\n}\n\ndef String obtainCurrentIpAddress() {\n\n    def wantedInterfaceDisplayName = System.getenv(\"TEST_MOCK_IFACE\");\n\n    if ((wantedInterfaceDisplayName != null) && (!wantedInterfaceDisplayName.isEmpty())) {\n        println \"\\n Interface wanted: \" + wantedInterfaceDisplayName\n    } else {\n        println \"\\n No interface wanted, you can select one by setting the interface name to environment variable TEST_MOCK_IFACE\"\n    }\n\n    def ipAddress = null;\n\n    Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces();\n    while (networkInterfaces.hasMoreElements()) {\n        NetworkInterface networkInterface = (NetworkInterface) networkInterfaces.nextElement();\n\n        Enumeration inetAddresses = networkInterface.getInetAddresses();\n        InetAddress inetAddress = (InetAddress) inetAddresses.nextElement();\n        println \" Found network [${networkInterface.getDisplayName()}] with IP ${inetAddress.getHostAddress()}\"\n\n        if (wantedInterfaceDisplayName?.trim() && !wantedInterfaceDisplayName.equalsIgnoreCase(networkInterface.displayName)) {\n            continue;\n        }\n\n        if (ipAddress == null) {\n            ipAddress = inetAddress.getHostAddress();\n            println \" Selected network ${ipAddress}\"\n        }\n    }\n\n    ipAddress\n}\n\n"
  },
  {
    "path": "app/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <issue id=\"all\">\n        <ignore regexp=\"src/gen/java/*\" />\n    </issue>\n</lint>"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Users/nicokuechler/Library/Android/sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n-dontwarn org.androidannotations.api.rest.*\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/ExampleProvider.java",
    "content": "package com.example.project.database.provider;\n\nimport java.util.Arrays;\n\nimport android.content.ContentValues;\nimport android.content.UriMatcher;\nimport android.database.Cursor;\nimport android.database.sqlite.SQLiteOpenHelper;\nimport android.net.Uri;\nimport android.support.annotation.NonNull;\nimport android.util.Log;\n\nimport com.example.project.BuildConfig;\nimport com.example.project.database.provider.base.BaseContentProvider;\nimport com.example.project.database.provider.address.AddressColumns;\nimport com.example.project.database.provider.contact.ContactColumns;\n\npublic class ExampleProvider extends BaseContentProvider {\n    private static final String TAG = ExampleProvider.class.getSimpleName();\n\n    private static final boolean DEBUG = BuildConfig.DEBUG;\n\n    private static final String TYPE_CURSOR_ITEM = \"vnd.android.cursor.item/\";\n    private static final String TYPE_CURSOR_DIR = \"vnd.android.cursor.dir/\";\n\n    public static final String AUTHORITY = \"com.example.project\";\n    public static final String CONTENT_URI_BASE = \"content://\" + AUTHORITY;\n\n    private static final int URI_TYPE_ADDRESS = 0;\n    private static final int URI_TYPE_ADDRESS_ID = 1;\n\n    private static final int URI_TYPE_CONTACT = 2;\n    private static final int URI_TYPE_CONTACT_ID = 3;\n\n\n\n    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);\n\n    static {\n        URI_MATCHER.addURI(AUTHORITY, AddressColumns.TABLE_NAME, URI_TYPE_ADDRESS);\n        URI_MATCHER.addURI(AUTHORITY, AddressColumns.TABLE_NAME + \"/#\", URI_TYPE_ADDRESS_ID);\n        URI_MATCHER.addURI(AUTHORITY, ContactColumns.TABLE_NAME, URI_TYPE_CONTACT);\n        URI_MATCHER.addURI(AUTHORITY, ContactColumns.TABLE_NAME + \"/#\", URI_TYPE_CONTACT_ID);\n    }\n\n    @Override\n    protected SQLiteOpenHelper createSqLiteOpenHelper() {\n        return ExampleSQLiteOpenHelper.getInstance(getContext());\n    }\n\n    @Override\n    protected boolean hasDebug() {\n        return DEBUG;\n    }\n\n    @Override\n    public String getType(Uri uri) {\n        int match = URI_MATCHER.match(uri);\n        switch (match) {\n            case URI_TYPE_ADDRESS:\n                return TYPE_CURSOR_DIR + AddressColumns.TABLE_NAME;\n            case URI_TYPE_ADDRESS_ID:\n                return TYPE_CURSOR_ITEM + AddressColumns.TABLE_NAME;\n\n            case URI_TYPE_CONTACT:\n                return TYPE_CURSOR_DIR + ContactColumns.TABLE_NAME;\n            case URI_TYPE_CONTACT_ID:\n                return TYPE_CURSOR_ITEM + ContactColumns.TABLE_NAME;\n\n        }\n        return null;\n    }\n\n    @Override\n    public Uri insert(Uri uri, ContentValues values) {\n        if (DEBUG) Log.d(TAG, \"insert uri=\" + uri + \" values=\" + values);\n        return super.insert(uri, values);\n    }\n\n    @Override\n    public int bulkInsert(Uri uri, ContentValues[] values) {\n        if (DEBUG) Log.d(TAG, \"bulkInsert uri=\" + uri + \" values.length=\" + values.length);\n        return super.bulkInsert(uri, values);\n    }\n\n    @Override\n    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {\n        if (DEBUG) Log.d(TAG, \"update uri=\" + uri + \" values=\" + values + \" selection=\" + selection + \" selectionArgs=\" + Arrays.toString(selectionArgs));\n        return super.update(uri, values, selection, selectionArgs);\n    }\n\n    @Override\n    public int delete(Uri uri, String selection, String[] selectionArgs) {\n        if (DEBUG) Log.d(TAG, \"delete uri=\" + uri + \" selection=\" + selection + \" selectionArgs=\" + Arrays.toString(selectionArgs));\n        return super.delete(uri, selection, selectionArgs);\n    }\n\n    @Override\n    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {\n        if (DEBUG)\n            Log.d(TAG, \"query uri=\" + uri + \" selection=\" + selection + \" selectionArgs=\" + Arrays.toString(selectionArgs) + \" sortOrder=\" + sortOrder\n                    + \" groupBy=\" + uri.getQueryParameter(QUERY_GROUP_BY) + \" having=\" + uri.getQueryParameter(QUERY_HAVING) + \" limit=\" + uri.getQueryParameter(QUERY_LIMIT));\n        return super.query(uri, projection, selection, selectionArgs, sortOrder);\n    }\n\n    @Override\n    protected QueryParams getQueryParams(Uri uri, String selection, String[] projection) {\n        QueryParams res = new QueryParams();\n        String id = null;\n        int matchedId = URI_MATCHER.match(uri);\n        switch (matchedId) {\n            case URI_TYPE_ADDRESS:\n            case URI_TYPE_ADDRESS_ID:\n                res.table = AddressColumns.TABLE_NAME;\n                res.idColumn = AddressColumns._ID;\n                res.tablesWithJoins = AddressColumns.TABLE_NAME;\n                if (ContactColumns.hasColumns(projection)) {\n                    res.tablesWithJoins += \" LEFT OUTER JOIN \" + ContactColumns.TABLE_NAME + \" AS \" + AddressColumns.PREFIX_CONTACT + \" ON \" + AddressColumns.TABLE_NAME + \".\" + AddressColumns.CONTACT_ID + \"=\" + AddressColumns.PREFIX_CONTACT + \".\" + ContactColumns._ID;\n                }\n                res.orderBy = AddressColumns.DEFAULT_ORDER;\n                break;\n\n            case URI_TYPE_CONTACT:\n            case URI_TYPE_CONTACT_ID:\n                res.table = ContactColumns.TABLE_NAME;\n                res.idColumn = ContactColumns._ID;\n                res.tablesWithJoins = ContactColumns.TABLE_NAME;\n                res.orderBy = ContactColumns.DEFAULT_ORDER;\n                break;\n\n            default:\n                throw new IllegalArgumentException(\"The uri '\" + uri + \"' is not supported by this ContentProvider\");\n        }\n\n        switch (matchedId) {\n            case URI_TYPE_ADDRESS_ID:\n            case URI_TYPE_CONTACT_ID:\n                id = uri.getLastPathSegment();\n        }\n        if (id != null) {\n            if (selection != null) {\n                res.selection = res.table + \".\" + res.idColumn + \"=\" + id + \" and (\" + selection + \")\";\n            } else {\n                res.selection = res.table + \".\" + res.idColumn + \"=\" + id;\n            }\n        } else {\n            res.selection = selection;\n        }\n        return res;\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/ExampleSQLiteOpenHelper.java",
    "content": "package com.example.project.database.provider;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.database.DatabaseErrorHandler;\nimport android.database.DefaultDatabaseErrorHandler;\nimport android.database.sqlite.SQLiteDatabase;\nimport android.database.sqlite.SQLiteOpenHelper;\nimport android.os.Build;\nimport android.util.Log;\n\nimport com.example.project.BuildConfig;\nimport com.example.project.database.provider.address.AddressColumns;\nimport com.example.project.database.provider.contact.ContactColumns;\n\npublic class ExampleSQLiteOpenHelper extends SQLiteOpenHelper {\n    private static final String TAG = ExampleSQLiteOpenHelper.class.getSimpleName();\n\n    public static final String DATABASE_FILE_NAME = \"example.db\";\n    private static final int DATABASE_VERSION = 1;\n    private static ExampleSQLiteOpenHelper sInstance;\n    private final Context mContext;\n    private final ExampleSQLiteOpenHelperCallbacks mOpenHelperCallbacks;\n\n    // @formatter:off\n    public static final String SQL_CREATE_TABLE_ADDRESS = \"CREATE TABLE IF NOT EXISTS \"\n            + AddressColumns.TABLE_NAME + \" ( \"\n            + AddressColumns._ID + \" INTEGER PRIMARY KEY AUTOINCREMENT, \"\n            + AddressColumns.CONTACT_ID + \" INTEGER NOT NULL, \"\n            + AddressColumns.STREET + \" TEXT, \"\n            + AddressColumns.NUMBER + \" TEXT, \"\n            + AddressColumns.CITY + \" TEXT, \"\n            + AddressColumns.COUNTRY + \" TEXT, \"\n            + AddressColumns.STATE + \" TEXT, \"\n            + AddressColumns.POSTALCODE + \" TEXT \"\n            + \", CONSTRAINT fk_contact_id FOREIGN KEY (\" + AddressColumns.CONTACT_ID + \") REFERENCES contact (_id) ON DELETE CASCADE\"\n            + \" );\";\n\n    public static final String SQL_CREATE_TABLE_CONTACT = \"CREATE TABLE IF NOT EXISTS \"\n            + ContactColumns.TABLE_NAME + \" ( \"\n            + ContactColumns._ID + \" INTEGER PRIMARY KEY AUTOINCREMENT, \"\n            + ContactColumns.UID + \" TEXT, \"\n            + ContactColumns.FIRST_NAME + \" TEXT, \"\n            + ContactColumns.LAST_NAME + \" TEXT, \"\n            + ContactColumns.BIRTHDATE + \" INTEGER \"\n            + \", CONSTRAINT first_or_last_name_must_be_given CHECK((first_name <> '' AND first_name IS NOT NULL) OR (last_name <> '' AND last_name IS NOT NULL)) ON CONFLICT FAIL\"\n            + \" );\";\n\n    // @formatter:on\n\n    public static ExampleSQLiteOpenHelper getInstance(Context context) {\n        // Use the application context, which will ensure that you\n        // don't accidentally leak an Activity's context.\n        // See this article for more information: http://bit.ly/6LRzfx\n        if (sInstance == null) {\n            sInstance = newInstance(context.getApplicationContext());\n        }\n        return sInstance;\n    }\n\n    private static ExampleSQLiteOpenHelper newInstance(Context context) {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {\n            return newInstancePreHoneycomb(context);\n        }\n        return newInstancePostHoneycomb(context);\n    }\n\n\n    /*\n     * Pre Honeycomb.\n     */\n    private static ExampleSQLiteOpenHelper newInstancePreHoneycomb(Context context) {\n        return new ExampleSQLiteOpenHelper(context);\n    }\n\n    private ExampleSQLiteOpenHelper(Context context) {\n        super(context, DATABASE_FILE_NAME, null, DATABASE_VERSION);\n        mContext = context;\n        mOpenHelperCallbacks = new ExampleSQLiteOpenHelperCallbacks();\n    }\n\n\n    /*\n     * Post Honeycomb.\n     */\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    private static ExampleSQLiteOpenHelper newInstancePostHoneycomb(Context context) {\n        return new ExampleSQLiteOpenHelper(context, new DefaultDatabaseErrorHandler());\n    }\n\n    @TargetApi(Build.VERSION_CODES.HONEYCOMB)\n    private ExampleSQLiteOpenHelper(Context context, DatabaseErrorHandler errorHandler) {\n        super(context, DATABASE_FILE_NAME, null, DATABASE_VERSION, errorHandler);\n        mContext = context;\n        mOpenHelperCallbacks = new ExampleSQLiteOpenHelperCallbacks();\n    }\n\n\n    @Override\n    public void onCreate(SQLiteDatabase db) {\n        if (BuildConfig.DEBUG) Log.d(TAG, \"onCreate\");\n        mOpenHelperCallbacks.onPreCreate(mContext, db);\n        db.execSQL(SQL_CREATE_TABLE_ADDRESS);\n        db.execSQL(SQL_CREATE_TABLE_CONTACT);\n        mOpenHelperCallbacks.onPostCreate(mContext, db);\n    }\n\n    @Override\n    public void onOpen(SQLiteDatabase db) {\n        super.onOpen(db);\n        if (!db.isReadOnly()) {\n            setForeignKeyConstraintsEnabled(db);\n        }\n        mOpenHelperCallbacks.onOpen(mContext, db);\n    }\n\n    private void setForeignKeyConstraintsEnabled(SQLiteDatabase db) {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {\n            setForeignKeyConstraintsEnabledPreJellyBean(db);\n        } else {\n            setForeignKeyConstraintsEnabledPostJellyBean(db);\n        }\n    }\n\n    private void setForeignKeyConstraintsEnabledPreJellyBean(SQLiteDatabase db) {\n        db.execSQL(\"PRAGMA foreign_keys=ON;\");\n    }\n\n    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)\n    private void setForeignKeyConstraintsEnabledPostJellyBean(SQLiteDatabase db) {\n        db.setForeignKeyConstraintsEnabled(true);\n    }\n\n    @Override\n    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {\n        mOpenHelperCallbacks.onUpgrade(mContext, db, oldVersion, newVersion);\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/ExampleSQLiteOpenHelperCallbacks.java",
    "content": "package com.example.project.database.provider;\n\nimport android.content.Context;\nimport android.database.sqlite.SQLiteDatabase;\n\nimport android.util.Log;\n\nimport com.example.project.BuildConfig;\n\n/**\n * Implement your custom database creation or upgrade code here.\n *\n * This file will not be overwritten if you re-run the content provider generator.\n */\npublic class ExampleSQLiteOpenHelperCallbacks {\n    private static final String TAG = ExampleSQLiteOpenHelperCallbacks.class.getSimpleName();\n\n    public void onOpen(final Context context, final SQLiteDatabase db) {\n        if (BuildConfig.DEBUG) Log.d(TAG, \"onOpen\");\n        // Insert your db open code here.\n    }\n\n    public void onPreCreate(final Context context, final SQLiteDatabase db) {\n        if (BuildConfig.DEBUG) Log.d(TAG, \"onPreCreate\");\n        // Insert your db creation code here. This is called before your tables are created.\n    }\n\n    public void onPostCreate(final Context context, final SQLiteDatabase db) {\n        if (BuildConfig.DEBUG) Log.d(TAG, \"onPostCreate\");\n        // Insert your db creation code here. This is called after your tables are created.\n    }\n\n    public void onUpgrade(final Context context, final SQLiteDatabase db, final int oldVersion, final int newVersion) {\n        if (BuildConfig.DEBUG) Log.d(TAG, \"Upgrading database from version \" + oldVersion + \" to \" + newVersion);\n        // Insert your upgrading code here.\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/address/AddressColumns.java",
    "content": "package com.example.project.database.provider.address;\n\nimport android.net.Uri;\nimport android.provider.BaseColumns;\n\nimport com.example.project.database.provider.ExampleProvider;\nimport com.example.project.database.provider.address.AddressColumns;\nimport com.example.project.database.provider.contact.ContactColumns;\n\n/**\n * Columns for the {@code address} table.\n */\npublic class AddressColumns implements BaseColumns {\n    public static final String TABLE_NAME = \"address\";\n    public static final Uri CONTENT_URI = Uri.parse(ExampleProvider.CONTENT_URI_BASE + \"/\" + TABLE_NAME);\n\n    /**\n     * Primary key.\n     */\n    public static final String _ID = BaseColumns._ID;\n\n    public static final String CONTACT_ID = \"contact_id\";\n\n    public static final String STREET = \"street\";\n\n    public static final String NUMBER = \"number\";\n\n    public static final String CITY = \"city\";\n\n    public static final String COUNTRY = \"country\";\n\n    public static final String STATE = \"state\";\n\n    public static final String POSTALCODE = \"postalcode\";\n\n\n    public static final String DEFAULT_ORDER = TABLE_NAME + \".\" +_ID;\n\n    // @formatter:off\n    public static final String[] ALL_COLUMNS = new String[] {\n            _ID,\n            CONTACT_ID,\n            STREET,\n            NUMBER,\n            CITY,\n            COUNTRY,\n            STATE,\n            POSTALCODE\n    };\n    // @formatter:on\n\n    public static boolean hasColumns(String[] projection) {\n        if (projection == null) return true;\n        for (String c : projection) {\n            if (c.equals(CONTACT_ID) || c.contains(\".\" + CONTACT_ID)) return true;\n            if (c.equals(STREET) || c.contains(\".\" + STREET)) return true;\n            if (c.equals(NUMBER) || c.contains(\".\" + NUMBER)) return true;\n            if (c.equals(CITY) || c.contains(\".\" + CITY)) return true;\n            if (c.equals(COUNTRY) || c.contains(\".\" + COUNTRY)) return true;\n            if (c.equals(STATE) || c.contains(\".\" + STATE)) return true;\n            if (c.equals(POSTALCODE) || c.contains(\".\" + POSTALCODE)) return true;\n        }\n        return false;\n    }\n\n    public static final String PREFIX_CONTACT = TABLE_NAME + \"__\" + ContactColumns.TABLE_NAME;\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/address/AddressContentValues.java",
    "content": "package com.example.project.database.provider.address;\n\nimport java.util.Date;\n\nimport android.content.ContentResolver;\nimport android.net.Uri;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\n\nimport com.example.project.database.provider.base.AbstractContentValues;\n\n/**\n * Content values wrapper for the {@code address} table.\n */\npublic class AddressContentValues extends AbstractContentValues {\n    @Override\n    public Uri uri() {\n        return AddressColumns.CONTENT_URI;\n    }\n\n    /**\n     * Update row(s) using the values stored by this object and the given selection.\n     *\n     * @param contentResolver The content resolver to use.\n     * @param where The selection to use (can be {@code null}).\n     */\n    public int update(ContentResolver contentResolver, @Nullable AddressSelection where) {\n        return contentResolver.update(uri(), values(), where == null ? null : where.sel(), where == null ? null : where.args());\n    }\n\n    public AddressContentValues putContactId(long value) {\n        mContentValues.put(AddressColumns.CONTACT_ID, value);\n        return this;\n    }\n\n\n    public AddressContentValues putStreet(@Nullable String value) {\n        mContentValues.put(AddressColumns.STREET, value);\n        return this;\n    }\n\n    public AddressContentValues putStreetNull() {\n        mContentValues.putNull(AddressColumns.STREET);\n        return this;\n    }\n\n    public AddressContentValues putNumber(@Nullable String value) {\n        mContentValues.put(AddressColumns.NUMBER, value);\n        return this;\n    }\n\n    public AddressContentValues putNumberNull() {\n        mContentValues.putNull(AddressColumns.NUMBER);\n        return this;\n    }\n\n    public AddressContentValues putCity(@Nullable String value) {\n        mContentValues.put(AddressColumns.CITY, value);\n        return this;\n    }\n\n    public AddressContentValues putCityNull() {\n        mContentValues.putNull(AddressColumns.CITY);\n        return this;\n    }\n\n    public AddressContentValues putCountry(@Nullable String value) {\n        mContentValues.put(AddressColumns.COUNTRY, value);\n        return this;\n    }\n\n    public AddressContentValues putCountryNull() {\n        mContentValues.putNull(AddressColumns.COUNTRY);\n        return this;\n    }\n\n    public AddressContentValues putState(@Nullable String value) {\n        mContentValues.put(AddressColumns.STATE, value);\n        return this;\n    }\n\n    public AddressContentValues putStateNull() {\n        mContentValues.putNull(AddressColumns.STATE);\n        return this;\n    }\n\n    public AddressContentValues putPostalcode(@Nullable String value) {\n        mContentValues.put(AddressColumns.POSTALCODE, value);\n        return this;\n    }\n\n    public AddressContentValues putPostalcodeNull() {\n        mContentValues.putNull(AddressColumns.POSTALCODE);\n        return this;\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/address/AddressCursor.java",
    "content": "package com.example.project.database.provider.address;\n\nimport java.util.Date;\n\nimport android.database.Cursor;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\n\nimport com.example.project.database.provider.base.AbstractCursor;\nimport com.example.project.database.provider.contact.*;\n\n/**\n * Cursor wrapper for the {@code address} table.\n */\npublic class AddressCursor extends AbstractCursor implements AddressModel {\n    public AddressCursor(Cursor cursor) {\n        super(cursor);\n    }\n\n    /**\n     * Primary key.\n     */\n    public long getId() {\n        Long res = getLongOrNull(AddressColumns._ID);\n        if (res == null)\n            throw new NullPointerException(\"The value of '_id' in the database was null, which is not allowed according to the model definition\");\n        return res;\n    }\n\n    /**\n     * Get the {@code contact_id} value.\n     */\n    public long getContactId() {\n        Long res = getLongOrNull(AddressColumns.CONTACT_ID);\n        if (res == null)\n            throw new NullPointerException(\"The value of 'contact_id' in the database was null, which is not allowed according to the model definition\");\n        return res;\n    }\n\n    /**\n     * Get the {@code uid} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getContactUid() {\n        String res = getStringOrNull(ContactColumns.UID);\n        return res;\n    }\n\n    /**\n     * Get the {@code first_name} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getContactFirstName() {\n        String res = getStringOrNull(ContactColumns.FIRST_NAME);\n        return res;\n    }\n\n    /**\n     * Get the {@code last_name} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getContactLastName() {\n        String res = getStringOrNull(ContactColumns.LAST_NAME);\n        return res;\n    }\n\n    /**\n     * Get the {@code birthdate} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public Date getContactBirthdate() {\n        Date res = getDateOrNull(ContactColumns.BIRTHDATE);\n        return res;\n    }\n\n    /**\n     * Get the {@code street} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getStreet() {\n        String res = getStringOrNull(AddressColumns.STREET);\n        return res;\n    }\n\n    /**\n     * Get the {@code number} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getNumber() {\n        String res = getStringOrNull(AddressColumns.NUMBER);\n        return res;\n    }\n\n    /**\n     * Get the {@code city} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getCity() {\n        String res = getStringOrNull(AddressColumns.CITY);\n        return res;\n    }\n\n    /**\n     * Get the {@code country} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getCountry() {\n        String res = getStringOrNull(AddressColumns.COUNTRY);\n        return res;\n    }\n\n    /**\n     * Get the {@code state} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getState() {\n        String res = getStringOrNull(AddressColumns.STATE);\n        return res;\n    }\n\n    /**\n     * Get the {@code postalcode} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getPostalcode() {\n        String res = getStringOrNull(AddressColumns.POSTALCODE);\n        return res;\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/address/AddressModel.java",
    "content": "package com.example.project.database.provider.address;\n\nimport com.example.project.database.provider.base.BaseModel;\n\nimport java.util.Date;\n\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\n\n/**\n * Data model for the {@code address} table.\n */\npublic interface AddressModel extends BaseModel {\n\n    /**\n     * Get the {@code contact_id} value.\n     */\n    long getContactId();\n\n    /**\n     * Get the {@code street} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    String getStreet();\n\n    /**\n     * Get the {@code number} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    String getNumber();\n\n    /**\n     * Get the {@code city} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    String getCity();\n\n    /**\n     * Get the {@code country} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    String getCountry();\n\n    /**\n     * Get the {@code state} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    String getState();\n\n    /**\n     * Get the {@code postalcode} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    String getPostalcode();\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/address/AddressSelection.java",
    "content": "package com.example.project.database.provider.address;\n\nimport java.util.Date;\n\nimport android.content.ContentResolver;\nimport android.database.Cursor;\nimport android.net.Uri;\n\nimport com.example.project.database.provider.base.AbstractSelection;\nimport com.example.project.database.provider.contact.*;\n\n/**\n * Selection for the {@code address} table.\n */\npublic class AddressSelection extends AbstractSelection<AddressSelection> {\n    @Override\n    protected Uri baseUri() {\n        return AddressColumns.CONTENT_URI;\n    }\n\n    /**\n     * Query the given content resolver using this selection.\n     *\n     * @param contentResolver The content resolver to query.\n     * @param projection A list of which columns to return. Passing null will return all columns, which is inefficient.\n     * @param sortOrder How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort\n     *            order, which may be unordered.\n     * @return A {@code AddressCursor} object, which is positioned before the first entry, or null.\n     */\n    public AddressCursor query(ContentResolver contentResolver, String[] projection, String sortOrder) {\n        Cursor cursor = contentResolver.query(uri(), projection, sel(), args(), sortOrder);\n        if (cursor == null) return null;\n        return new AddressCursor(cursor);\n    }\n\n    /**\n     * Equivalent of calling {@code query(contentResolver, projection, null)}.\n     */\n    public AddressCursor query(ContentResolver contentResolver, String[] projection) {\n        return query(contentResolver, projection, null);\n    }\n\n    /**\n     * Equivalent of calling {@code query(contentResolver, projection, null, null)}.\n     */\n    public AddressCursor query(ContentResolver contentResolver) {\n        return query(contentResolver, null, null);\n    }\n\n\n    public AddressSelection id(long... value) {\n        addEquals(\"address.\" + AddressColumns._ID, toObjectArray(value));\n        return this;\n    }\n\n    public AddressSelection contactId(long... value) {\n        addEquals(AddressColumns.CONTACT_ID, toObjectArray(value));\n        return this;\n    }\n\n    public AddressSelection contactIdNot(long... value) {\n        addNotEquals(AddressColumns.CONTACT_ID, toObjectArray(value));\n        return this;\n    }\n\n    public AddressSelection contactIdGt(long value) {\n        addGreaterThan(AddressColumns.CONTACT_ID, value);\n        return this;\n    }\n\n    public AddressSelection contactIdGtEq(long value) {\n        addGreaterThanOrEquals(AddressColumns.CONTACT_ID, value);\n        return this;\n    }\n\n    public AddressSelection contactIdLt(long value) {\n        addLessThan(AddressColumns.CONTACT_ID, value);\n        return this;\n    }\n\n    public AddressSelection contactIdLtEq(long value) {\n        addLessThanOrEquals(AddressColumns.CONTACT_ID, value);\n        return this;\n    }\n\n    public AddressSelection contactUid(String... value) {\n        addEquals(ContactColumns.UID, value);\n        return this;\n    }\n\n    public AddressSelection contactUidNot(String... value) {\n        addNotEquals(ContactColumns.UID, value);\n        return this;\n    }\n\n    public AddressSelection contactUidLike(String... value) {\n        addLike(ContactColumns.UID, value);\n        return this;\n    }\n\n    public AddressSelection contactUidContains(String... value) {\n        addContains(ContactColumns.UID, value);\n        return this;\n    }\n\n    public AddressSelection contactUidStartsWith(String... value) {\n        addStartsWith(ContactColumns.UID, value);\n        return this;\n    }\n\n    public AddressSelection contactUidEndsWith(String... value) {\n        addEndsWith(ContactColumns.UID, value);\n        return this;\n    }\n\n    public AddressSelection contactFirstName(String... value) {\n        addEquals(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactFirstNameNot(String... value) {\n        addNotEquals(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactFirstNameLike(String... value) {\n        addLike(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactFirstNameContains(String... value) {\n        addContains(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactFirstNameStartsWith(String... value) {\n        addStartsWith(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactFirstNameEndsWith(String... value) {\n        addEndsWith(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactLastName(String... value) {\n        addEquals(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactLastNameNot(String... value) {\n        addNotEquals(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactLastNameLike(String... value) {\n        addLike(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactLastNameContains(String... value) {\n        addContains(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactLastNameStartsWith(String... value) {\n        addStartsWith(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactLastNameEndsWith(String... value) {\n        addEndsWith(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public AddressSelection contactBirthdate(Date... value) {\n        addEquals(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public AddressSelection contactBirthdateNot(Date... value) {\n        addNotEquals(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public AddressSelection contactBirthdate(Long... value) {\n        addEquals(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public AddressSelection contactBirthdateAfter(Date value) {\n        addGreaterThan(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public AddressSelection contactBirthdateAfterEq(Date value) {\n        addGreaterThanOrEquals(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public AddressSelection contactBirthdateBefore(Date value) {\n        addLessThan(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public AddressSelection contactBirthdateBeforeEq(Date value) {\n        addLessThanOrEquals(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public AddressSelection street(String... value) {\n        addEquals(AddressColumns.STREET, value);\n        return this;\n    }\n\n    public AddressSelection streetNot(String... value) {\n        addNotEquals(AddressColumns.STREET, value);\n        return this;\n    }\n\n    public AddressSelection streetLike(String... value) {\n        addLike(AddressColumns.STREET, value);\n        return this;\n    }\n\n    public AddressSelection streetContains(String... value) {\n        addContains(AddressColumns.STREET, value);\n        return this;\n    }\n\n    public AddressSelection streetStartsWith(String... value) {\n        addStartsWith(AddressColumns.STREET, value);\n        return this;\n    }\n\n    public AddressSelection streetEndsWith(String... value) {\n        addEndsWith(AddressColumns.STREET, value);\n        return this;\n    }\n\n    public AddressSelection number(String... value) {\n        addEquals(AddressColumns.NUMBER, value);\n        return this;\n    }\n\n    public AddressSelection numberNot(String... value) {\n        addNotEquals(AddressColumns.NUMBER, value);\n        return this;\n    }\n\n    public AddressSelection numberLike(String... value) {\n        addLike(AddressColumns.NUMBER, value);\n        return this;\n    }\n\n    public AddressSelection numberContains(String... value) {\n        addContains(AddressColumns.NUMBER, value);\n        return this;\n    }\n\n    public AddressSelection numberStartsWith(String... value) {\n        addStartsWith(AddressColumns.NUMBER, value);\n        return this;\n    }\n\n    public AddressSelection numberEndsWith(String... value) {\n        addEndsWith(AddressColumns.NUMBER, value);\n        return this;\n    }\n\n    public AddressSelection city(String... value) {\n        addEquals(AddressColumns.CITY, value);\n        return this;\n    }\n\n    public AddressSelection cityNot(String... value) {\n        addNotEquals(AddressColumns.CITY, value);\n        return this;\n    }\n\n    public AddressSelection cityLike(String... value) {\n        addLike(AddressColumns.CITY, value);\n        return this;\n    }\n\n    public AddressSelection cityContains(String... value) {\n        addContains(AddressColumns.CITY, value);\n        return this;\n    }\n\n    public AddressSelection cityStartsWith(String... value) {\n        addStartsWith(AddressColumns.CITY, value);\n        return this;\n    }\n\n    public AddressSelection cityEndsWith(String... value) {\n        addEndsWith(AddressColumns.CITY, value);\n        return this;\n    }\n\n    public AddressSelection country(String... value) {\n        addEquals(AddressColumns.COUNTRY, value);\n        return this;\n    }\n\n    public AddressSelection countryNot(String... value) {\n        addNotEquals(AddressColumns.COUNTRY, value);\n        return this;\n    }\n\n    public AddressSelection countryLike(String... value) {\n        addLike(AddressColumns.COUNTRY, value);\n        return this;\n    }\n\n    public AddressSelection countryContains(String... value) {\n        addContains(AddressColumns.COUNTRY, value);\n        return this;\n    }\n\n    public AddressSelection countryStartsWith(String... value) {\n        addStartsWith(AddressColumns.COUNTRY, value);\n        return this;\n    }\n\n    public AddressSelection countryEndsWith(String... value) {\n        addEndsWith(AddressColumns.COUNTRY, value);\n        return this;\n    }\n\n    public AddressSelection state(String... value) {\n        addEquals(AddressColumns.STATE, value);\n        return this;\n    }\n\n    public AddressSelection stateNot(String... value) {\n        addNotEquals(AddressColumns.STATE, value);\n        return this;\n    }\n\n    public AddressSelection stateLike(String... value) {\n        addLike(AddressColumns.STATE, value);\n        return this;\n    }\n\n    public AddressSelection stateContains(String... value) {\n        addContains(AddressColumns.STATE, value);\n        return this;\n    }\n\n    public AddressSelection stateStartsWith(String... value) {\n        addStartsWith(AddressColumns.STATE, value);\n        return this;\n    }\n\n    public AddressSelection stateEndsWith(String... value) {\n        addEndsWith(AddressColumns.STATE, value);\n        return this;\n    }\n\n    public AddressSelection postalcode(String... value) {\n        addEquals(AddressColumns.POSTALCODE, value);\n        return this;\n    }\n\n    public AddressSelection postalcodeNot(String... value) {\n        addNotEquals(AddressColumns.POSTALCODE, value);\n        return this;\n    }\n\n    public AddressSelection postalcodeLike(String... value) {\n        addLike(AddressColumns.POSTALCODE, value);\n        return this;\n    }\n\n    public AddressSelection postalcodeContains(String... value) {\n        addContains(AddressColumns.POSTALCODE, value);\n        return this;\n    }\n\n    public AddressSelection postalcodeStartsWith(String... value) {\n        addStartsWith(AddressColumns.POSTALCODE, value);\n        return this;\n    }\n\n    public AddressSelection postalcodeEndsWith(String... value) {\n        addEndsWith(AddressColumns.POSTALCODE, value);\n        return this;\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/base/AbstractContentValues.java",
    "content": "package com.example.project.database.provider.base;\n\nimport android.content.ContentResolver;\nimport android.content.ContentValues;\nimport android.net.Uri;\n\npublic abstract class AbstractContentValues {\n    protected final ContentValues mContentValues = new ContentValues();\n\n    /**\n     * Returns the {@code uri} argument to pass to the {@code ContentResolver} methods.\n     */\n    public abstract Uri uri();\n\n    /**\n     * Returns the {@code ContentValues} wrapped by this object.\n     */\n    public ContentValues values() {\n        return mContentValues;\n    }\n\n    /**\n     * Inserts a row into a table using the values stored by this object.\n     * \n     * @param contentResolver The content resolver to use.\n     */\n    public Uri insert(ContentResolver contentResolver) {\n        return contentResolver.insert(uri(), values());\n    }\n}"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/base/AbstractCursor.java",
    "content": "package com.example.project.database.provider.base;\n\nimport java.util.Date;\nimport java.util.HashMap;\n\nimport android.database.Cursor;\nimport android.database.CursorWrapper;\nimport android.provider.BaseColumns;\n\npublic abstract class AbstractCursor extends CursorWrapper {\n    private final HashMap<String, Integer> mColumnIndexes;\n\n    public AbstractCursor(Cursor cursor) {\n        super(cursor);\n        mColumnIndexes = new HashMap<String, Integer>(cursor.getColumnCount() * 4 / 3, .75f);\n    }\n\n    public abstract long getId();\n\n    protected int getCachedColumnIndexOrThrow(String colName) {\n        Integer index = mColumnIndexes.get(colName);\n        if (index == null) {\n            index = getColumnIndexOrThrow(colName);\n            mColumnIndexes.put(colName, index);\n        }\n        return index;\n    }\n\n    public String getStringOrNull(String colName) {\n        int index = getCachedColumnIndexOrThrow(colName);\n        if (isNull(index)) return null;\n        return getString(index);\n    }\n\n    public Integer getIntegerOrNull(String colName) {\n        int index = getCachedColumnIndexOrThrow(colName);\n        if (isNull(index)) return null;\n        return getInt(index);\n    }\n\n    public Long getLongOrNull(String colName) {\n        int index = getCachedColumnIndexOrThrow(colName);\n        if (isNull(index)) return null;\n        return getLong(index);\n    }\n\n    public Float getFloatOrNull(String colName) {\n        int index = getCachedColumnIndexOrThrow(colName);\n        if (isNull(index)) return null;\n        return getFloat(index);\n    }\n\n    public Double getDoubleOrNull(String colName) {\n        int index = getCachedColumnIndexOrThrow(colName);\n        if (isNull(index)) return null;\n        return getDouble(index);\n    }\n\n    public Boolean getBooleanOrNull(String colName) {\n        int index = getCachedColumnIndexOrThrow(colName);\n        if (isNull(index)) return null;\n        return getInt(index) != 0;\n    }\n\n    public Date getDateOrNull(String colName) {\n        int index = getCachedColumnIndexOrThrow(colName);\n        if (isNull(index)) return null;\n        return new Date(getLong(index));\n    }\n\n    public byte[] getBlobOrNull(String colName) {\n        int index = getCachedColumnIndexOrThrow(colName);\n        if (isNull(index)) return null;\n        return getBlob(index);\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/base/AbstractSelection.java",
    "content": "package com.example.project.database.provider.base;\n\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\n\nimport android.content.ContentResolver;\nimport android.net.Uri;\n\npublic abstract class AbstractSelection<T extends AbstractSelection<?>> {\n    private static final String EQ = \"=?\";\n    private static final String PAREN_OPEN = \"(\";\n    private static final String PAREN_CLOSE = \")\";\n    private static final String AND = \" AND \";\n    private static final String OR = \" OR \";\n    private static final String IS_NULL = \" IS NULL\";\n    private static final String IS_NOT_NULL = \" IS NOT NULL\";\n    private static final String IN = \" IN (\";\n    private static final String NOT_IN = \" NOT IN (\";\n    private static final String COMMA = \",\";\n    private static final String GT = \">?\";\n    private static final String LT = \"<?\";\n    private static final String GT_EQ = \">=?\";\n    private static final String LT_EQ = \"<=?\";\n    private static final String NOT_EQ = \"<>?\";\n    private static final String LIKE = \" LIKE ?\";\n    private static final String CONTAINS = \" LIKE '%' || ? || '%'\";\n    private static final String STARTS = \" LIKE ? || '%'\";\n    private static final String ENDS = \" LIKE '%' || ?\";\n\n    private final StringBuilder mSelection = new StringBuilder();\n    private final List<String> mSelectionArgs = new ArrayList<String>(5);\n\n    Boolean mNotify;\n    String mGroupBy;\n    String mHaving;\n    Integer mLimit;\n\n    protected void addEquals(String column, Object[] value) {\n        mSelection.append(column);\n\n        if (value == null) {\n            // Single null value\n            mSelection.append(IS_NULL);\n        } else if (value.length > 1) {\n            // Multiple values ('in' clause)\n            mSelection.append(IN);\n            for (int i = 0; i < value.length; i++) {\n                mSelection.append(\"?\");\n                if (i < value.length - 1) {\n                    mSelection.append(COMMA);\n                }\n                mSelectionArgs.add(valueOf(value[i]));\n            }\n            mSelection.append(PAREN_CLOSE);\n        } else {\n            // Single value\n            if (value[0] == null) {\n                // Single null value\n                mSelection.append(IS_NULL);\n            } else {\n                // Single not null value\n                mSelection.append(EQ);\n                mSelectionArgs.add(valueOf(value[0]));\n            }\n        }\n    }\n\n    protected void addNotEquals(String column, Object[] value) {\n        mSelection.append(column);\n\n        if (value == null) {\n            // Single null value\n            mSelection.append(IS_NOT_NULL);\n        } else if (value.length > 1) {\n            // Multiple values ('in' clause)\n            mSelection.append(NOT_IN);\n            for (int i = 0; i < value.length; i++) {\n                mSelection.append(\"?\");\n                if (i < value.length - 1) {\n                    mSelection.append(COMMA);\n                }\n                mSelectionArgs.add(valueOf(value[i]));\n            }\n            mSelection.append(PAREN_CLOSE);\n        } else {\n            // Single value\n            if (value[0] == null) {\n                // Single null value\n                mSelection.append(IS_NOT_NULL);\n            } else {\n                // Single not null value\n                mSelection.append(NOT_EQ);\n                mSelectionArgs.add(valueOf(value[0]));\n            }\n        }\n    }\n\n    protected void addLike(String column, String[] values) {\n        mSelection.append(PAREN_OPEN);\n        for (int i = 0; i < values.length; i++) {\n            mSelection.append(column);\n            mSelection.append(LIKE);\n            mSelectionArgs.add(values[i]);\n            if (i < values.length - 1) {\n                mSelection.append(OR);\n            }\n        }\n        mSelection.append(PAREN_CLOSE);\n    }\n\n    protected void addContains(String column, String[] values) {\n        mSelection.append(PAREN_OPEN);\n        for (int i = 0; i < values.length; i++) {\n            mSelection.append(column);\n            mSelection.append(CONTAINS);\n            mSelectionArgs.add(values[i]);\n            if (i < values.length - 1) {\n                mSelection.append(OR);\n            }\n        }\n        mSelection.append(PAREN_CLOSE);\n    }\n\n    protected void addStartsWith(String column, String[] values) {\n        mSelection.append(PAREN_OPEN);\n        for (int i = 0; i < values.length; i++) {\n            mSelection.append(column);\n            mSelection.append(STARTS);\n            mSelectionArgs.add(values[i]);\n            if (i < values.length - 1) {\n                mSelection.append(OR);\n            }\n        }\n        mSelection.append(PAREN_CLOSE);\n    }\n\n    protected void addEndsWith(String column, String[] values) {\n        mSelection.append(PAREN_OPEN);\n        for (int i = 0; i < values.length; i++) {\n            mSelection.append(column);\n            mSelection.append(ENDS);\n            mSelectionArgs.add(values[i]);\n            if (i < values.length - 1) {\n                mSelection.append(OR);\n            }\n        }\n        mSelection.append(PAREN_CLOSE);\n    }\n\n    protected void addGreaterThan(String column, Object value) {\n        mSelection.append(column);\n        mSelection.append(GT);\n        mSelectionArgs.add(valueOf(value));\n    }\n\n    protected void addGreaterThanOrEquals(String column, Object value) {\n        mSelection.append(column);\n        mSelection.append(GT_EQ);\n        mSelectionArgs.add(valueOf(value));\n    }\n\n    protected void addLessThan(String column, Object value) {\n        mSelection.append(column);\n        mSelection.append(LT);\n        mSelectionArgs.add(valueOf(value));\n    }\n\n    protected void addLessThanOrEquals(String column, Object value) {\n        mSelection.append(column);\n        mSelection.append(LT_EQ);\n        mSelectionArgs.add(valueOf(value));\n    }\n\n    public void addRaw(String raw, Object... args) {\n        mSelection.append(\" \");\n        mSelection.append(raw);\n        mSelection.append(\" \");\n        for (Object arg : args) {\n            mSelectionArgs.add(valueOf(arg));\n        }\n    }\n\n    private String valueOf(Object obj) {\n        if (obj instanceof Date) {\n            return String.valueOf(((Date) obj).getTime());\n        } else if (obj instanceof Boolean) {\n            return (Boolean) obj ? \"1\" : \"0\";\n        } else if (obj instanceof Enum) {\n            return String.valueOf(((Enum<?>) obj).ordinal());\n        }\n        return String.valueOf(obj);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public T openParen() {\n        mSelection.append(PAREN_OPEN);\n        return (T) this;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public T closeParen() {\n        mSelection.append(PAREN_CLOSE);\n        return (T) this;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public T and() {\n        mSelection.append(AND);\n        return (T) this;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public T or() {\n        mSelection.append(OR);\n        return (T) this;\n    }\n\n\n    protected Object[] toObjectArray(int... array) {\n        Object[] res = new Object[array.length];\n        for (int i = 0; i < array.length; i++) {\n            res[i] = array[i];\n        }\n        return res;\n    }\n\n    protected Object[] toObjectArray(long... array) {\n        Object[] res = new Object[array.length];\n        for (int i = 0; i < array.length; i++) {\n            res[i] = array[i];\n        }\n        return res;\n    }\n\n    protected Object[] toObjectArray(float... array) {\n        Object[] res = new Object[array.length];\n        for (int i = 0; i < array.length; i++) {\n            res[i] = array[i];\n        }\n        return res;\n    }\n\n    protected Object[] toObjectArray(double... array) {\n        Object[] res = new Object[array.length];\n        for (int i = 0; i < array.length; i++) {\n            res[i] = array[i];\n        }\n        return res;\n    }\n\n    protected Object[] toObjectArray(Boolean value) {\n        return new Object[] { value };\n    }\n\n\n    /**\n     * Returns the selection produced by this object.\n     */\n    public String sel() {\n        return mSelection.toString();\n    }\n\n    /**\n     * Returns the selection arguments produced by this object.\n     */\n    public String[] args() {\n        int size = mSelectionArgs.size();\n        if (size == 0) return null;\n        return mSelectionArgs.toArray(new String[size]);\n    }\n\n\n    /**\n     * Returns the {@code uri} argument to pass to the {@code ContentResolver} methods.\n     */\n    public Uri uri() {\n        Uri uri = baseUri();\n        if (mNotify != null) uri = BaseContentProvider.notify(uri, mNotify);\n        if (mGroupBy != null) uri = BaseContentProvider.groupBy(uri, mGroupBy);\n        if (mHaving != null) uri = BaseContentProvider.having(uri, mHaving);\n        if (mLimit != null) uri = BaseContentProvider.limit(uri, String.valueOf(mLimit));\n        return uri;\n    }\n\n    protected abstract Uri baseUri();\n\n    /**\n     * Deletes row(s) specified by this selection.\n     *\n     * @param contentResolver The content resolver to use.\n     * @return The number of rows deleted.\n     */\n    public int delete(ContentResolver contentResolver) {\n        return contentResolver.delete(uri(), sel(), args());\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public T notify(boolean notify) {\n        mNotify = notify;\n        return (T) this;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public T groupBy(String groupBy) {\n        mGroupBy = groupBy;\n        return (T) this;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public T having(String having) {\n        mHaving = having;\n        return (T) this;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public T limit(int limit) {\n        mLimit = limit;\n        return (T) this;\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/base/BaseContentProvider.java",
    "content": "package com.example.project.database.provider.base;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.HashSet;\n\nimport android.content.ContentProvider;\nimport android.content.ContentProviderOperation;\nimport android.content.ContentProviderResult;\nimport android.content.ContentValues;\nimport android.content.OperationApplicationException;\nimport android.database.Cursor;\nimport android.database.sqlite.SQLiteDatabase;\nimport android.database.sqlite.SQLiteOpenHelper;\nimport android.net.Uri;\nimport android.provider.BaseColumns;\nimport android.support.annotation.NonNull;\nimport android.util.Log;\n\npublic abstract class BaseContentProvider extends ContentProvider {\n    public static final String QUERY_NOTIFY = \"QUERY_NOTIFY\";\n    public static final String QUERY_GROUP_BY = \"QUERY_GROUP_BY\";\n    public static final String QUERY_HAVING = \"QUERY_HAVING\";\n    public static final String QUERY_LIMIT = \"QUERY_LIMIT\";\n\n    public static class QueryParams {\n        public String table;\n        public String tablesWithJoins;\n        public String idColumn;\n        public String selection;\n        public String orderBy;\n    }\n\n\n    protected abstract QueryParams getQueryParams(Uri uri, String selection, String[] projection);\n    protected abstract boolean hasDebug();\n\n    protected abstract SQLiteOpenHelper createSqLiteOpenHelper();\n\n    protected SQLiteOpenHelper mSqLiteOpenHelper;\n\n    @Override\n    public final boolean onCreate() {\n        if (hasDebug()) {\n            // Enable logging of SQL statements as they are executed.\n            try {\n                Class<?> sqliteDebugClass = Class.forName(\"android.database.sqlite.SQLiteDebug\");\n                Field field = sqliteDebugClass.getDeclaredField(\"DEBUG_SQL_STATEMENTS\");\n                field.setAccessible(true);\n                field.set(null, true);\n\n                // Uncomment the following block if you also want logging of execution time (more verbose)\n                // field = sqliteDebugClass.getDeclaredField(\"DEBUG_SQL_TIME\");\n                // field.setAccessible(true);\n                // field.set(null, true);\n            } catch (Throwable t) {\n                if (hasDebug()) Log.w(getClass().getSimpleName(), \"Could not enable SQLiteDebug logging\", t);\n            }\n        }\n        mSqLiteOpenHelper = createSqLiteOpenHelper();\n        return false;\n    }\n\n\n    @Override\n    public Uri insert(Uri uri, ContentValues values) {\n        String table = uri.getLastPathSegment();\n        long rowId = mSqLiteOpenHelper.getWritableDatabase().insertOrThrow(table, null, values);\n        if (rowId == -1) return null;\n        String notify;\n        if (((notify = uri.getQueryParameter(QUERY_NOTIFY)) == null || \"true\".equals(notify))) {\n            getContext().getContentResolver().notifyChange(uri, null);\n        }\n        return uri.buildUpon().appendEncodedPath(String.valueOf(rowId)).build();\n    }\n\n    @Override\n    public int bulkInsert(Uri uri, ContentValues[] values) {\n        String table = uri.getLastPathSegment();\n        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();\n        int res = 0;\n        db.beginTransaction();\n        try {\n            for (ContentValues v : values) {\n                long id = db.insert(table, null, v);\n                db.yieldIfContendedSafely();\n                if (id != -1) {\n                    res++;\n                }\n            }\n            db.setTransactionSuccessful();\n        } finally {\n            db.endTransaction();\n        }\n        String notify;\n        if (res != 0 && ((notify = uri.getQueryParameter(QUERY_NOTIFY)) == null || \"true\".equals(notify))) {\n            getContext().getContentResolver().notifyChange(uri, null);\n        }\n\n        return res;\n    }\n\n    @Override\n    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {\n        QueryParams queryParams = getQueryParams(uri, selection, null);\n        int res = mSqLiteOpenHelper.getWritableDatabase().update(queryParams.table, values, queryParams.selection, selectionArgs);\n        String notify;\n        if (res != 0 && ((notify = uri.getQueryParameter(QUERY_NOTIFY)) == null || \"true\".equals(notify))) {\n            getContext().getContentResolver().notifyChange(uri, null);\n        }\n        return res;\n    }\n\n    @Override\n    public int delete(Uri uri, String selection, String[] selectionArgs) {\n        QueryParams queryParams = getQueryParams(uri, selection, null);\n        int res = mSqLiteOpenHelper.getWritableDatabase().delete(queryParams.table, queryParams.selection, selectionArgs);\n        String notify;\n        if (res != 0 && ((notify = uri.getQueryParameter(QUERY_NOTIFY)) == null || \"true\".equals(notify))) {\n            getContext().getContentResolver().notifyChange(uri, null);\n        }\n        return res;\n    }\n\n    @Override\n    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {\n        String groupBy = uri.getQueryParameter(QUERY_GROUP_BY);\n        String having = uri.getQueryParameter(QUERY_HAVING);\n        String limit = uri.getQueryParameter(QUERY_LIMIT);\n        QueryParams queryParams = getQueryParams(uri, selection, projection);\n        projection = ensureIdIsFullyQualified(projection, queryParams.table, queryParams.idColumn);\n        Cursor res = mSqLiteOpenHelper.getReadableDatabase().query(queryParams.tablesWithJoins, projection, queryParams.selection, selectionArgs, groupBy,\n                having, sortOrder == null ? queryParams.orderBy : sortOrder, limit);\n        res.setNotificationUri(getContext().getContentResolver(), uri);\n        return res;\n    }\n\n    private String[] ensureIdIsFullyQualified(String[] projection, String tableName, String idColumn) {\n        if (projection == null) return null;\n        String[] res = new String[projection.length];\n        for (int i = 0; i < projection.length; i++) {\n            if (projection[i].equals(idColumn)) {\n                res[i] = tableName + \".\" + idColumn + \" AS \" + BaseColumns._ID;\n            } else {\n                res[i] = projection[i];\n            }\n        }\n        return res;\n    }\n\n    @Override\n    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {\n        HashSet<Uri> urisToNotify = new HashSet<Uri>(operations.size());\n        for (ContentProviderOperation operation : operations) {\n            urisToNotify.add(operation.getUri());\n        }\n        SQLiteDatabase db = mSqLiteOpenHelper.getWritableDatabase();\n        db.beginTransaction();\n        try {\n            int numOperations = operations.size();\n            ContentProviderResult[] results = new ContentProviderResult[numOperations];\n            int i = 0;\n            for (ContentProviderOperation operation : operations) {\n                results[i] = operation.apply(this, results, i);\n                if (operation.isYieldAllowed()) {\n                    db.yieldIfContendedSafely();\n                }\n                i++;\n            }\n            db.setTransactionSuccessful();\n            for (Uri uri : urisToNotify) {\n                getContext().getContentResolver().notifyChange(uri, null);\n            }\n            return results;\n        } finally {\n            db.endTransaction();\n        }\n    }\n\n\n    public static Uri notify(Uri uri, boolean notify) {\n        return uri.buildUpon().appendQueryParameter(QUERY_NOTIFY, String.valueOf(notify)).build();\n    }\n\n    public static Uri groupBy(Uri uri, String groupBy) {\n        return uri.buildUpon().appendQueryParameter(QUERY_GROUP_BY, groupBy).build();\n    }\n\n    public static Uri having(Uri uri, String having) {\n        return uri.buildUpon().appendQueryParameter(QUERY_HAVING, having).build();\n    }\n\n    public static Uri limit(Uri uri, String limit) {\n        return uri.buildUpon().appendQueryParameter(QUERY_LIMIT, limit).build();\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/base/BaseModel.java",
    "content": "package com.example.project.database.provider.base;\n\npublic interface BaseModel {\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/contact/ContactColumns.java",
    "content": "package com.example.project.database.provider.contact;\n\nimport android.net.Uri;\nimport android.provider.BaseColumns;\n\nimport com.example.project.database.provider.ExampleProvider;\nimport com.example.project.database.provider.address.AddressColumns;\nimport com.example.project.database.provider.contact.ContactColumns;\n\n/**\n * Columns for the {@code contact} table.\n */\npublic class ContactColumns implements BaseColumns {\n    public static final String TABLE_NAME = \"contact\";\n    public static final Uri CONTENT_URI = Uri.parse(ExampleProvider.CONTENT_URI_BASE + \"/\" + TABLE_NAME);\n\n    /**\n     * Primary key.\n     */\n    public static final String _ID = BaseColumns._ID;\n\n    public static final String UID = \"uid\";\n\n    public static final String FIRST_NAME = \"first_name\";\n\n    public static final String LAST_NAME = \"last_name\";\n\n    public static final String BIRTHDATE = \"birthdate\";\n\n\n    public static final String DEFAULT_ORDER = TABLE_NAME + \".\" +_ID;\n\n    // @formatter:off\n    public static final String[] ALL_COLUMNS = new String[] {\n            _ID,\n            UID,\n            FIRST_NAME,\n            LAST_NAME,\n            BIRTHDATE\n    };\n    // @formatter:on\n\n    public static boolean hasColumns(String[] projection) {\n        if (projection == null) return true;\n        for (String c : projection) {\n            if (c.equals(UID) || c.contains(\".\" + UID)) return true;\n            if (c.equals(FIRST_NAME) || c.contains(\".\" + FIRST_NAME)) return true;\n            if (c.equals(LAST_NAME) || c.contains(\".\" + LAST_NAME)) return true;\n            if (c.equals(BIRTHDATE) || c.contains(\".\" + BIRTHDATE)) return true;\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/contact/ContactContentValues.java",
    "content": "package com.example.project.database.provider.contact;\n\nimport java.util.Date;\n\nimport android.content.ContentResolver;\nimport android.net.Uri;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\n\nimport com.example.project.database.provider.base.AbstractContentValues;\n\n/**\n * Content values wrapper for the {@code contact} table.\n */\npublic class ContactContentValues extends AbstractContentValues {\n    @Override\n    public Uri uri() {\n        return ContactColumns.CONTENT_URI;\n    }\n\n    /**\n     * Update row(s) using the values stored by this object and the given selection.\n     *\n     * @param contentResolver The content resolver to use.\n     * @param where The selection to use (can be {@code null}).\n     */\n    public int update(ContentResolver contentResolver, @Nullable ContactSelection where) {\n        return contentResolver.update(uri(), values(), where == null ? null : where.sel(), where == null ? null : where.args());\n    }\n\n    public ContactContentValues putUid(@Nullable String value) {\n        mContentValues.put(ContactColumns.UID, value);\n        return this;\n    }\n\n    public ContactContentValues putUidNull() {\n        mContentValues.putNull(ContactColumns.UID);\n        return this;\n    }\n\n    public ContactContentValues putFirstName(@Nullable String value) {\n        mContentValues.put(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public ContactContentValues putFirstNameNull() {\n        mContentValues.putNull(ContactColumns.FIRST_NAME);\n        return this;\n    }\n\n    public ContactContentValues putLastName(@Nullable String value) {\n        mContentValues.put(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public ContactContentValues putLastNameNull() {\n        mContentValues.putNull(ContactColumns.LAST_NAME);\n        return this;\n    }\n\n    public ContactContentValues putBirthdate(@Nullable Date value) {\n        mContentValues.put(ContactColumns.BIRTHDATE, value == null ? null : value.getTime());\n        return this;\n    }\n\n    public ContactContentValues putBirthdateNull() {\n        mContentValues.putNull(ContactColumns.BIRTHDATE);\n        return this;\n    }\n\n    public ContactContentValues putBirthdate(@Nullable Long value) {\n        mContentValues.put(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/contact/ContactCursor.java",
    "content": "package com.example.project.database.provider.contact;\n\nimport java.util.Date;\n\nimport android.database.Cursor;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\n\nimport com.example.project.database.provider.base.AbstractCursor;\n\n/**\n * Cursor wrapper for the {@code contact} table.\n */\npublic class ContactCursor extends AbstractCursor implements ContactModel {\n    public ContactCursor(Cursor cursor) {\n        super(cursor);\n    }\n\n    /**\n     * Primary key.\n     */\n    public long getId() {\n        Long res = getLongOrNull(ContactColumns._ID);\n        if (res == null)\n            throw new NullPointerException(\"The value of '_id' in the database was null, which is not allowed according to the model definition\");\n        return res;\n    }\n\n    /**\n     * Get the {@code uid} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getUid() {\n        String res = getStringOrNull(ContactColumns.UID);\n        return res;\n    }\n\n    /**\n     * Get the {@code first_name} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getFirstName() {\n        String res = getStringOrNull(ContactColumns.FIRST_NAME);\n        return res;\n    }\n\n    /**\n     * Get the {@code last_name} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public String getLastName() {\n        String res = getStringOrNull(ContactColumns.LAST_NAME);\n        return res;\n    }\n\n    /**\n     * Get the {@code birthdate} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    public Date getBirthdate() {\n        Date res = getDateOrNull(ContactColumns.BIRTHDATE);\n        return res;\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/contact/ContactModel.java",
    "content": "package com.example.project.database.provider.contact;\n\nimport com.example.project.database.provider.base.BaseModel;\n\nimport java.util.Date;\n\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\n\n/**\n * Data model for the {@code contact} table.\n */\npublic interface ContactModel extends BaseModel {\n\n    /**\n     * Get the {@code uid} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    String getUid();\n\n    /**\n     * Get the {@code first_name} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    String getFirstName();\n\n    /**\n     * Get the {@code last_name} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    String getLastName();\n\n    /**\n     * Get the {@code birthdate} value.\n     * Can be {@code null}.\n     */\n    @Nullable\n    Date getBirthdate();\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/database/provider/contact/ContactSelection.java",
    "content": "package com.example.project.database.provider.contact;\n\nimport java.util.Date;\n\nimport android.content.ContentResolver;\nimport android.database.Cursor;\nimport android.net.Uri;\n\nimport com.example.project.database.provider.base.AbstractSelection;\n\n/**\n * Selection for the {@code contact} table.\n */\npublic class ContactSelection extends AbstractSelection<ContactSelection> {\n    @Override\n    protected Uri baseUri() {\n        return ContactColumns.CONTENT_URI;\n    }\n\n    /**\n     * Query the given content resolver using this selection.\n     *\n     * @param contentResolver The content resolver to query.\n     * @param projection A list of which columns to return. Passing null will return all columns, which is inefficient.\n     * @param sortOrder How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort\n     *            order, which may be unordered.\n     * @return A {@code ContactCursor} object, which is positioned before the first entry, or null.\n     */\n    public ContactCursor query(ContentResolver contentResolver, String[] projection, String sortOrder) {\n        Cursor cursor = contentResolver.query(uri(), projection, sel(), args(), sortOrder);\n        if (cursor == null) return null;\n        return new ContactCursor(cursor);\n    }\n\n    /**\n     * Equivalent of calling {@code query(contentResolver, projection, null)}.\n     */\n    public ContactCursor query(ContentResolver contentResolver, String[] projection) {\n        return query(contentResolver, projection, null);\n    }\n\n    /**\n     * Equivalent of calling {@code query(contentResolver, projection, null, null)}.\n     */\n    public ContactCursor query(ContentResolver contentResolver) {\n        return query(contentResolver, null, null);\n    }\n\n\n    public ContactSelection id(long... value) {\n        addEquals(\"contact.\" + ContactColumns._ID, toObjectArray(value));\n        return this;\n    }\n\n    public ContactSelection uid(String... value) {\n        addEquals(ContactColumns.UID, value);\n        return this;\n    }\n\n    public ContactSelection uidNot(String... value) {\n        addNotEquals(ContactColumns.UID, value);\n        return this;\n    }\n\n    public ContactSelection uidLike(String... value) {\n        addLike(ContactColumns.UID, value);\n        return this;\n    }\n\n    public ContactSelection uidContains(String... value) {\n        addContains(ContactColumns.UID, value);\n        return this;\n    }\n\n    public ContactSelection uidStartsWith(String... value) {\n        addStartsWith(ContactColumns.UID, value);\n        return this;\n    }\n\n    public ContactSelection uidEndsWith(String... value) {\n        addEndsWith(ContactColumns.UID, value);\n        return this;\n    }\n\n    public ContactSelection firstName(String... value) {\n        addEquals(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection firstNameNot(String... value) {\n        addNotEquals(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection firstNameLike(String... value) {\n        addLike(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection firstNameContains(String... value) {\n        addContains(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection firstNameStartsWith(String... value) {\n        addStartsWith(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection firstNameEndsWith(String... value) {\n        addEndsWith(ContactColumns.FIRST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection lastName(String... value) {\n        addEquals(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection lastNameNot(String... value) {\n        addNotEquals(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection lastNameLike(String... value) {\n        addLike(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection lastNameContains(String... value) {\n        addContains(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection lastNameStartsWith(String... value) {\n        addStartsWith(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection lastNameEndsWith(String... value) {\n        addEndsWith(ContactColumns.LAST_NAME, value);\n        return this;\n    }\n\n    public ContactSelection birthdate(Date... value) {\n        addEquals(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public ContactSelection birthdateNot(Date... value) {\n        addNotEquals(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public ContactSelection birthdate(Long... value) {\n        addEquals(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public ContactSelection birthdateAfter(Date value) {\n        addGreaterThan(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public ContactSelection birthdateAfterEq(Date value) {\n        addGreaterThanOrEquals(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public ContactSelection birthdateBefore(Date value) {\n        addLessThan(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n\n    public ContactSelection birthdateBeforeEq(Date value) {\n        addLessThanOrEquals(ContactColumns.BIRTHDATE, value);\n        return this;\n    }\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/network/json/ContactJson.java",
    "content": "\npackage com.example.project.network.json;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport javax.annotation.Generated;\nimport com.fasterxml.jackson.annotation.JsonAnyGetter;\nimport com.fasterxml.jackson.annotation.JsonAnySetter;\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport com.fasterxml.jackson.annotation.JsonPropertyOrder;\nimport org.apache.commons.lang3.builder.EqualsBuilder;\nimport org.apache.commons.lang3.builder.HashCodeBuilder;\nimport org.apache.commons.lang3.builder.ToStringBuilder;\n\n\n/**\n * Simple single contact.\n * \n */\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@Generated(\"org.jsonschema2pojo\")\n@JsonPropertyOrder({\n    \"id\",\n    \"firstName\",\n    \"lastName\",\n    \"birthDate\"\n})\npublic class ContactJson {\n\n    @JsonProperty(\"id\")\n    private String id;\n    @JsonProperty(\"firstName\")\n    private String firstName;\n    @JsonProperty(\"lastName\")\n    private String lastName;\n    @JsonProperty(\"birthDate\")\n    private String birthDate;\n    @JsonIgnore\n    private Map<String, Object> additionalProperties = new HashMap<String, Object>();\n\n    /**\n     * \n     * @return\n     *     The id\n     */\n    @JsonProperty(\"id\")\n    public String getId() {\n        return id;\n    }\n\n    /**\n     * \n     * @param id\n     *     The id\n     */\n    @JsonProperty(\"id\")\n    public void setId(String id) {\n        this.id = id;\n    }\n\n    /**\n     * \n     * @return\n     *     The firstName\n     */\n    @JsonProperty(\"firstName\")\n    public String getFirstName() {\n        return firstName;\n    }\n\n    /**\n     * \n     * @param firstName\n     *     The firstName\n     */\n    @JsonProperty(\"firstName\")\n    public void setFirstName(String firstName) {\n        this.firstName = firstName;\n    }\n\n    /**\n     * \n     * @return\n     *     The lastName\n     */\n    @JsonProperty(\"lastName\")\n    public String getLastName() {\n        return lastName;\n    }\n\n    /**\n     * \n     * @param lastName\n     *     The lastName\n     */\n    @JsonProperty(\"lastName\")\n    public void setLastName(String lastName) {\n        this.lastName = lastName;\n    }\n\n    /**\n     * \n     * @return\n     *     The birthDate\n     */\n    @JsonProperty(\"birthDate\")\n    public String getBirthDate() {\n        return birthDate;\n    }\n\n    /**\n     * \n     * @param birthDate\n     *     The birthDate\n     */\n    @JsonProperty(\"birthDate\")\n    public void setBirthDate(String birthDate) {\n        this.birthDate = birthDate;\n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this);\n    }\n\n    @JsonAnyGetter\n    public Map<String, Object> getAdditionalProperties() {\n        return this.additionalProperties;\n    }\n\n    @JsonAnySetter\n    public void setAdditionalProperty(String name, Object value) {\n        this.additionalProperties.put(name, value);\n    }\n\n    @Override\n    public int hashCode() {\n        return new HashCodeBuilder().append(id).append(firstName).append(lastName).append(birthDate).append(additionalProperties).toHashCode();\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if (other == this) {\n            return true;\n        }\n        if ((other instanceof ContactJson) == false) {\n            return false;\n        }\n        ContactJson rhs = ((ContactJson) other);\n        return new EqualsBuilder().append(id, rhs.id).append(firstName, rhs.firstName).append(lastName, rhs.lastName).append(birthDate, rhs.birthDate).append(additionalProperties, rhs.additionalProperties).isEquals();\n    }\n\n}\n"
  },
  {
    "path": "app/src/gen/java/com/example/project/network/json/ContactListJson.java",
    "content": "\npackage com.example.project.network.json;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport javax.annotation.Generated;\nimport com.fasterxml.jackson.annotation.JsonAnyGetter;\nimport com.fasterxml.jackson.annotation.JsonAnySetter;\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport com.fasterxml.jackson.annotation.JsonPropertyOrder;\nimport org.apache.commons.lang3.builder.EqualsBuilder;\nimport org.apache.commons.lang3.builder.HashCodeBuilder;\nimport org.apache.commons.lang3.builder.ToStringBuilder;\n\n\n/**\n * Collection of contacts.\n * \n */\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@Generated(\"org.jsonschema2pojo\")\n@JsonPropertyOrder({\n    \"contacts\"\n})\npublic class ContactListJson {\n\n    @JsonProperty(\"contacts\")\n    private List<ContactJson> contacts = new ArrayList<ContactJson>();\n    @JsonIgnore\n    private Map<String, Object> additionalProperties = new HashMap<String, Object>();\n\n    /**\n     * \n     * @return\n     *     The contacts\n     */\n    @JsonProperty(\"contacts\")\n    public List<ContactJson> getContacts() {\n        return contacts;\n    }\n\n    /**\n     * \n     * @param contacts\n     *     The contacts\n     */\n    @JsonProperty(\"contacts\")\n    public void setContacts(List<ContactJson> contacts) {\n        this.contacts = contacts;\n    }\n\n    @Override\n    public String toString() {\n        return ToStringBuilder.reflectionToString(this);\n    }\n\n    @JsonAnyGetter\n    public Map<String, Object> getAdditionalProperties() {\n        return this.additionalProperties;\n    }\n\n    @JsonAnySetter\n    public void setAdditionalProperty(String name, Object value) {\n        this.additionalProperties.put(name, value);\n    }\n\n    @Override\n    public int hashCode() {\n        return new HashCodeBuilder().append(contacts).append(additionalProperties).toHashCode();\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if (other == this) {\n            return true;\n        }\n        if ((other instanceof ContactListJson) == false) {\n            return false;\n        }\n        ContactListJson rhs = ((ContactListJson) other);\n        return new EqualsBuilder().append(contacts, rhs.contacts).append(additionalProperties, rhs.additionalProperties).isEquals();\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.example.project\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".views.start.StartActivity_\"\n            android:finishOnTaskLaunch=\"true\"\n            android:label=\"@string/app_name\"\n            android:noHistory=\"true\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity\n            android:name=\".views.contact_list.ContactListActivity_\"\n            android:label=\"List\" />\n        <activity\n            android:name=\".views.contact_details.DetailActivity_\"\n            android:label=\"Details\">\n            <meta-data\n                android:name=\"android.support.PARENT_ACTIVITY\"\n                android:value=\".views.contact_list.ContactListActivity_\" />\n        </activity>\n        <activity\n            android:name=\".views.contact_edit.EditActivity_\"\n            android:label=\"Create or Update\">\n            <meta-data\n                android:name=\"android.support.PARENT_ACTIVITY\"\n                android:value=\".views.contact_list.ContactListActivity_\" />\n        </activity>\n\n        <provider\n            android:name=\"com.example.project.database.ExampleDbProvider_\"\n            android:authorities=\"com.example.project\"\n            android:exported=\"false\" />\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "app/src/main/java/com/example/project/business/contact/CreateContactFunction.java",
    "content": "package com.example.project.business.contact;\n\nimport com.example.project.database.provider.contact.ContactContentValues;\nimport com.example.project.database.contact.ContactDb;\n\nimport org.androidannotations.annotations.Bean;\nimport org.androidannotations.annotations.EBean;\n\nimport java.util.Date;\n\n@EBean\npublic class CreateContactFunction {\n\n    @Bean\n    ContactDb contactDb;\n\n    public void apply(String firstName, String lastName, Date birthDate) {\n        apply(\"\", firstName, lastName, birthDate);\n    }\n\n    public void apply(String uid, String firstName, String lastName, Date birthDate) {\n        ContactContentValues contentValues = contactDb.insertDataContainer();\n        contentValues.putUid(uid);\n        contentValues.putFirstName(firstName);\n        contentValues.putLastName(lastName);\n        contentValues.putBirthdate(birthDate);\n        contactDb.insert(contentValues);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/business/contact/DeleteContactFunction.java",
    "content": "package com.example.project.business.contact;\n\nimport org.androidannotations.annotations.EBean;\n\n@EBean\npublic class DeleteContactFunction {\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/business/contact/QueryContactFunction.java",
    "content": "package com.example.project.business.contact;\n\nimport android.support.annotation.Nullable;\n\nimport com.example.project.database.contact.ContactDb;\nimport com.example.project.database.provider.contact.ContactCursor;\nimport com.example.project.database.provider.contact.ContactModel;\n\nimport org.androidannotations.annotations.Bean;\nimport org.androidannotations.annotations.EBean;\n\nimport java.util.Date;\n\n@EBean\npublic class QueryContactFunction {\n\n    @Bean\n    ContactDb contactDb;\n\n    public ContactModel apply(long contactId) {\n        ContactCursor contactCursor = contactDb.queryById(contactId);\n        return createContactModel(contactCursor);\n    }\n\n    public ContactModel applyByUid(String contactUid) {\n        ContactCursor contactCursor = contactDb.queryByUid(contactUid);\n        return createContactModel(contactCursor);\n    }\n\n    private ContactModel createContactModel(ContactCursor contactCursor) {\n\n        if(!contactCursor.moveToFirst()) {\n            return null;\n        }\n\n        final String contactUid = contactCursor.getUid();\n        final String firstName = contactCursor.getFirstName();\n        final String lastName = contactCursor.getLastName();\n        final Date birthDate = contactCursor.getBirthdate();\n        contactCursor.close();\n\n        return new ContactModel() {\n            @Nullable\n            @Override\n            public String getUid() {\n                return contactUid;\n            }\n\n            @Nullable\n            @Override\n            public String getFirstName() {\n                return firstName;\n            }\n\n            @Nullable\n            @Override\n            public String getLastName() {\n                return lastName;\n            }\n\n            @Nullable\n            @Override\n            public Date getBirthdate() {\n                return birthDate;\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/business/contact/QueryContactListFunction.java",
    "content": "package com.example.project.business.contact;\n\nimport com.example.project.database.provider.contact.ContactCursor;\nimport com.example.project.database.contact.ContactDb;\n\nimport org.androidannotations.annotations.Bean;\nimport org.androidannotations.annotations.EBean;\n\n@EBean\npublic class QueryContactListFunction {\n\n    @Bean\n    ContactDb contactDb;\n\n    public ContactCursor apply() {\n        return contactDb.queryAll();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/business/contact/UpdateContactFunction.java",
    "content": "package com.example.project.business.contact;\n\nimport org.androidannotations.annotations.EBean;\n\n@EBean\npublic class UpdateContactFunction {\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/business/contact_sync/SyncContactsFunction.java",
    "content": "package com.example.project.business.contact_sync;\n\nimport com.example.project.business.contact.CreateContactFunction;\nimport com.example.project.business.contact.QueryContactFunction;\nimport com.example.project.database.provider.contact.ContactModel;\nimport com.example.project.network.contact.ContactRestClient;\nimport com.example.project.network.json.ContactJson;\nimport com.example.project.network.json.ContactListJson;\n\nimport org.androidannotations.annotations.Bean;\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.rest.RestService;\nimport org.apache.http.conn.HttpHostConnectException;\nimport org.joda.time.DateTime;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.client.HttpClientErrorException;\nimport org.springframework.web.client.HttpServerErrorException;\nimport org.springframework.web.client.ResourceAccessException;\nimport org.springframework.web.client.RestClientException;\n\nimport java.util.Date;\n\n@EBean\npublic class SyncContactsFunction {\n\n    @RestService\n    ContactRestClient contactRestClient;\n\n    @Bean\n    QueryContactFunction queryContactFunction;\n\n    @Bean\n    CreateContactFunction createContactFunction;\n\n    public static class Result {\n        public boolean successful;\n\n        public String errorReason;\n\n        public Result(String errorReason) {\n            this.errorReason = errorReason;\n            successful = false;\n        }\n\n        public Result() {\n            successful = true;\n        }\n    }\n\n    public Result apply() {\n        try {\n            ResponseEntity<ContactListJson> contacts = contactRestClient.getContacts();\n            if (contacts.getStatusCode() == HttpStatus.OK) {\n                syncContactsToDatabase(contacts.getBody());\n                return new Result();\n            } else {\n                return new Result(\"unknown\");\n            }\n        } catch (RestClientException e) {\n            return new Result(e.getMessage());\n        }\n    }\n\n    private void syncContactsToDatabase(ContactListJson contacts) {\n        for (ContactJson contact : contacts.getContacts()) {\n            ContactModel contactModel = queryContactFunction.applyByUid(contact.getId());\n            if (contactModel == null) {\n                String uid = contact.getId();\n                String firstName = contact.getFirstName();\n                String lastName = contact.getLastName();\n                Date birthDate = DateTime.parse(contact.getBirthDate()).toDate();\n                createContactFunction.apply(uid, firstName, lastName, birthDate);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/database/ExampleDbProvider.java",
    "content": "package com.example.project.database;\n\nimport com.example.project.database.provider.ExampleProvider;\n\nimport org.androidannotations.annotations.EProvider;\n\n@EProvider\npublic class ExampleDbProvider extends ExampleProvider {\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/database/ExampleSQLiteOpenHelperCallbacks.java",
    "content": "package com.example.project.database;\n\nimport android.content.Context;\nimport android.database.sqlite.SQLiteDatabase;\n\nimport android.util.Log;\n\nimport com.example.project.BuildConfig;\n\n/**\n * Implement your custom database creation or upgrade code here.\n */\npublic class ExampleSQLiteOpenHelperCallbacks {\n    private static final String TAG = ExampleSQLiteOpenHelperCallbacks.class.getSimpleName();\n\n    public void onOpen(final Context context, final SQLiteDatabase db) {\n        if (BuildConfig.DEBUG) Log.d(TAG, \"onOpen\");\n        // Insert your db open code here.\n    }\n\n    public void onPreCreate(final Context context, final SQLiteDatabase db) {\n        if (BuildConfig.DEBUG) Log.d(TAG, \"onPreCreate\");\n        // Insert your db creation code here. This is called before your tables are created.\n    }\n\n    public void onPostCreate(final Context context, final SQLiteDatabase db) {\n        if (BuildConfig.DEBUG) Log.d(TAG, \"onPostCreate\");\n        // Insert your db creation code here. This is called after your tables are created.\n    }\n\n    public void onUpgrade(final Context context, final SQLiteDatabase db, final int oldVersion, final int newVersion) {\n        if (BuildConfig.DEBUG) Log.d(TAG, \"Upgrading database from version \" + oldVersion + \" to \" + newVersion);\n        // Insert your upgrading code here.\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/database/contact/AddressDb.java",
    "content": "package com.example.project.database.contact;\n\nimport android.content.ContentUris;\nimport android.content.Context;\nimport android.net.Uri;\n\nimport com.example.project.database.provider.address.AddressColumns;\nimport com.example.project.database.provider.address.AddressContentValues;\nimport com.example.project.database.provider.address.AddressCursor;\nimport com.example.project.database.provider.address.AddressSelection;\nimport com.example.project.database.provider.contact.ContactColumns;\n\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.RootContext;\nimport org.apache.commons.lang3.ArrayUtils;\n\n@EBean\npublic class AddressDb {\n\n    @RootContext\n    Context context;\n\n    // one join example\n    private final String[] ALL_JOINED_COLUMNS = (String[]) ArrayUtils.addAll(AddressColumns.ALL_COLUMNS, ContactColumns.ALL_COLUMNS);\n\n    public long insert(AddressContentValues contentValues) {\n        Uri contentUri = contentValues.insert(context.getContentResolver());\n        return ContentUris.parseId(contentUri);\n    }\n\n    public AddressCursor queryById(long addressId) {\n        return new AddressSelection().id(addressId).query(context.getContentResolver(), ALL_JOINED_COLUMNS);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/database/contact/ContactDb.java",
    "content": "package com.example.project.database.contact;\n\nimport android.content.ContentUris;\nimport android.content.Context;\nimport android.net.Uri;\n\nimport com.example.project.database.provider.contact.ContactContentValues;\nimport com.example.project.database.provider.contact.ContactCursor;\nimport com.example.project.database.provider.contact.ContactSelection;\n\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.RootContext;\n\n@EBean\npublic class ContactDb {\n\n    @RootContext\n    Context context;\n\n    public ContactContentValues insertDataContainer() {\n        return new ContactContentValues();\n    }\n\n    public long insert(ContactContentValues contentValues) {\n        Uri contentUri = contentValues.insert(context.getContentResolver());\n        return ContentUris.parseId(contentUri);\n    }\n\n    public ContactCursor queryAll() {\n        return new ContactSelection().query(context.getContentResolver());\n    }\n\n    public ContactCursor queryById(long contactId) {\n        return new ContactSelection().id(contactId).query(context.getContentResolver());\n    }\n\n    public ContactCursor queryByUid(String contactUid) {\n        return new ContactSelection().uid(contactUid).query(context.getContentResolver());\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/network/contact/ContactRestClient.java",
    "content": "package com.example.project.network.contact;\n\nimport com.example.project.network.json.ContactListJson;\n\nimport org.androidannotations.annotations.rest.Delete;\nimport org.androidannotations.annotations.rest.Get;\nimport org.androidannotations.annotations.rest.Post;\nimport org.androidannotations.annotations.rest.Put;\nimport org.androidannotations.annotations.rest.Rest;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;\nimport org.springframework.web.client.RestClientException;\n\n@Rest(converters = {MappingJackson2HttpMessageConverter.class}, interceptors = {RootUrlInterceptor.class})\npublic interface ContactRestClient {\n\n    @Get(\"/contacts\")\n    ResponseEntity<ContactListJson> getContacts() throws RestClientException;\n\n    @Post(\"/contacts\")\n    ResponseEntity<Void> createContact() throws RestClientException;\n\n    @Put(\"/contacts/{id}\")\n    ResponseEntity<Void> updateContact(String id) throws RestClientException;\n\n    @Delete(\"/contacts/{id}\")\n    ResponseEntity<Void> deleteContact(String id) throws RestClientException;\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/network/contact/RootUrlInterceptor.java",
    "content": "package com.example.project.network.contact;\n\nimport android.content.Context;\n\nimport com.example.project.R;\n\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.RootContext;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.http.HttpRequest;\nimport org.springframework.http.client.ClientHttpRequestExecution;\nimport org.springframework.http.client.ClientHttpRequestInterceptor;\nimport org.springframework.http.client.ClientHttpResponse;\n\nimport java.io.IOException;\nimport java.net.URI;\n\n@EBean\npublic class RootUrlInterceptor implements ClientHttpRequestInterceptor {\n\n    @RootContext\n    Context context;\n\n    @Override\n    public ClientHttpResponse intercept(final HttpRequest originalRequest, byte[] body, ClientHttpRequestExecution execution) throws IOException {\n        final URI uriWithRootUrl = prependRootUrl(originalRequest.getURI());\n        return executeWithInterceptedUri(originalRequest, body, execution, uriWithRootUrl);\n    }\n\n    private ClientHttpResponse executeWithInterceptedUri(final HttpRequest originalRequest, byte[] body, ClientHttpRequestExecution execution, final URI uriWithRootUrl) throws IOException {\n        HttpRequest interceptedRequest = new HttpRequest() {\n            @Override\n            public HttpHeaders getHeaders() {\n                return originalRequest.getHeaders();\n            }\n\n            @Override\n            public HttpMethod getMethod() {\n                return originalRequest.getMethod();\n            }\n\n            @Override\n            public URI getURI() {\n                return uriWithRootUrl;\n            }\n        };\n        return execution.execute(interceptedRequest, body);\n    }\n\n    private URI prependRootUrl(URI originalUri) {\n        return URI.create(\"http://\" + context.getResources().getString(R.string.const_wiremock_ip) + \":1337\" + originalUri.toString());\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/common/AppIdlingResources.java",
    "content": "package com.example.project.views.common;\n\nimport android.support.test.espresso.contrib.CountingIdlingResource;\n\nimport org.androidannotations.annotations.EBean;\n\n@EBean(scope = EBean.Scope.Singleton)\npublic class AppIdlingResources {\n\n    CountingIdlingResource idlingResource = new CountingIdlingResource(\"AppIdlingResources\");\n\n    public CountingIdlingResource getIdlingResource() {\n        return idlingResource;\n    }\n\n    public void increment() {\n        idlingResource.increment();\n    }\n\n    public void decrement() {\n        idlingResource.decrement();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/common/cursorloader/CursorAdapterWithCursorLoader.java",
    "content": "package com.example.project.views.common.cursorloader;\n\nimport android.database.Cursor;\nimport android.os.Bundle;\nimport android.support.v4.app.LoaderManager;\nimport android.support.v4.content.CursorLoader;\nimport android.support.v4.content.Loader;\nimport android.support.v4.widget.CursorAdapter;\n\nimport com.example.project.database.provider.contact.ContactCursor;\nimport com.example.project.views.common.mvp.BaseActivityPresenter;\n\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.RootContext;\n\n/**\n * Simplify handling for basic cursor loader + cursor adapter combination.\n * <p/>\n * Always listen for changes on the data source and reload new content.\n * <p/>\n * Implement this class, add the Adapter to a AdapterView and call {@link #start()}.\n */\n@EBean\npublic abstract class CursorAdapterWithCursorLoader {\n\n    /**\n     * Expecting the adapter where the swap cursor method will be called.\n     */\n    public abstract CursorAdapter getCursorAdapter();\n\n    /**\n     * Provide an unique identifier for the cursor loader.\n     */\n    public abstract int getLoaderId();\n\n    /**\n     * Will be called on background when the cursor should loaded\n     */\n    public abstract Cursor loadCursor();\n\n    @RootContext\n    protected BaseActivityPresenter context;\n\n    public void start() {\n        LoaderManager loaderManager = context.getSupportLoaderManager();\n\n        Loader<ContactCursor> loader = loaderManager.getLoader(getLoaderId());\n        if (loader != null && !loader.isReset()) {\n            loaderManager.restartLoader(getLoaderId(), null, createLoaderCallback());\n        } else {\n            loaderManager.initLoader(getLoaderId(), null, createLoaderCallback());\n        }\n    }\n\n    private LoaderManager.LoaderCallbacks<Cursor> createLoaderCallback() {\n        return new LoaderManager.LoaderCallbacks<Cursor>() {\n            @Override\n            public Loader<Cursor> onCreateLoader(int id, Bundle args) {\n                return new CursorLoader(context) {\n\n                    private ForceLoadContentObserver observer = new ForceLoadContentObserver();\n\n                    @Override\n                    public Cursor loadInBackground() {\n                        Cursor cursor = loadCursor();\n                        cursor.registerContentObserver(observer);\n                        return cursor;\n                    }\n                };\n            }\n\n            @Override\n            public void onLoadFinished(Loader<Cursor> loader, final Cursor data) {\n                getCursorAdapter().swapCursor(data);\n            }\n\n            @Override\n            public void onLoaderReset(Loader<Cursor> loader) {\n                getCursorAdapter().swapCursor(null);\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/common/mvp/BaseActivityPresenter.java",
    "content": "package com.example.project.views.common.mvp;\n\nimport android.support.v7.app.AppCompatActivity;\n\nimport org.androidannotations.annotations.AfterViews;\nimport org.androidannotations.annotations.EActivity;\n\n/**\n * Base presenter for activities.\n */\n@EActivity\npublic abstract class BaseActivityPresenter extends AppCompatActivity implements BasePresenter {\n\n    /** Guard to avoid multiple calls to {@link BasePresenter#onViewCreated} */\n    private boolean firstTimeOnAfterViews = true;\n\n    // wrapper for the life cycles\n\n    @AfterViews\n    protected void baseOnAfterViews() {\n        if (firstTimeOnAfterViews) {\n            firstTimeOnAfterViews = false;\n            onViewCreated();\n        }\n    }\n\n    @Override\n    public void onResume() {\n        super.onResume();\n        onViewResume();\n    }\n\n    @Override\n    public void onPause() {\n        super.onPause();\n        onViewPause();\n    }\n\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n        onViewDestroy();\n    }\n\n    // don't force child classes to implement the life cycle methods\n\n    @Override\n    public void onViewCreated() {\n    }\n\n    @Override\n    public void onViewResume() {\n    }\n\n    @Override\n    public void onViewPause() {\n    }\n\n    @Override\n    public void onViewDestroy() {\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/common/mvp/BaseFragmentPresenter.java",
    "content": "package com.example.project.views.common.mvp;\n\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\n\nimport org.androidannotations.annotations.EFragment;\n\n/**\n * Base presenter for fragments.\n */\n@EFragment\npublic abstract class BaseFragmentPresenter extends Fragment implements BasePresenter {\n\n    // wrapper for the life cycles\n\n    @Override\n    public void onActivityCreated(Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        onViewCreated();\n    }\n\n    @Override\n    public void onResume() {\n        super.onResume();\n        onViewResume();\n    }\n\n    @Override\n    public void onPause() {\n        super.onPause();\n        onViewPause();\n    }\n\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n        onViewDestroy();\n    }\n\n    // don't force child classes to implement the life cycle methods\n\n    @Override\n    public void onViewCreated() {\n    }\n\n    @Override\n    public void onViewResume() {\n    }\n\n    @Override\n    public void onViewPause() {\n    }\n\n    @Override\n    public void onViewDestroy() {\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/common/mvp/BasePresenter.java",
    "content": "package com.example.project.views.common.mvp;\n\n/**\n * Base presenter for activities and fragments.\n *\n * Equalize the lifecycle handling for easy switch between activity and fragment.\n * The wrapped life cycles avoid the necessary of super method calls and let you easy write unit tests.\n */\npublic interface BasePresenter {\n\n    /**\n     * Called after the view is full created and injected.\n     *\n     * At this time you should start to initialise the view content. This will only be called\n     * once in the life of the view. This gets be called at very end of onCreate.\n     */\n    void onViewCreated();\n\n    /**\n     * Called if the view is shown and the user may interact with it.\n     *\n     * May be called multiple times but only in combination with {@link #onViewPause()}.\n     */\n    void onViewResume();\n\n    /**\n     * Called when the view is going into background and the user can't anymore interact with it.\n     *\n     * This is the place to save persistent content.\n     *\n     * This is the same like onPause. Take also note of {@link android.app.Activity#onPause()}.\n     * May be called multiple times but only in combination with {@link #onViewResume()}.\n     */\n    void onViewPause();\n\n    /**\n     * Called if the view gets destroyed.\n     *\n     * Do final clean up by releasing/stopping not more necessary processes.\n     */\n    void onViewDestroy();\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/common/mvp/BaseView.java",
    "content": "package com.example.project.views.common.mvp;\n\npublic interface BaseView {\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/common/testwrapper/ViewFinisher.java",
    "content": "package com.example.project.views.common.testwrapper;\n\nimport android.app.Activity;\n\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.RootContext;\n\n@EBean\npublic class ViewFinisher {\n\n    @RootContext\n    Activity activity;\n\n    public void finish() {\n        activity.finish();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_details/DetailActivity.java",
    "content": "package com.example.project.views.contact_details;\n\nimport com.example.project.R;\nimport com.example.project.views.common.mvp.BaseActivityPresenter;\n\nimport org.androidannotations.annotations.EActivity;\nimport org.androidannotations.annotations.Extra;\nimport org.androidannotations.annotations.FragmentById;\n\n@EActivity(R.layout.activity_detail)\npublic class DetailActivity extends BaseActivityPresenter {\n\n    @FragmentById(R.id.fragment_detail)\n    DetailFragment detailFragment;\n\n    @Extra\n    protected long contactId;\n\n    @Override\n    public void onViewCreated() {\n        detailFragment.onShowContact(contactId);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_details/DetailActivityIntent.java",
    "content": "package com.example.project.views.contact_details;\n\nimport android.content.Context;\n\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.RootContext;\n\n@EBean\npublic class DetailActivityIntent {\n\n    @RootContext\n    Context context;\n\n    public void start(long contactId) {\n        DetailActivity_.intent(context).contactId(contactId).start();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_details/DetailFragment.java",
    "content": "package com.example.project.views.contact_details;\n\nimport com.example.project.R;\nimport com.example.project.views.common.mvp.BaseFragmentPresenter;\n\nimport org.androidannotations.annotations.EFragment;\n\n@EFragment(R.layout.fragment_detail)\npublic class DetailFragment extends BaseFragmentPresenter {\n\n    public void onShowContact(long contactId) {\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_details/DetailView.java",
    "content": "package com.example.project.views.contact_details;\n\nimport com.example.project.views.common.mvp.BaseView;\n\npublic class DetailView implements BaseView {\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_edit/EditActivity.java",
    "content": "package com.example.project.views.contact_edit;\n\nimport com.example.project.R;\nimport com.example.project.views.common.mvp.BaseActivityPresenter;\nimport com.example.project.views.common.testwrapper.ViewFinisher;\n\nimport org.androidannotations.annotations.Bean;\nimport org.androidannotations.annotations.EActivity;\nimport org.androidannotations.annotations.Extra;\nimport org.androidannotations.annotations.FragmentById;\n\n@EActivity(R.layout.activity_edit)\npublic class EditActivity extends BaseActivityPresenter implements EditConfirmedListener {\n\n    @FragmentById(R.id.fragment_edit)\n    EditFragment editFragment;\n\n    @Bean\n    ViewFinisher viewFinisher;\n\n    @Extra\n    protected long contactId;\n\n    @Override\n    public void onViewCreated() {\n        editFragment.setEditConfirmedListener(this);\n        editFragment.onShowContact(contactId);\n    }\n\n    @Override\n    public void onEditConfirmed() {\n        viewFinisher.finish();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_edit/EditActivityIntent.java",
    "content": "package com.example.project.views.contact_edit;\n\nimport android.content.Context;\n\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.RootContext;\n\n@EBean\npublic class EditActivityIntent {\n\n    @RootContext\n    Context context;\n\n    public void start(long contactId) {\n        EditActivity_.intent(context).contactId(contactId).start();\n    }\n\n    public void start() {\n        EditActivity_.intent(context).start();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_edit/EditConfirmedListener.java",
    "content": "package com.example.project.views.contact_edit;\n\npublic interface EditConfirmedListener {\n    void onEditConfirmed();\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_edit/EditFragment.java",
    "content": "package com.example.project.views.contact_edit;\n\nimport com.example.project.R;\nimport com.example.project.business.contact.CreateContactFunction;\nimport com.example.project.business.contact.QueryContactFunction;\nimport com.example.project.database.provider.contact.ContactModel;\nimport com.example.project.views.common.mvp.BaseFragmentPresenter;\n\nimport org.androidannotations.annotations.Background;\nimport org.androidannotations.annotations.Bean;\nimport org.androidannotations.annotations.Click;\nimport org.androidannotations.annotations.EFragment;\nimport org.apache.commons.lang3.StringUtils;\nimport org.joda.time.DateTime;\n\nimport java.util.Date;\n\n@EFragment(R.layout.fragment_edit)\npublic class EditFragment extends BaseFragmentPresenter {\n\n    @Bean\n    EditView editView;\n\n    @Bean\n    CreateContactFunction createContactFunction;\n\n    @Bean\n    QueryContactFunction queryContactFunction;\n\n    private EditConfirmedListener editConfirmedListener;\n    private long contactId;\n\n    public void setEditConfirmedListener(EditConfirmedListener editConfirmedListener) {\n        this.editConfirmedListener = editConfirmedListener;\n    }\n\n    public void onShowContact(long contactId) {\n        this.contactId = contactId;\n        if(contactId != 0) {\n            loadAndShowContactDetails();\n        }\n    }\n\n    private void loadAndShowContactDetails() {\n        ContactModel contact = queryContactFunction.apply(contactId);\n        editView.setFirstName(contact.getFirstName());\n        editView.setLastName(contact.getLastName());\n        editView.setBirthDate(dateString(contact.getBirthdate()));\n    }\n\n    @Click(R.id.confirm)\n    public void onClickConfirm() {\n        String firstName = editView.getFirstName();\n        String lastName = editView.getLastName();\n        String birthDate = editView.getBirthDate();\n\n        createOrUpdateContact(firstName, lastName, date(birthDate));\n        editConfirmedListener.onEditConfirmed();\n    }\n\n    @Background\n    void createOrUpdateContact(String firstName, String lastName, Date birthDate) {\n        createContactFunction.apply(firstName, lastName, birthDate);\n    }\n\n    private String dateString(Date date) {\n        if (date == null) {\n            return \"\";\n        } else {\n            return date.toString();\n        }\n    }\n\n    private Date date(String dateString) {\n        if(StringUtils.isNotEmpty(dateString)) {\n            return DateTime.parse(dateString).toDate();\n        } else {\n            return null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_edit/EditView.java",
    "content": "package com.example.project.views.contact_edit;\n\nimport android.widget.EditText;\n\nimport com.example.project.R;\nimport com.example.project.views.common.mvp.BaseView;\n\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.ViewById;\n\n@EBean\npublic class EditView implements BaseView {\n\n    @ViewById(R.id.first_name)\n    EditText firstName;\n\n    @ViewById(R.id.last_name)\n    EditText lastName;\n\n    @ViewById(R.id.birth_date)\n    EditText birthDate;\n\n    public void setFirstName(String input) {\n        firstName.setText(input);\n    }\n\n    public String getFirstName() {\n        return firstName.getText().toString();\n    }\n\n    public void setLastName(String input) {\n        lastName.setText(input);\n    }\n\n    public String getLastName() {\n        return lastName.getText().toString();\n    }\n\n    public void setBirthDate(String input) {\n        birthDate.setText(input);\n    }\n\n    public String getBirthDate() {\n        return birthDate.getText().toString();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_list/ContactAdapter.java",
    "content": "package com.example.project.views.contact_list;\n\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.support.v4.widget.CursorAdapter;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\nimport com.example.project.database.provider.contact.ContactCursor;\n\nimport org.androidannotations.annotations.EBean;\n\n@EBean\npublic class ContactAdapter extends CursorAdapter {\n\n    public static final int AVOID_AUTO_QUERY_AND_CONTENT_OBSERVERS = 0;\n\n    public ContactAdapter(Context context) {\n        super(context, null, AVOID_AUTO_QUERY_AND_CONTENT_OBSERVERS);\n    }\n\n    @Override\n    public View newView(Context context, Cursor cursor, ViewGroup parent) {\n        return LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_2, null);\n    }\n\n    @Override\n    public void bindView(View view, Context context, Cursor cursor) {\n        ContactCursor contacts = (ContactCursor) cursor;\n        ((TextView) view.findViewById(android.R.id.text1)).setText(contacts.getFirstName() + \" \" + contacts.getLastName());\n        if(contacts.getBirthdate() != null) {\n            ((TextView) view.findViewById(android.R.id.text2)).setText(contacts.getBirthdate().toString());\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_list/ContactAdapterLoader.java",
    "content": "package com.example.project.views.contact_list;\n\nimport android.database.Cursor;\nimport android.support.v4.widget.CursorAdapter;\nimport android.util.Log;\n\nimport com.example.project.business.contact.QueryContactListFunction;\nimport com.example.project.views.common.cursorloader.CursorAdapterWithCursorLoader;\n\nimport org.androidannotations.annotations.Bean;\nimport org.androidannotations.annotations.EBean;\n\n@EBean\npublic class ContactAdapterLoader extends CursorAdapterWithCursorLoader {\n\n    @Bean\n    ContactAdapter contactAdapter;\n\n    @Bean\n    QueryContactListFunction queryContactListFunction;\n\n    @Override\n    public CursorAdapter getCursorAdapter() {\n        return contactAdapter;\n    }\n\n    @Override\n    public int getLoaderId() {\n        return 1;\n    }\n\n    @Override\n    public Cursor loadCursor() {\n        Log.e(\"sync\", \"sync load\");\n        return queryContactListFunction.apply();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_list/ContactListActivity.java",
    "content": "package com.example.project.views.contact_list;\n\nimport android.util.Log;\nimport android.widget.Toast;\n\nimport com.example.project.R;\nimport com.example.project.business.contact_sync.SyncContactsFunction;\nimport com.example.project.views.common.AppIdlingResources;\nimport com.example.project.views.common.mvp.BaseActivityPresenter;\nimport com.example.project.views.contact_details.DetailActivityIntent;\nimport com.example.project.views.contact_details.DetailFragment;\nimport com.example.project.views.contact_edit.EditActivityIntent;\n\nimport org.androidannotations.annotations.Background;\nimport org.androidannotations.annotations.Bean;\nimport org.androidannotations.annotations.EActivity;\nimport org.androidannotations.annotations.FragmentById;\nimport org.androidannotations.annotations.OptionsItem;\nimport org.androidannotations.annotations.OptionsMenu;\nimport org.androidannotations.annotations.UiThread;\n\n@EActivity(R.layout.activity_main)\n@OptionsMenu(R.menu.menu_main)\npublic class ContactListActivity extends BaseActivityPresenter implements ShowContactListener {\n\n    @FragmentById(R.id.fragment_list)\n    ContactListFragment contactListFragment;\n\n    @FragmentById(R.id.fragment_detail)\n    DetailFragment detailFragment;\n\n    @Bean\n    DetailActivityIntent detailActivityIntent;\n\n    @Bean\n    EditActivityIntent editActivityIntent;\n\n    @Bean\n    SyncContactsFunction syncContactsFunction;\n\n    @Bean\n    AppIdlingResources appIdlingResources;\n\n    @Override\n    public void onViewCreated() {\n        contactListFragment.setShowContactListener(this);\n    }\n\n    @OptionsItem(R.id.action_add_contact)\n    public void onCreateContact() {\n        editActivityIntent.start();\n    }\n\n    @OptionsItem(R.id.action_sync_contacts)\n    @Background\n    void onSyncContacts() {\n        Log.e(\"sync\", \"sync start\");\n        appIdlingResources.increment();\n        SyncContactsFunction.Result result = syncContactsFunction.apply();\n        showSyncResult(result);\n        appIdlingResources.decrement();\n        Log.e(\"sync\", \"sync finish\");\n    }\n\n    @UiThread(propagation = UiThread.Propagation.REUSE)\n    void showSyncResult(SyncContactsFunction.Result result) {\n        if(result.successful) {\n            Log.e(\"sync\", \"sync success\");\n            Toast.makeText(this, \"Sync done\", Toast.LENGTH_SHORT).show();\n        } else {\n            Log.e(\"sync\", \"sync failed\");\n            Toast.makeText(this, \"Sync failed: \" + result.errorReason, Toast.LENGTH_SHORT).show();\n        }\n    }\n\n    @Override\n    public void onShowContact(long contactId) {\n        if(detailFragment == null) {\n            detailActivityIntent.start(contactId);\n        } else {\n            detailFragment.onShowContact(contactId);\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_list/ContactListActivityIntent.java",
    "content": "package com.example.project.views.contact_list;\n\nimport android.content.Context;\n\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.RootContext;\n\n@EBean\npublic class ContactListActivityIntent {\n\n    @RootContext\n    Context context;\n\n    public void start() {\n        ContactListActivity_.intent(context).start();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_list/ContactListFragment.java",
    "content": "package com.example.project.views.contact_list;\n\nimport com.example.project.R;\nimport com.example.project.database.provider.contact.ContactCursor;\nimport com.example.project.views.common.mvp.BaseFragmentPresenter;\n\nimport org.androidannotations.annotations.Bean;\nimport org.androidannotations.annotations.EFragment;\nimport org.androidannotations.annotations.ItemClick;\n\n@EFragment(R.layout.fragment_list)\npublic class ContactListFragment extends BaseFragmentPresenter {\n\n    @Bean\n    ContactListView view;\n\n    @Bean\n    ContactAdapterLoader contactsLoader;\n\n    private ShowContactListener showContactListener;\n\n    @Override\n    public void onViewCreated() {\n        view.showContacts(contactsLoader.getCursorAdapter());\n        contactsLoader.start();\n    }\n\n    @ItemClick(R.id.listView)\n    public void onContactClick(ContactCursor item) {\n        showContactListener.onShowContact(item.getId());\n    }\n\n    public void setShowContactListener(ShowContactListener showContactListener) {\n        this.showContactListener = showContactListener;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_list/ContactListView.java",
    "content": "package com.example.project.views.contact_list;\n\nimport android.widget.ListAdapter;\nimport android.widget.ListView;\n\nimport com.example.project.R;\nimport com.example.project.views.common.mvp.BaseView;\n\nimport org.androidannotations.annotations.EBean;\nimport org.androidannotations.annotations.ViewById;\n\n@EBean\npublic class ContactListView implements BaseView {\n\n    @ViewById(R.id.listView)\n    ListView contactList;\n\n    public void showContacts(ListAdapter listAdapter) {\n        contactList.setAdapter(listAdapter);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/contact_list/ShowContactListener.java",
    "content": "package com.example.project.views.contact_list;\n\npublic interface ShowContactListener {\n    void onShowContact(long contact);\n}\n"
  },
  {
    "path": "app/src/main/java/com/example/project/views/start/StartActivity.java",
    "content": "package com.example.project.views.start;\n\nimport com.example.project.views.common.mvp.BaseActivityPresenter;\nimport com.example.project.views.contact_list.ContactListActivityIntent;\n\nimport org.androidannotations.annotations.Bean;\nimport org.androidannotations.annotations.EActivity;\n\n@EActivity\npublic class StartActivity extends BaseActivityPresenter {\n\n    @Bean\n    ContactListActivityIntent contactListActivityIntent;\n\n    @Override\n    public void onViewResume() {\n        contactListActivityIntent.start();\n    }\n}\n"
  },
  {
    "path": "app/src/main/json/database/schema/_config.json",
    "content": "{\n  \"syntaxVersion\": 3,\n  \"projectPackageId\": \"com.example.project\",\n  \"authority\": \"com.example.project\",\n  \"providerJavaPackage\": \"com.example.project.database.provider\",\n  \"providerClassName\": \"ExampleProvider\",\n  \"sqliteOpenHelperClassName\": \"ExampleSQLiteOpenHelper\",\n  \"sqliteOpenHelperCallbacksClassName\": \"ExampleSQLiteOpenHelperCallbacks\",\n  \"databaseFileName\": \"example.db\",\n  \"databaseVersion\": 1,\n  \"enableForeignKeys\": true,\n  \"useAnnotations\": true\n}"
  },
  {
    "path": "app/src/main/json/database/schema/address.json",
    "content": "{\n  \"fields\": [\n    {\n      \"name\": \"contact_id\",\n      \"type\": \"Long\",\n      \"nullable\": false,\n      \"foreignKey\": {\n        \"table\": \"contact\",\n        \"onDelete\": \"CASCADE\"\n      }\n    },\n    {\n      \"name\": \"street\",\n      \"type\": \"String\",\n      \"nullable\": true\n    },\n    {\n      \"name\": \"number\",\n      \"type\": \"String\",\n      \"nullable\": true\n    },\n    {\n      \"name\": \"city\",\n      \"type\": \"String\",\n      \"nullable\": true\n    },\n    {\n      \"name\": \"country\",\n      \"type\": \"String\",\n      \"nullable\": true\n    },\n    {\n      \"name\": \"state\",\n      \"type\": \"String\",\n      \"nullable\": true\n    },\n    {\n      \"name\": \"postalcode\",\n      \"type\": \"String\",\n      \"nullable\": true\n    }\n  ]\n}"
  },
  {
    "path": "app/src/main/json/database/schema/contact.json",
    "content": "{\n  \"fields\": [\n    {\n      \"name\": \"uid\",\n      \"type\": \"String\",\n      \"nullable\": true\n    },\n    {\n      \"name\": \"first_name\",\n      \"type\": \"String\",\n      \"nullable\": true\n    },\n    {\n      \"name\": \"last_name\",\n      \"type\": \"String\",\n      \"nullable\": true\n    },\n    {\n      \"name\": \"birthdate\",\n      \"type\": \"Date\",\n      \"nullable\": true\n    }\n  ],\n  \"constraints\": [\n    {\n      \"name\": \"first_or_last_name_must_be_given\",\n      \"definition\": \"CHECK((first_name <> '' AND first_name IS NOT NULL) OR (last_name <> '' AND last_name IS NOT NULL)) ON CONFLICT FAIL\"\n    }\n  ]\n}"
  },
  {
    "path": "app/src/main/json/network/schema/contactJson.json",
    "content": "{\n  \"description\": \"Simple single contact.\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"id\": { \"type\": \"string\" },\n    \"firstName\": { \"type\": \"string\" },\n    \"lastName\": { \"type\": \"string\" },\n    \"birthDate\": { \"type\": \"string\" }\n  }\n}"
  },
  {
    "path": "app/src/main/json/network/schema/contactListJson.json",
    "content": "{\n  \"description\": \"Collection of contacts.\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"contacts\" : {\n      \"type\" : \"array\",\n      \"items\" : {\n        \"$ref\" : \"contactJson.json\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "app/src/main/res/layout/activity_detail.xml",
    "content": "<fragment xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/fragment_detail\"\n    android:name=\"com.example.project.views.contact_details.DetailFragment_\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:layout=\"@layout/fragment_detail\" />\n"
  },
  {
    "path": "app/src/main/res/layout/activity_edit.xml",
    "content": "<fragment xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/fragment_edit\"\n    android:name=\"com.example.project.views.contact_edit.EditFragment_\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:layout=\"@layout/fragment_edit\" />\n"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<fragment xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/fragment_list\"\n    android:name=\"com.example.project.views.contact_list.ContactListFragment_\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:layout=\"@layout/fragment_list\" />\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_detail.xml",
    "content": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    tools:context=\".MainActivityFragment\">\n\n    <TextView\n        android:id=\"@+id/first_name\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/hello_world\" />\n    <TextView\n        android:id=\"@+id/last_name\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/hello_world\" />\n\n    <DatePicker\n        android:id=\"@+id/birth_date\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <Button\n        android:id=\"@+id/confirm\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_edit.xml",
    "content": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    tools:context=\".MainActivityFragment\">\n\n    <android.support.design.widget.TextInputLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n        <EditText\n            android:id=\"@+id/first_name\"\n            android:layout_width=\"200dp\"\n            android:layout_height=\"wrap_content\"\n            android:hint=\"@string/first_name\" />\n\n    </android.support.design.widget.TextInputLayout>\n\n    <android.support.design.widget.TextInputLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n        <EditText\n            android:id=\"@+id/last_name\"\n            android:layout_width=\"200dp\"\n            android:layout_height=\"wrap_content\"\n            android:hint=\"@string/last_name\" />\n\n    </android.support.design.widget.TextInputLayout>\n\n    <android.support.design.widget.TextInputLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n        <EditText\n            android:id=\"@+id/birth_date\"\n            android:layout_width=\"200dp\"\n            android:layout_height=\"wrap_content\"\n            android:inputType=\"date\"\n            android:hint=\"@string/birth_date\" />\n\n    </android.support.design.widget.TextInputLayout>\n\n    <Button\n        android:id=\"@+id/confirm\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/create_contact\" />\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_list.xml",
    "content": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    tools:context=\".MainActivityFragment\">\n\n    <ListView\n        android:id=\"@+id/listView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_alignParentLeft=\"true\"\n        android:layout_alignParentStart=\"true\"\n        android:layout_alignParentTop=\"true\" />\n\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/layout-land/activity_main.xml",
    "content": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:baselineAligned=\"false\"\n    android:orientation=\"horizontal\">\n\n    <fragment\n        android:id=\"@+id/fragment_list\"\n        android:name=\"com.example.project.views.contact_list.ContactListFragment_\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"match_parent\"\n        android:layout_weight=\"0.3\"\n        tools:layout=\"@layout/fragment_list\" />\n\n    <fragment\n        android:id=\"@+id/fragment_detail\"\n        android:name=\"com.example.project.views.contact_details.DetailFragment_\"\n        android:layout_width=\"0dp\"\n        android:layout_height=\"match_parent\"\n        android:layout_weight=\"0.7\"\n        tools:layout=\"@layout/fragment_detail\"\n        tools:ignore=\"InconsistentLayout\" />\n\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/menu/menu_main.xml",
    "content": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:context=\".MainActivity\">\n\n    <item\n        android:id=\"@+id/action_add_contact\"\n        android:icon=\"@android:drawable/ic_input_add\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/action_add_contact\"\n        app:showAsAction=\"ifRoom\" />\n\n    <item\n        android:id=\"@+id/action_sync_contacts\"\n        android:icon=\"@android:drawable/stat_notify_sync_noanim\"\n        android:orderInCategory=\"50\"\n        android:title=\"@string/action_sync_contacts\"\n        app:showAsAction=\"ifRoom\" />\n</menu>\n"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/string_api_url.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"const_wiremock_ip\">#const_wiremock_ip#</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">InitialAndroidProject</string>\n    <string name=\"hello_world\">Hello world!</string>\n\n    <string name=\"action_add_contact\">Add Contact</string>\n    <string name=\"action_sync_contacts\">Sync Contacts</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings_details.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n\n    <string name=\"first_name\">First Name</string>\n    <string name=\"last_name\">Last Name</string>\n    <string name=\"birth_date\">Birth Date</string>\n    <string name=\"create_contact\">Add</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/test/java/com/example/project/RoboTestCase.java",
    "content": "package com.example.project;\n\nimport android.content.Context;\n\nimport com.example.project.database.provider.ExampleSQLiteOpenHelper;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RobolectricGradleTestRunner;\nimport org.robolectric.RuntimeEnvironment;\nimport org.robolectric.annotation.Config;\n\nimport java.lang.reflect.Field;\n\n@RunWith(RobolectricGradleTestRunner.class)\n@Config(constants = BuildConfig.class, sdk = 21)\npublic abstract class RoboTestCase {\n\n    protected Context context;\n\n    @Before\n    public void roboSetup() {\n        context = RuntimeEnvironment.application;\n    }\n\n    @After\n    public void finishRobolectricTest() {\n        resetSingleton(ExampleSQLiteOpenHelper.class, \"sInstance\");\n    }\n\n    private void resetSingleton(Class clazz, String fieldName) {\n        Field instance;\n        try {\n            instance = clazz.getDeclaredField(fieldName);\n            instance.setAccessible(true);\n            instance.set(null, null);\n        } catch (Exception e) {\n            throw new RuntimeException();\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/test/java/com/example/project/business/contact/QueryContactListFunctionTest.java",
    "content": "package com.example.project.business.contact;\n\nimport com.example.project.database.provider.contact.ContactCursor;\nimport com.example.project.database.contact.ContactDb;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.runners.MockitoJUnitRunner;\n\nimport static org.mockito.BDDMockito.given;\nimport static org.assertj.core.api.Assertions.assertThat;\n\n@RunWith(MockitoJUnitRunner.class)\npublic class QueryContactListFunctionTest {\n\n    @InjectMocks\n    QueryContactListFunction queryContactListFunction;\n\n    @Mock\n    ContactDb contactDb;\n\n    @Mock\n    ContactCursor allContactCursor;\n\n    @Test\n    public void shouldLoadAllContacts() {\n        given(contactDb.queryAll()).willReturn(allContactCursor);\n        ContactCursor result = queryContactListFunction.apply();\n        assertThat(result).isSameAs(allContactCursor);\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/example/project/database/contact/AddressDbInsertTest.java",
    "content": "package com.example.project.database.contact;\n\nimport android.database.sqlite.SQLiteException;\n\nimport com.example.project.RoboTestCase;\nimport com.example.project.database.provider.address.AddressContentValues;\nimport com.example.project.database.provider.contact.ContactContentValues;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class AddressDbInsertTest extends RoboTestCase {\n\n    ContactDb contactDb;\n    AddressDb addressDb;\n    long contactId;\n    long addressId;\n\n    AddressContentValues addressContentValues = new AddressContentValues()\n            .putStreet(\"My Street\")\n            .putNumber(\"42a\")\n            .putCity(\"Berlin\")\n            .putCountry(\"Berlin\")\n            .putState(\"Germany\")\n            .putPostalcode(\"12345\");\n\n    @Before\n    public void setup() {\n        addressDb = AddressDb_.getInstance_(context);\n        contactDb = ContactDb_.getInstance_(context);\n        givenContactReference();\n    }\n\n    @Test\n    public void insert() {\n        whenAddressIsInserted(addressContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    @Test(expected = SQLiteException.class)\n    public void insert_contactId_isMandatory() {\n        addressContentValues.putContactId(0);\n        whenAddressIsInserted(addressContentValues);\n    }\n\n    @Test(expected = SQLiteException.class)\n    public void insert_contactId_mustExist() {\n        long notExistingContact = 42;\n        assertThat(notExistingContact).isNotEqualTo(contactId);\n        addressContentValues.putContactId(notExistingContact);\n        whenAddressIsInserted(addressContentValues);\n    }\n\n    @Test\n    public void insert_street_isNullable() {\n        addressContentValues.putStreet(null);\n        whenAddressIsInserted(addressContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    @Test\n    public void insert_number_isNullable() {\n        addressContentValues.putNumber(null);\n        whenAddressIsInserted(addressContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    @Test\n    public void insert_city_isNullable() {\n        addressContentValues.putCity(null);\n        whenAddressIsInserted(addressContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    @Test\n    public void insert_country_isNullable() {\n        addressContentValues.putCountry(null);\n        whenAddressIsInserted(addressContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    @Test\n    public void insert_state_isNullable() {\n        addressContentValues.putState(null);\n        whenAddressIsInserted(addressContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    @Test\n    public void insert_postalcode_isNullable() {\n        addressContentValues.putPostalcode(null);\n        whenAddressIsInserted(addressContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    private void thenInsertWasSuccessful() {\n        assertThat(addressId).isPositive();\n    }\n\n    private void givenContactReference() {\n        contactId = contactDb.insert(new ContactContentValues().putFirstName(\"May\"));\n        addressContentValues.putContactId(contactId);\n    }\n\n    private void whenAddressIsInserted(AddressContentValues contentValues) {\n        givenAddressAtDatabase(contentValues);\n    }\n\n    private void givenAddressAtDatabase(AddressContentValues contentValues) {\n        addressId = addressDb.insert(contentValues);\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/example/project/database/contact/AddressDbTest.java",
    "content": "package com.example.project.database.contact;\n\nimport com.example.project.RoboTestCase;\nimport com.example.project.database.provider.address.AddressContentValues;\nimport com.example.project.database.provider.address.AddressCursor;\nimport com.example.project.database.provider.contact.ContactContentValues;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class AddressDbTest extends RoboTestCase {\n\n    ContactDb contactDb;\n    AddressDb addressDb;\n    long contactId;\n    long addressId;\n\n    AddressContentValues addressContentValues = new AddressContentValues()\n            .putStreet(\"My Street\")\n            .putNumber(\"42a\")\n            .putCity(\"Berlin\")\n            .putCountry(\"Berlin\")\n            .putState(\"Germany\")\n            .putPostalcode(\"12345\");\n\n    @Before\n    public void setup() {\n        addressDb = AddressDb_.getInstance_(context);\n        contactDb = ContactDb_.getInstance_(context);\n        givenContactReference();\n    }\n\n    @Test\n    public void queryById() {\n        givenAddressAtDatabase(addressContentValues);\n        AddressCursor addressCursor = addressDb.queryById(addressId);\n        assertThat(addressCursor.getCount()).isEqualTo(1);\n    }\n\n    @Test\n    public void queryById_correctIds() {\n        givenContactReference();\n        givenAddressAtDatabase(addressContentValues);\n        assertThat(contactId).isNotEqualTo(1);\n        assertThat(addressId).isNotEqualTo(contactId);\n\n        AddressCursor addressCursor = addressDb.queryById(addressId);\n        addressCursor.moveToFirst();\n\n        assertThat(addressCursor.getId()).isEqualTo(addressId);\n        assertThat(addressCursor.getContactId()).isEqualTo(contactId);\n    }\n\n    private void givenContactReference() {\n        contactId = contactDb.insert(new ContactContentValues().putFirstName(\"May\"));\n        addressContentValues.putContactId(contactId);\n    }\n\n    private void givenAddressAtDatabase(AddressContentValues contentValues) {\n        addressId = addressDb.insert(contentValues);\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/example/project/database/contact/ContactDbInsertTest.java",
    "content": "package com.example.project.database.contact;\n\n\nimport android.database.sqlite.SQLiteException;\n\nimport com.example.project.RoboTestCase;\nimport com.example.project.database.provider.contact.ContactContentValues;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.util.Date;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class ContactDbInsertTest extends RoboTestCase {\n\n    ContactDb contactDb;\n    long contactId;\n\n    ContactContentValues contactContentValues = new ContactContentValues()\n            .putFirstName(\"Max\")\n            .putLastName(\"Max\")\n            .putBirthdate(new Date());\n\n    @Before\n    public void setup() {\n        contactDb = ContactDb_.getInstance_(context);\n    }\n\n    @Test\n    public void insert() {\n        whenContactIsInserted(contactContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    @Test\n    public void insert_firstname_isNullable() {\n        contactContentValues.putFirstName(null);\n        whenContactIsInserted(contactContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    @Test\n    public void insert_lastname_isNullable() {\n        contactContentValues.putLastName(null);\n        whenContactIsInserted(contactContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    @Test(expected = SQLiteException.class)\n    public void insert_firstOrLastname_isMandatory() {\n        contactContentValues.putFirstName(null);\n        contactContentValues.putLastName(null);\n        whenContactIsInserted(contactContentValues);\n    }\n\n    @Test\n    public void insert_birthdate_isNullable() {\n        contactContentValues.putBirthdate(0l);\n        whenContactIsInserted(contactContentValues);\n        thenInsertWasSuccessful();\n    }\n\n    private void thenInsertWasSuccessful() {\n        assertThat(contactId).isPositive();\n    }\n\n    private void whenContactIsInserted(ContactContentValues contentValues) {\n        contactId = contactDb.insert(contentValues);\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/example/project/database/contact/ContactDbTest.java",
    "content": "package com.example.project.database.contact;\n\n\nimport com.example.project.RoboTestCase;\nimport com.example.project.database.provider.contact.ContactContentValues;\nimport com.example.project.database.provider.contact.ContactCursor;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.util.Date;\n\nimport static org.assertj.android.api.Assertions.assertThat;\n\npublic class ContactDbTest extends RoboTestCase {\n\n    ContactDb contactDb;\n    long contactId;\n\n    ContactContentValues contactContentValues = new ContactContentValues()\n            .putFirstName(\"Max\")\n            .putLastName(\"Max\")\n            .putBirthdate(new Date());\n\n    @Before\n    public void setup() {\n        contactDb = ContactDb_.getInstance_(context);\n    }\n\n    @Test\n    public void queryAll() {\n        givenContactAtDatabase(contactContentValues);\n        givenContactAtDatabase(contactContentValues);\n        ContactCursor contactCursor = contactDb.queryAll();\n        assertThat(contactCursor).hasCount(2);\n    }\n\n    private void givenContactAtDatabase(ContactContentValues contentValues) {\n        contactId = contactDb.insert(contentValues);\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/example/project/views/contact_edit/EditActivityTest.java",
    "content": "package com.example.project.views.contact_edit;\n\nimport com.example.project.views.common.testwrapper.ViewFinisher;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.runners.MockitoJUnitRunner;\n\nimport static org.mockito.Mockito.verify;\n\n@RunWith(MockitoJUnitRunner.class)\npublic class EditActivityTest {\n\n    @InjectMocks\n    EditActivity editActivity;\n\n    @Mock\n    EditFragment editFragment;\n\n    @Mock\n    ViewFinisher viewFinisher;\n\n    long CONTACT_ID = 42;\n\n    @Test\n    public void testOnViewCreated_shouldInitDetailFragment() throws Exception {\n        editActivity.contactId = CONTACT_ID;\n        editActivity.onViewCreated();\n        verify(editFragment).setEditConfirmedListener(editActivity);\n        verify(editFragment).onShowContact(CONTACT_ID);\n    }\n\n    @Test\n    public void testOnEditConfirmed_shouldFinishTheActivity() throws Exception {\n        editActivity.onEditConfirmed();\n        verify(viewFinisher).finish();\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/example/project/views/contact_edit/EditFragmentTest.java",
    "content": "package com.example.project.views.contact_edit;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.runners.MockitoJUnitRunner;\n\nimport static org.junit.Assert.*;\n\n@RunWith(MockitoJUnitRunner.class)\n@Ignore\npublic class EditFragmentTest {\n\n    @InjectMocks\n    EditFragment editFragment;\n\n    @Mock\n    EditView editView;\n\n    @Mock\n    EditConfirmedListener editConfirmedListener;\n\n    @Test\n    public void testOnShowContact_shouldLoadContactDetails() throws Exception {\n        editFragment.onShowContact(42);\n    }\n\n    @Test\n    public void testOnClickConfirm_shouldSaveContact() throws Exception {\n\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/example/project/views/contact_list/ContactListActivityTest.java",
    "content": "package com.example.project.views.contact_list;\n\nimport com.example.project.views.contact_details.DetailActivityIntent;\nimport com.example.project.views.contact_details.DetailFragment;\nimport com.example.project.views.contact_edit.EditActivityIntent;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.runners.MockitoJUnitRunner;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.mockito.Mockito.verify;\n\n@RunWith(MockitoJUnitRunner.class)\npublic class ContactListActivityTest {\n\n    public static final int CONTACT_ID = 42;\n\n    @Mock\n    DetailActivityIntent detailActivityIntent;\n\n    @Mock\n    EditActivityIntent editActivityIntent;\n\n    @Mock\n    ContactListFragment contactListFragment;\n\n    @Mock\n    DetailFragment detailFragment;\n\n    @InjectMocks\n    ContactListActivity contactListActivity;\n\n    @Test\n    public void testOnCreateContact() throws Exception {\n        whenClickCreateContact();\n        thenEditActivityIsStartedInCreationMode();\n    }\n\n    @Test\n    public void testOnShowContact_portrait() throws Exception {\n        givenPortraitMode();\n        contactListActivity.onShowContact(42);\n        thenDetailAreShownInNewActivity(CONTACT_ID);\n    }\n\n    @Test\n    public void testOnShowContact_landscape() throws Exception {\n        givenLandscapeMode();\n        contactListActivity.onShowContact(CONTACT_ID);\n        thenDetailsAreShownInDetailFragment(CONTACT_ID);\n    }\n\n    @Test\n    public void testOnViewCreated_shouldRegisterSelfAsShowContactListener() {\n        contactListActivity.onViewCreated();\n        verify(contactListFragment).setShowContactListener(contactListActivity);\n    }\n\n    private void thenDetailAreShownInNewActivity(long expectedContactId) {\n        verify(detailActivityIntent).start(expectedContactId);\n    }\n\n    private void thenDetailsAreShownInDetailFragment(long expectedContactId) {\n        verify(detailFragment).onShowContact(expectedContactId);\n    }\n\n    private void givenPortraitMode() {\n        contactListActivity.detailFragment = null;\n    }\n\n    private void givenLandscapeMode() {\n        assertThat(contactListActivity.detailFragment).isNotNull();\n    }\n\n    private void thenEditActivityIsStartedInCreationMode() {\n        verify(editActivityIntent).start();\n    }\n\n    private void whenClickCreateContact() {\n        contactListActivity.onCreateContact();\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/example/project/views/contact_list/ContactListFragmentTest.java",
    "content": "package com.example.project.views.contact_list;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.runners.MockitoJUnitRunner;\n\nimport static org.mockito.BDDMockito.given;\nimport static org.mockito.Mockito.verify;\n\n@RunWith(MockitoJUnitRunner.class)\npublic class ContactListFragmentTest {\n\n    @Mock\n    ContactListView view;\n\n    @Mock\n    ContactAdapterLoader contactAdapterLoader;\n\n    @Mock\n    ContactAdapter contactAdapter;\n\n    @InjectMocks\n    ContactListFragment contactListFragment;\n\n    @Before\n    public void setup() {\n        given(contactAdapterLoader.getCursorAdapter()).willReturn(contactAdapter);\n    }\n\n    @Test\n    public void testOnViewCreated_shouldStartLoadingContacts() throws Exception {\n        contactListFragment.onViewCreated();\n        verify(view).showContacts(contactAdapter);\n        verify(contactAdapterLoader).start();\n    }\n}"
  },
  {
    "path": "app/src/test/java/com/example/project/views/start/StartActivityTest.java",
    "content": "package com.example.project.views.start;\n\nimport com.example.project.views.contact_list.ContactListActivityIntent;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.runners.MockitoJUnitRunner;\n\nimport static org.mockito.Mockito.verify;\n\n@RunWith(MockitoJUnitRunner.class)\npublic class StartActivityTest {\n\n    @Mock\n    ContactListActivityIntent contactListActivityIntent;\n\n    @InjectMocks\n    StartActivity startActivity;\n\n    @Test\n    public void viewIsStarted() throws Exception {\n        startActivity.onViewResume();\n        thenNextActivityShouldBeStarted();\n    }\n\n    private void thenNextActivityShouldBeStarted() {\n        verify(contactListActivityIntent).start();\n    }\n}"
  },
  {
    "path": "appCt/build.gradle",
    "content": "buildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        // support to get app module under test with robolectric in separated test module\n        classpath \"com.novoda:gradle-android-test-plugin:0.10.4\"\n    }\n}\n\napply plugin: 'java'\n\n// support code coverage for the component tests\n// this must be before the plugin: 'android-test' declaration\napply plugin: \"jacoco\"\n\n// support to get app module under test with robolectric in separated test module\napply plugin: 'android-test'\n\nandroid {\n    projectUnderTest ':app'\n}\n\n// support to get the separated test module work inside android studio\n// this must be after the projectUnderTest declaration\napply from: 'build.novoda-android-studio.gradle'\n\n// support code coverage for the component tests\n// this must be after the projectUnderTest declaration\napply from: \"build.jacoco-test-report.gradle\"\n\n// test support for android specific stuff like database and network\napply from: 'build.robolectric.gradle'\n\ndependencies {\n\n    // basic unit tests support + mocks + fluent assertions + android assertions\n    testCompile 'junit:junit:4.12'\n    testCompile 'org.mockito:mockito-all:2.0.2-beta'\n    testCompile('com.squareup.assertj:assertj-android:1.1.0') {\n        exclude module: \"support-annotations\"\n    }\n\n    // easy modify wiremock stubbing support\n    // need standalone version to avoid conflicts with org.apache.http classes (not all tests will run anymore)\n    testCompile ('com.github.tomakehurst:wiremock:1.42:standalone') { exclude module: \"*\" }\n}\n\n\n// force utf-8 is necessary for windows environments, without it test classes aren't interpreted in utf-8\ntasks.withType(JavaCompile) {\n    options.encoding = \"utf-8\"\n}\n\n// avoid release compile for tests for less build time\n// avoid lint and tests in same process (TODO check if still necessary)\nafterEvaluate {\n\n    def isLintRun = false\n    def isTestRun = false\n\n    gradle.startParameter.taskNames.each {\n        if (it.contains(\"lint\")) {\n            isLintRun = true\n        }\n        if (it.contains(\"test\")) {\n            isTestRun = true\n        }\n    }\n\n    if (isLintRun && isTestRun) {\n        println \"WARNING: tests for release type are disabled for supporting jacoco\"\n        println \"WARNING: run test and lint at same time is not supported\"\n        exit 1\n    }\n\n    if (isTestRun) {\n        tasks.each {\n            if (it.name.contains(\"Release\")) {\n                it.enabled = false\n            }\n        }\n    }\n}"
  },
  {
    "path": "appCt/build.jacoco-test-report.gradle",
    "content": "// apply plugin: \"jacoco\" must be before the plugin: 'android-test' declaration\n\njacoco {\n    toolVersion = projectJacocoVersion\n}\n\next.coverageSourceDirs = [\n        '../app/src/main/java',\n        '../app/build/source/apt/debug',\n        '../app/build/generated/source/db',\n        '../app/build/generated/source/buildConfig/debug',\n        '../app/build/generated/source/r/debug']\n\njacocoTestReport {\n    reports {\n        xml.enabled = false\n        html.enabled = true\n    }\n    // class R is used, but usage will not be covered, so ignore this class from report\n    classDirectories = fileTree(dir: '../App/build/intermediates/classes/debug',\n            exclude: 'com/example/R*.class')\n    additionalSourceDirs = files(coverageSourceDirs)\n    executionData = files('build/jacoco/testDebug.exec')\n}\n\n// just clean up dashboard, following reports are not of interest\ntestRelease.reports.html.enabled = false\ntestRelease.reports.junitXml.enabled = false\ntestDebug.reports.junitXml.enabled = false"
  },
  {
    "path": "appCt/build.novoda-android-studio.gradle",
    "content": "// workaround force compile the test classes in android studio\ntasks.testClasses.dependsOn(tasks.testDebugClasses)\n\n// workaround to force recognize correct output dirs for android studio\ntask addTest {\n    def file = file(project.name + \".iml\")\n    doLast {\n        try {\n            def parsedXml = (new XmlParser()).parse(file)\n            def node = parsedXml.component[1]\n            def outputNode = parsedXml.component[1].output[0]\n            def outputTestNode = parsedXml.component[1].'output-test'[0]\n            def rewrite = false\n\n            new Node(node, 'sourceFolder', ['url': 'file://$MODULE_DIR$/' + \"${it}\", 'isTestSource': \"true\"])\n\n            if (outputNode == null) {\n                new Node(node, 'output', ['url': 'file://$MODULE_DIR$/build/resources/testDebug'])\n                rewrite = true\n            } else {\n                if (outputNode.attributes['url'] != 'file://$MODULE_DIR$/build/resources/testDebug') {\n                    outputNode.attributes = ['url': 'file://$MODULE_DIR$/build/resources/testDebug']\n                    rewrite = true\n                }\n            }\n\n            if (outputTestNode == null) {\n                new Node(node, 'output-test', ['url': 'file://$MODULE_DIR$/build/test-classes/debug'])\n                rewrite = true\n            } else {\n                if (outputTestNode.attributes['url'] != 'file://$MODULE_DIR$/build/test-classes/debug') {\n                    outputTestNode.attributes = ['url': 'file://$MODULE_DIR$/build/test-classes/debug']\n                    rewrite = true\n                }\n            }\n\n            if (rewrite) {\n                def writer = new StringWriter()\n                new XmlNodePrinter(new PrintWriter(writer)).print(parsedXml)\n                file.text = writer.toString()\n            }\n        } catch (FileNotFoundException e) {\n            // iml not found, common on command line only builds\n        }\n\n    }\n}\ntasks.testClasses.dependsOn(tasks.addTest)"
  },
  {
    "path": "appCt/build.robolectric.gradle",
    "content": "dependencies {\n    testCompile('org.robolectric:shadows-support-v4:3.0') {\n        exclude module: \"robolectric\"\n        exclude module: \"support-v4\"\n        exclude module: \"support-annotations\"\n    }\n\n    testCompile('org.robolectric:robolectric:3.0') {\n        exclude module: 'classworlds'\n        exclude module: 'commons-logging'\n        exclude module: 'httpclient'\n        exclude module: 'maven-artifact'\n        exclude module: 'maven-artifact-manager'\n        exclude module: 'maven-error-diagnostics'\n        exclude module: 'maven-model'\n        exclude module: 'maven-project'\n        exclude module: 'maven-settings'\n        exclude module: 'plexus-container-default'\n        exclude module: 'plexus-interpolation'\n        exclude module: 'plexus-utils'\n        exclude module: 'wagon-file'\n        exclude module: 'wagon-http-lightweight'\n        exclude module: 'wagon-provider-api'\n    }\n}"
  },
  {
    "path": "appCt/src/test/java/android/database/ShadowContentObservable.java",
    "content": "package android.database;\n\nimport android.net.Uri;\n\nimport org.robolectric.annotation.Implementation;\nimport org.robolectric.annotation.Implements;\nimport org.robolectric.annotation.RealObject;\n\nimport java.util.ArrayList;\n\n@Implements(ContentObservable.class)\npublic class ShadowContentObservable {\n\n    @RealObject\n    ContentObservable realObject;\n\n    /**\n     * Through the synchronisation from foreground and background thread the mObservers access may throw ConcurrentModificationException\n     * when the list gets modified after notify an observer.\n     * <p/>\n     * Example is a cursorLoader after insert data on background.\n     * Then notify gets called and the loader does a reload where the loader add himself as observer.\n     * This operation changes existing observers list.\n     */\n    @Implementation\n    public void dispatchChange(boolean selfChange, Uri uri) {\n        synchronized (realObject.mObservers) {\n            @SuppressWarnings(\"unchecked\")\n            ArrayList<ContentObserver> currentObservers = (ArrayList<ContentObserver>) realObject.mObservers.clone();\n            for (ContentObserver observer : currentObservers) {\n                if (!selfChange || observer.deliverSelfNotifications()) {\n                    observer.dispatchChange(selfChange, uri);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/RobolectricTestCase.java",
    "content": "package com.example.project;\n\nimport android.content.Context;\nimport android.database.ShadowContentObservable;\n\nimport com.example.project.BuildConfig;\nimport com.example.project.database.provider.ExampleSQLiteOpenHelper;\nimport com.example.project.robolectric.CostomRobolectricTestRunner;\nimport com.example.project.robolectric.ShadowBackgroundExecutor;\nimport com.github.tomakehurst.wiremock.client.WireMock;\n\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.runner.RunWith;\nimport org.robolectric.RuntimeEnvironment;\nimport org.robolectric.annotation.Config;\n\nimport java.lang.reflect.Field;\n\n@RunWith(CostomRobolectricTestRunner.class)\n@Config(constants = BuildConfig.class, sdk = 21, shadows = {ShadowContentObservable.class, ShadowBackgroundExecutor.class})\npublic abstract class RobolectricTestCase {\n\n    protected Context context;\n\n    @Before\n    public void roboSetup() {\n        context = RuntimeEnvironment.application;\n        WireMock.configureFor(context.getString(R.string.const_wiremock_ip), 1337);\n        WireMock.resetToDefault();\n    }\n\n    @After\n    public void finishRobolectricTest() {\n        resetSingleton(ExampleSQLiteOpenHelper.class, \"sInstance\");\n    }\n\n    private void resetSingleton(Class clazz, String fieldName) {\n        Field instance;\n        try {\n            instance = clazz.getDeclaredField(fieldName);\n            instance.setAccessible(true);\n            instance.set(null, null);\n        } catch (Exception e) {\n            throw new RuntimeException();\n        }\n    }\n}"
  },
  {
    "path": "appCt/src/test/java/com/example/project/robolectric/CostomRobolectricTestRunner.java",
    "content": "package com.example.project.robolectric;\n\nimport com.example.project.BuildConfig;\n\nimport org.androidannotations.api.BackgroundExecutor;\nimport org.junit.runners.model.InitializationError;\nimport org.robolectric.RobolectricTestRunner;\nimport org.robolectric.annotation.Config;\nimport org.robolectric.internal.SdkEnvironment;\nimport org.robolectric.internal.bytecode.InstrumentationConfiguration;\n\nimport java.io.File;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n/**\n * Adjust some path declarations to the module under test.\n * <p/>\n * Original robolectric would search at wrong locations when used inside separated test module.\n */\npublic class CostomRobolectricTestRunner extends RobolectricTestRunner {\n\n    public CostomRobolectricTestRunner(Class<?> testClass) throws InitializationError {\n        super(testClass);\n\n        // provide UncaughtExceptionHandler to avoid nullponter exception if error on thread occur\n        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {\n            @Override\n            public void uncaughtException(Thread t, Throwable e) {\n                throw new RuntimeException(e);\n            }\n        });\n\n        String buildVariant = (BuildConfig.FLAVOR.isEmpty() ? \"\" : BuildConfig.FLAVOR + \"/\") + BuildConfig.BUILD_TYPE;\n        String intermediatesPath = BuildConfig.MODULE_PATH + \"/build//intermediates\";\n\n        System.setProperty(\"android.package\", BuildConfig.APPLICATION_ID);\n        System.setProperty(\"android.manifest\", intermediatesPath + \"/manifests/full/\" + buildVariant + \"/AndroidManifest.xml\");\n        System.setProperty(\"android.resources\", intermediatesPath + \"/res/merged/\" + buildVariant);\n        System.setProperty(\"android.assets\", intermediatesPath + \"/assets/\" + buildVariant);\n        System.setProperty(\"java.io.tmpdir\", intermediatesPath + \"/test-data\");\n        mkdir(intermediatesPath + \"/test-data\");\n    }\n\n    private void mkdir(String path) {\n        File file = new File(path);\n        if (!file.exists()) {\n            assertThat(file.mkdir()).isTrue();\n        }\n    }\n\n    /**\n     * Declare custom classes to be shadowed when shadow exist.\n     */\n    public InstrumentationConfiguration createClassLoaderConfig() {\n        InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder();\n        builder.addInstrumentedClass(BackgroundExecutor.class.getName());\n        return builder.build();\n    }\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/robolectric/RoboButton.java",
    "content": "package com.example.project.robolectric;\n\nimport android.app.Activity;\nimport android.widget.Button;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class RoboButton {\n\n    Button button;\n\n    public RoboButton(Activity activity, int resourceId) {\n        button = (Button) activity.findViewById(resourceId);\n    }\n\n    public void click() {\n        assertThat(button.performClick()).isTrue();\n    }\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/robolectric/RoboListView.java",
    "content": "package com.example.project.robolectric;\n\nimport android.app.Activity;\nimport android.widget.ListView;\n\nimport org.robolectric.Shadows;\n\npublic class RoboListView {\n\n    ListView listView;\n\n    public RoboListView(Activity activity, int resourceId) {\n        listView = (ListView) activity.findViewById(resourceId);\n    }\n\n    public int count() {\n        Shadows.shadowOf(listView).populateItems();\n        return listView.getCount();\n    }\n\n    public RoboListViewEntry entry(int pos) {\n        Shadows.shadowOf(listView).populateItems();\n        return new RoboListViewEntry(listView, listView.getChildAt(pos));\n    }\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/robolectric/RoboListViewEntry.java",
    "content": "package com.example.project.robolectric;\n\nimport android.view.View;\nimport android.widget.ListView;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class RoboListViewEntry {\n\n    private ListView listView;\n    private View listViewEntry;\n\n    public RoboListViewEntry(ListView listView, View listViewEntry) {\n        this.listView = listView;\n        this.listViewEntry = listViewEntry;\n    }\n\n    public void click() {\n        assertThat(listView.performItemClick(null, listView.getPositionForView(listViewEntry), 0)).isTrue();\n    }\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/robolectric/RoboTextEdit.java",
    "content": "package com.example.project.robolectric;\n\nimport android.app.Activity;\nimport android.widget.EditText;\n\npublic class RoboTextEdit {\n\n    EditText editText;\n\n    public RoboTextEdit(Activity activity, int resourceId) {\n        editText = (EditText) activity.findViewById(resourceId);\n    }\n\n    public void insert(String text) {\n        editText.setText(text);\n    }\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/robolectric/ShadowBackgroundExecutor.java",
    "content": "package com.example.project.robolectric;\n\nimport org.androidannotations.api.BackgroundExecutor;\nimport org.assertj.core.util.Strings;\nimport org.robolectric.Robolectric;\nimport org.robolectric.annotation.Implementation;\nimport org.robolectric.annotation.Implements;\nimport org.robolectric.util.Scheduler;\n\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Ensure synchronous execution of android annotations background tasks.\n * <p/>\n * Robolectric is designed to execute all background tasks synced to avoid flaky tests. Current\n * it miss support for android annotations so this class will do the job.\n * <p/>\n * Additional the shadow tries to simulate the behaviour of android annotations cancelable tasks.\n * But real interrupt feature is not supported because there is no async with robolectric tests.\n */\n@Implements(BackgroundExecutor.class)\npublic class ShadowBackgroundExecutor {\n\n    static Map<String, Runnable> cancelableTasks = new HashMap<>();\n\n    @Implementation\n    public static synchronized void execute(final BackgroundExecutor.Task task) {\n        String taskId = extractTaskId(task);\n\n        if (Strings.isNullOrEmpty(taskId)) {\n            Robolectric.getBackgroundThreadScheduler().post(task);\n        } else {\n            Runnable taskWrapper = wrapAsCancelableTask(task, taskId);\n            Robolectric.getBackgroundThreadScheduler().post(taskWrapper);\n        }\n    }\n\n    /**\n     * Stop the run of queued background cancelableTasks.\n     * <p/>\n     * To use it you must stop automatic background task execution with\n     * {@link }Robolectric#getBackgroundthreadScheduler()} and pause it {@link Scheduler#pause()}\n     */\n    public static synchronized void cancelAll(String id, boolean mayInterruptIfRunning) {\n        Runnable runnable = cancelableTasks.remove(id);\n        Robolectric.getBackgroundThreadScheduler().remove(runnable);\n    }\n\n    private static Runnable wrapAsCancelableTask(final BackgroundExecutor.Task task, String taskId) {\n        final String fTaskId = taskId;\n        Runnable taskWrapper = new Runnable() {\n            @Override\n            public void run() {\n                task.run();\n                cancelableTasks.remove(fTaskId);\n            }\n        };\n        cancelableTasks.put(fTaskId, taskWrapper);\n        return taskWrapper;\n    }\n\n    private static String extractTaskId(BackgroundExecutor.Task task) {\n        try {\n            Field privateStringField = BackgroundExecutor.Task.class.getDeclaredField(\"id\");\n            privateStringField.setAccessible(true);\n            return (String) privateStringField.get(task);\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n}"
  },
  {
    "path": "appCt/src/test/java/com/example/project/testdata/TestContactData.java",
    "content": "package com.example.project.testdata;\n\nimport com.example.project.database.provider.contact.ContactContentValues;\nimport com.example.project.database.contact.ContactDb;\nimport com.example.project.database.contact.ContactDb_;\n\nimport org.robolectric.RuntimeEnvironment;\n\nimport java.util.Date;\n\npublic class TestContactData {\n\n    public static void createRandomeContacts(int count) {\n        for (int i = 0; i < count; i++) {\n            ContactContentValues contactContentValues = new ContactContentValues();\n            contactContentValues.putFirstName(\"Max \" + i);\n            contactContentValues.putLastName(\"Muster\");\n            contactContentValues.putBirthdate(new Date());\n\n            ContactDb contactDb = ContactDb_.getInstance_(RuntimeEnvironment.application);\n            contactDb.insert(contactContentValues);\n        }\n    }\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/views/contac_list/ContactListSpec.java",
    "content": "package com.example.project.views.contac_list;\n\nimport android.content.Intent;\n\nimport com.example.project.RobolectricTestCase;\nimport com.example.project.business.contact.CreateContactFunction_;\nimport com.example.project.testdata.TestContactData;\nimport com.example.project.views.contact_details.DetailActivity_;\nimport com.example.project.views.contact_edit.EditActivity_;\nimport com.github.tomakehurst.wiremock.http.Fault;\n\nimport org.junit.Test;\nimport org.robolectric.shadows.ShadowToast;\n\nimport java.util.Date;\n\nimport static com.github.tomakehurst.wiremock.client.WireMock.aResponse;\nimport static com.github.tomakehurst.wiremock.client.WireMock.get;\nimport static com.github.tomakehurst.wiremock.client.WireMock.stubFor;\nimport static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;\nimport static org.assertj.android.api.Assertions.assertThat;\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class ContactListSpec extends RobolectricTestCase {\n\n    RoboContactListPage roboContactListPage = new RoboContactListPage();\n\n    @Test\n    public void showContactDetails() {\n        givenPageHasContacts();\n        whenClickListItem();\n        thenDetailsAreShownInNewPage();\n    }\n\n    @Test\n    public void openCreateContact() {\n        givenPageWithoutContacts();\n        whenClickCreateContact();\n        thenCreateNewContactIsShownInNewPage();\n    }\n\n    @Test\n    public void refreshContactListOnNewContact() {\n        givenPageWithoutContacts();\n        whenInsertNewContact();\n        thenPageHasContacts();\n    }\n\n    @Test\n    public void syncContacts() {\n        givenPageWithoutContacts();\n        whenClickSyncContact();\n        thenPageHasContacts();\n        thenToastWasShown(\"Sync done\");\n    }\n\n    @Test\n    public void syncContactsFail() {\n        givenContactsRequestAnswerWithError(500);\n        givenPageWithoutContacts();\n        whenClickSyncContact();\n        thenToastWasShown(\"Sync failed: 500 Internal Server Error\");\n    }\n\n    @Test\n    public void syncContactsWithConnectionLost() {\n        givenContactsRequestAnswerWithFault(Fault.RANDOM_DATA_THEN_CLOSE);\n        givenPageWithoutContacts();\n        whenClickSyncContact();\n        thenToastWasShown(\"Sync failed: Unknown status code [-1] null\");\n    }\n\n    private void givenContactsRequestAnswerWithFault(Fault fault) {\n        stubFor(get(urlEqualTo(\"/contacts\")).willReturn(aResponse().withFault(fault)));\n    }\n\n    private void givenContactsRequestAnswerWithError(int statusCode) {\n        stubFor(get(urlEqualTo(\"/contacts\")).willReturn(aResponse().withStatus(statusCode)));\n    }\n\n    private void thenToastWasShown(String expectedMessage) {\n        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(expectedMessage);\n    }\n\n    private void whenClickSyncContact() {\n        roboContactListPage.syncContacts().click();\n    }\n\n    private void thenPageHasContacts() {\n        assertThat(roboContactListPage.list().count()).isPositive();\n    }\n\n    private void whenInsertNewContact() {\n        CreateContactFunction_.getInstance_(context).apply(\"A\", \"B\", new Date());\n    }\n\n    private void thenCreateNewContactIsShownInNewPage() {\n        Intent intent = roboContactListPage.nextStartedActivity();\n        assertThat(intent).hasComponent(context, EditActivity_.class);\n        assertThat(intent.getLongExtra(EditActivity_.CONTACT_ID_EXTRA, 0)).isZero();\n    }\n\n    private void whenClickCreateContact() {\n        roboContactListPage.createContact().click();\n    }\n\n    private void whenClickListItem() {\n        roboContactListPage.list().entry(0).click();\n    }\n\n    private void thenDetailsAreShownInNewPage() {\n        Intent intent = roboContactListPage.nextStartedActivity();\n        assertThat(intent).hasComponent(context, DetailActivity_.class);\n    }\n\n    private void givenPageWithoutContacts() {\n        roboContactListPage.startPage();\n        assertThat(roboContactListPage.list().count()).isZero();\n    }\n\n    private void givenPageHasContacts() {\n        TestContactData.createRandomeContacts(3);\n        roboContactListPage.startPage();\n        assertThat(roboContactListPage.list().count()).isPositive();\n    }\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/views/contac_list/RoboContactListPage.java",
    "content": "package com.example.project.views.contac_list;\n\nimport android.content.Intent;\n\nimport com.example.project.R;\nimport com.example.project.robolectric.RoboListView;\nimport com.example.project.views.contact_list.ContactListActivity;\nimport com.example.project.views.contact_list.ContactListActivity_;\n\nimport org.robolectric.Robolectric;\nimport org.robolectric.Shadows;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class RoboContactListPage {\n\n    ContactListActivity contactListActivity;\n\n    public void startPage() {\n        contactListActivity = Robolectric.setupActivity(ContactListActivity_.class);\n    }\n\n    public RoboListView list() {\n        return new RoboListView(contactListActivity, R.id.listView);\n    }\n\n    public Menu createContact() {\n        return new Menu(R.id.action_add_contact);\n    }\n\n    public Menu syncContacts() {\n        return new Menu(R.id.action_sync_contacts);\n    }\n\n    public Intent nextStartedActivity() {\n        return Shadows.shadowOf(contactListActivity).getNextStartedActivity();\n    }\n\n    public class Menu {\n        private int resourceId;\n\n        public Menu(int resourceId) {\n            this.resourceId = resourceId;\n        }\n\n        public void click() {\n            assertThat(Shadows.shadowOf(contactListActivity).clickMenuItem(resourceId)).isTrue();\n        }\n    }\n}"
  },
  {
    "path": "appCt/src/test/java/com/example/project/views/contact_details/ContactDetailSpec.java",
    "content": "package com.example.project.views.contact_details;\n\nimport com.example.project.RobolectricTestCase;\n\nimport org.junit.Ignore;\n\n@Ignore\npublic class ContactDetailSpec extends RobolectricTestCase {\n\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/views/contact_edit/ContactCreateSpec.java",
    "content": "package com.example.project.views.contact_edit;\n\nimport com.example.project.database.contact.ContactDb_;\nimport com.example.project.database.provider.contact.ContactCursor;\nimport com.example.project.RobolectricTestCase;\n\nimport org.junit.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\nimport static org.assertj.android.api.Assertions.assertThat;\n\npublic class ContactCreateSpec extends RobolectricTestCase {\n\n    RoboContactEditPage contactEditPage = new RoboContactEditPage();\n\n    @Test\n    public void testShouldCreateContact() {\n        givenDatabaseHasNoContacts();\n        whenCreateContact();\n        thenCreateContactViewIsClosed();\n        thenDatabaseHasContacts(1);\n    }\n\n    private void thenDatabaseHasContacts(int expectedCount) {\n        ContactCursor contactCursor = ContactDb_.getInstance_(context).queryAll();\n        assertThat(contactCursor).hasCount(expectedCount);\n    }\n\n    private void thenCreateContactViewIsClosed() {\n        assertThat(contactEditPage.editActivity.isFinishing()).isTrue();\n    }\n\n    private void whenCreateContact() {\n        contactEditPage.startPage();\n        contactEditPage.firstName().insert(\"My First Name\");\n        contactEditPage.lastName().insert(\"My Last Name\");\n        contactEditPage.birthDate().insert(\"1984-11-11\");\n        contactEditPage.confirm().click();\n    }\n\n    private void givenDatabaseHasNoContacts() {\n        ContactCursor contactCursor = ContactDb_.getInstance_(context).queryAll();\n        assertThat(contactCursor).hasCount(0);\n    }\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/views/contact_edit/ContactEditSpec.java",
    "content": "package com.example.project.views.contact_edit;\n\nimport com.example.project.RobolectricTestCase;\n\nimport org.junit.Ignore;\n\n@Ignore\npublic class ContactEditSpec extends RobolectricTestCase {\n\n}\n"
  },
  {
    "path": "appCt/src/test/java/com/example/project/views/contact_edit/RoboContactEditPage.java",
    "content": "package com.example.project.views.contact_edit;\n\nimport com.example.project.R;\nimport com.example.project.robolectric.RoboButton;\nimport com.example.project.robolectric.RoboTextEdit;\n\nimport org.robolectric.Robolectric;\n\npublic class RoboContactEditPage {\n    EditActivity editActivity;\n\n    public void startPage() {\n        editActivity = Robolectric.setupActivity(EditActivity_.class);\n    }\n\n    public RoboTextEdit firstName() {\n        return new RoboTextEdit(editActivity, R.id.first_name);\n    }\n\n    public RoboTextEdit lastName() {\n        return new RoboTextEdit(editActivity, R.id.last_name);\n    }\n\n    public RoboTextEdit birthDate() {\n        return new RoboTextEdit(editActivity, R.id.birth_date);\n    }\n\n    public RoboButton confirm() {\n        return new RoboButton(editActivity, R.id.confirm);\n    }\n}\n"
  },
  {
    "path": "appIt/build.gradle",
    "content": "apply plugin: 'com.android.test'\n\nandroid {\n    compileSdkVersion projectAndroidVersion\n    buildToolsVersion projectAndroidBuildToolsVersion\n\n    defaultConfig {\n        // minimal should be same from app module\n        minSdkVersion projectAndroidMinVersion\n        testApplicationId 'com.example.project.test'\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n\n    buildTypes {\n        debug {\n            // support code coverage for the integration tests\n            testCoverageEnabled = true\n        }\n    }\n\n    jacoco {\n        //noinspection GroovyAssignabilityCheck\n        version projectJacocoVersion\n    }\n\n    targetProjectPath ':app'\n    targetVariant 'debug'\n    \n    dexOptions {\n        if(isCi) {\n            // CircleCi allow max 4G memory for all processes together and dex does exceed it\n            // with his parallel execution. Shrink the javaMaxHeapSize does it only per dex process\n            // but the combination exceed the max memory and to less value let it run for long time.\n            // javaMaxHeapSize \"1024M\"\n\n            // Speed up build for CI by ignoring extra build steps which should speed up build for developers.\n            // Also reduce memory usage by avoiding multiple (pre) dex processes.\n            incremental false\n            preDexLibraries = false\n        }\n    }\n}\n\ndependencies {\n    // force dependencies to use the same support-annotations version (must be same from app)\n    compile \"com.android.support:support-annotations:$projectAndroidSupportToolsVersion\"\n\n    // fluent assertion support and android specific assertions\n    compile 'com.squareup.assertj:assertj-android:1.1.0'\n\n    // espresso support\n    compile 'com.android.support.test.espresso:espresso-core:2.2'\n    compile 'com.android.support.test:runner:0.3'\n}\n"
  },
  {
    "path": "appIt/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.example.project.test\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@android:drawable/sym_def_app_icon\" />\n\n    <!-- Specify runner and target application package -->\n    <instrumentation\n        android:name=\"android.support.test.runner.AndroidJUnitRunner\"\n        android:targetPackage=\"com.example.project\" />\n\n</manifest>\n"
  },
  {
    "path": "appIt/src/main/java/com/example/project/EspressoTestCase.java",
    "content": "package com.example.project;\n\nimport android.app.Activity;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.espresso.Espresso;\nimport android.support.test.rule.ActivityTestRule;\nimport android.support.test.runner.AndroidJUnit4;\nimport android.view.WindowManager;\n\nimport com.example.project.database.provider.address.AddressSelection;\nimport com.example.project.database.provider.contact.ContactSelection;\nimport com.example.project.views.common.AppIdlingResources;\nimport com.example.project.views.common.AppIdlingResources_;\n\nimport org.junit.Before;\nimport org.junit.Rule;\nimport org.junit.runner.RunWith;\n\nimport java.lang.reflect.ParameterizedType;\n\n@RunWith(AndroidJUnit4.class)\npublic abstract class EspressoTestCase<A extends Activity> {\n\n    @Rule\n    public ActivityTestRule<A> activityRule = new ActivityTestRule<>(getGenericActivityClass());\n\n    @Before\n    public void setupEspresso() {\n        Espresso.registerIdlingResources(AppIdlingResources_.getInstance_(InstrumentationRegistry.getContext()).getIdlingResource());\n\n        clearDatabase();\n        avoidLockScreen();\n    }\n\n    private void clearDatabase() {\n        new ContactSelection().delete(InstrumentationRegistry.getContext().getContentResolver());\n        new AddressSelection().delete(InstrumentationRegistry.getContext().getContentResolver());\n    }\n\n    private void avoidLockScreen() {\n        // sometimes tests failed on emulator, following approach should avoid it\n        // http://stackoverflow.com/questions/22737476/false-positives-junit-framework-assertionfailederror-edittext-is-not-found\n        // http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_SHOW_WHEN_LOCKED\n        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {\n            @Override\n            public void run() {\n                Activity activity = activityRule.getActivity();\n                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);\n                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);\n                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);\n                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);\n            }\n        });\n    }\n\n    private Class<A> getGenericActivityClass() {\n        //noinspection unchecked\n        return ((Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);\n    }\n}\n"
  },
  {
    "path": "appIt/src/main/java/com/example/project/espresso/CurrentActivity.java",
    "content": "package com.example.project.espresso;\n\nimport android.app.Activity;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.espresso.core.deps.guava.collect.Iterables;\nimport android.support.test.rule.ActivityTestRule;\nimport android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;\nimport android.support.test.runner.lifecycle.Stage;\n\npublic class CurrentActivity {\n\n    @SuppressWarnings(\"unchecked\")\n    public static <A extends Activity> A get() {\n        InstrumentationRegistry.getInstrumentation().waitForIdleSync();\n        final Activity[] activity = new Activity[1];\n        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {\n            @Override\n            public void run() {\n                java.util.Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);\n                activity[0] = Iterables.getOnlyElement(activities);\n            }\n        });\n        return (A) activity[0];\n    }\n}\n"
  },
  {
    "path": "appIt/src/main/java/com/example/project/espresso/EspButton.java",
    "content": "package com.example.project.espresso;\n\nimport android.support.test.espresso.action.ViewActions;\n\nimport static android.support.test.espresso.Espresso.onView;\nimport static android.support.test.espresso.matcher.ViewMatchers.withId;\n\npublic class EspButton<P> {\n\n    private int resourceId;\n\n    public EspButton(int resourceId) {\n        this.resourceId = resourceId;\n    }\n\n    public P click() {\n        onView(withId(resourceId)).perform(ViewActions.click());\n        return null;\n    }\n}\n"
  },
  {
    "path": "appIt/src/main/java/com/example/project/espresso/EspListView.java",
    "content": "package com.example.project.espresso;\n\nimport android.view.View;\nimport android.widget.ListView;\n\nimport org.hamcrest.Description;\nimport org.hamcrest.TypeSafeMatcher;\n\nimport static android.support.test.espresso.Espresso.onView;\nimport static android.support.test.espresso.assertion.ViewAssertions.matches;\nimport static android.support.test.espresso.matcher.ViewMatchers.withId;\n\npublic class EspListView {\n    private int resourceId;\n\n    public EspListView(int resourceId) {\n        this.resourceId = resourceId;\n    }\n\n    public int count() {\n        final int[] counts = new int[1];\n        onView(withId(resourceId)).check(matches(new TypeSafeMatcher<View>() {\n            @Override\n            public boolean matchesSafely(View view) {\n                ListView listView = (ListView) view;\n                counts[0] = listView.getCount();\n                return true;\n            }\n\n            @Override\n            public void describeTo(Description description) {\n            }\n        }));\n        return counts[0];\n    }\n}\n"
  },
  {
    "path": "appIt/src/main/java/com/example/project/espresso/EspMenuItem.java",
    "content": "package com.example.project.espresso;\n\nimport android.support.test.espresso.action.ViewActions;\n\nimport static android.support.test.espresso.Espresso.onView;\nimport static android.support.test.espresso.matcher.ViewMatchers.withId;\n\npublic class EspMenuItem<P> {\n\n    int resourceId;\n\n    public EspMenuItem(int resourceId) {\n        this.resourceId = resourceId;\n    }\n\n    public P click() {\n        onView(withId(resourceId)).perform(ViewActions.click());\n        return null;\n    }\n}\n"
  },
  {
    "path": "appIt/src/main/java/com/example/project/espresso/EspTextEdit.java",
    "content": "package com.example.project.espresso;\n\nimport static android.support.test.espresso.Espresso.onView;\nimport static android.support.test.espresso.action.ViewActions.typeText;\nimport static android.support.test.espresso.matcher.ViewMatchers.withId;\n\npublic class EspTextEdit {\n\n    int resourceId;\n\n    public EspTextEdit(int resourceId) {\n        this.resourceId = resourceId;\n    }\n\n    public void insert(String text) {\n        onView(withId(resourceId)).perform(typeText(text));\n    }\n}\n"
  },
  {
    "path": "appIt/src/main/java/com/example/project/pages/EspContactListPage.java",
    "content": "package com.example.project.pages;\n\nimport com.example.project.R;\nimport com.example.project.espresso.EspListView;\nimport com.example.project.espresso.EspMenuItem;\n\npublic class EspContactListPage {\n\n    public EspMenuItem<EspEditContactPage> createContact() {\n        return new EspMenuItem<EspEditContactPage>(R.id.action_add_contact) {\n            @Override\n            public EspEditContactPage click() {\n                super.click();\n                return new EspEditContactPage();\n            }\n        };\n    }\n\n    public EspMenuItem<EspContactListPage> syncContacts() {\n        return new EspMenuItem<EspContactListPage>(R.id.action_sync_contacts) {\n            @Override\n            public EspContactListPage click() {\n                super.click();\n                return EspContactListPage.this;\n            }\n        };\n    }\n\n    public EspListView contactList() {\n        return new EspListView(R.id.listView);\n    }\n}\n"
  },
  {
    "path": "appIt/src/main/java/com/example/project/pages/EspEditContactPage.java",
    "content": "package com.example.project.pages;\n\nimport com.example.project.R;\nimport com.example.project.espresso.EspButton;\nimport com.example.project.espresso.EspTextEdit;\n\npublic class EspEditContactPage {\n\n    public EspTextEdit firstName() {\n        return new EspTextEdit(R.id.first_name);\n    }\n\n    public EspTextEdit lastName() {\n        return new EspTextEdit(R.id.last_name);\n    }\n\n    public EspButton<EspContactListPage> confirm() {\n        return new EspButton<EspContactListPage>(R.id.confirm) {\n            @Override\n            public EspContactListPage click() {\n                super.click();\n                return new EspContactListPage();\n            }\n        };\n    }\n\n    public EspTextEdit birthDate() {\n        return new EspTextEdit(R.id.birth_date);\n    }\n}\n"
  },
  {
    "path": "appIt/src/main/java/com/example/project/test/CreateContactTest.java",
    "content": "package com.example.project.test;\n\nimport com.example.project.EspressoTestCase;\nimport com.example.project.pages.EspContactListPage;\nimport com.example.project.pages.EspEditContactPage;\nimport com.example.project.views.contact_list.ContactListActivity_;\n\nimport org.junit.Test;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class CreateContactTest extends EspressoTestCase<ContactListActivity_> {\n\n    EspContactListPage contactListPage = new EspContactListPage();\n\n    @Test\n    public void testCreateNewContact() {\n        givenListHasNoContacts();\n        whenAddContact();\n        thenListHasContacts();\n    }\n\n    private void thenListHasContacts() {\n        assertThat(contactListPage.contactList().count()).isPositive();\n    }\n\n    private void whenAddContact() {\n        EspEditContactPage editContactPage = contactListPage.createContact().click();\n        editContactPage.firstName().insert(\"My First Name\");\n        editContactPage.lastName().insert(\"My Last Name\");\n        editContactPage.birthDate().insert(\"1984-11-11\");\n        contactListPage =  editContactPage.confirm().click();\n    }\n\n    private void givenListHasNoContacts() {\n        assertThat(contactListPage.contactList().count()).isZero();\n    }\n}\n"
  },
  {
    "path": "appIt/src/main/java/com/example/project/test/SyncContactsTest.java",
    "content": "package com.example.project.test;\n\nimport com.example.project.EspressoTestCase;\nimport com.example.project.pages.EspContactListPage;\nimport com.example.project.pages.EspEditContactPage;\nimport com.example.project.views.contact_list.ContactListActivity_;\n\nimport org.junit.Test;\n\nimport static android.support.test.espresso.Espresso.onView;\nimport static android.support.test.espresso.assertion.ViewAssertions.matches;\nimport static android.support.test.espresso.matcher.RootMatchers.withDecorView;\nimport static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;\nimport static android.support.test.espresso.matcher.ViewMatchers.withText;\nimport static org.hamcrest.Matchers.is;\nimport static org.hamcrest.Matchers.not;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\npublic class SyncContactsTest extends EspressoTestCase<ContactListActivity_> {\n\n    EspContactListPage contactListPage = new EspContactListPage();\n\n    @Test\n    public void testSyncContacts() {\n        givenListHasNoContacts();\n        whenSyncContacts();\n\n        onView(withText(\"Sync done\")).inRoot(withDecorView(not(is(activityRule.getActivity().getWindow().getDecorView())))).check(matches(isDisplayed()));\n\n        thenListHasContacts();\n    }\n\n    private void thenListHasContacts() {\n        assertThat(contactListPage.contactList().count()).isPositive();\n    }\n\n    private void whenSyncContacts() {\n        contactListPage.syncContacts().click();\n    }\n\n    private void givenListHasNoContacts() {\n        assertThat(contactListPage.contactList().count()).isZero();\n    }\n}\n"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:1.3.0'\n\n        // plugin for reporting code coverage to coveralls\n        classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.4.0'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\n// set flag whether we are on a build server\next.isCi = (\"true\".equals(System.getenv(\"TRAVIS\")) || \"true\".equals(System.getenv(\"CIRCLECI\")))\n\n// current robolectric has no support for android M (v23) https://github.com/robolectric/robolectric/issues/1865\next.projectAndroidVersion = 22\n\n// latest supported version by google playstore app is v8 (august 2015)\n// latest supported version by joda time library is v10\next.projectAndroidMinVersion = 10\n\n// sometimes support tools and build tools have same version but support tools version grow faster with time\n// current robolectric has no support for android M (v23) stuff\next.projectAndroidBuildToolsVersion = \"22.0.1\"\next.projectAndroidSupportToolsVersion = \"22.2.1\"\n\n// not all jacoco versions work without issues\n// TODO try which is the latest working version without issues, with 0.7.5 is saw some\next.projectJacocoVersion = \"0.7.0.201403182114\"\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\n// ensure clean is also triggered for root build folder\napply plugin: 'java'\n\n// support to see all reports on one page\napply plugin: 'build-dashboard'\nbuildDashboard {\n    reports.html.destination = \"build/\"\n}\nbuildDashboard << {\n    println file(\"build/index.html\").absolutePath\n}\n\n// just clean up dashboard from not generated reports\ntest.reports.html.enabled = false\ntest.reports.junitXml.enabled = false\n\n// support combined test code coverage for all levels (unit, component, integration)\napply from: \"build.jacoco-test-report.gradle\"\n"
  },
  {
    "path": "build.jacoco-test-report.gradle",
    "content": "apply plugin: \"jacoco\"\napply plugin: 'com.github.kt3k.coveralls'\n\njacoco {\n    toolVersion = projectJacocoVersion\n}\n\ntask configureCoverageReport {\n    doFirst {\n        def includeAppSrc = false;\n        def includeCoreSrc = false;\n        def includeDatabaseSrc = false;\n        def coverageFiles = []\n        def coverageSourceDirs = []\n\n        // exclude generated classes from code coverage report because not all generated methods will be used\n        def defaultExcludes = ['**/R.class', '**/R$*.class', '**/BuildConfig.class' // generated by android\n                               , '**/*_*' // generated by androidannotaions\n                               , '**/*InjectAdapter.class', '**/*ModuleAdapter*.class' // generated by dagger\n                               , '**/database/provider/*' // generated database handling\n                               ]\n\n        // Don't take not existing coverage report files or the report will be empty\n\n        def currentCoverageFile = 'app/build/jacoco/testDebugUnitTest.exec'\n        if (file(currentCoverageFile).exists()) {\n            println \"found app unit test coverage\"\n            includeAppSrc = true;\n            coverageFiles += currentCoverageFile\n        }\n        currentCoverageFile = 'appIt/build/outputs/code-coverage/connected/coverage.ec'\n        if (file(currentCoverageFile).exists()) {\n            println \"found app integration test coverage\"\n            includeAppSrc = true;\n            coverageFiles += currentCoverageFile\n        }\n        currentCoverageFile = 'appCt/build/jacoco/testDebug.exec'\n        if (file(currentCoverageFile).exists()) {\n            println \"found app component test coverage\"\n            includeAppSrc = true;\n            coverageFiles += currentCoverageFile\n        }\n\n        // Don't include classes from modules we haven't executed\n        if (includeAppSrc) {\n            coverageSourceDirs += 'app/src/main/java'\n            tasks.jacocoTestReport.classDirectories += fileTree(dir: 'app/build/intermediates/classes/debug', excludes: defaultExcludes)\n        }\n\n        tasks.jacocoTestReport.additionalSourceDirs = files(coverageSourceDirs)\n        tasks.jacocoTestReport.executionData = files(coverageFiles)\n\n\n        // Send code coverage report to coveralls with coveralls-gradle-plugin. To get the plugin working\n        // we need to include the coverageSourceDirs as main sources. But this conflicts with android\n        // studio and also with jacocoTestReport task.\n        coveralls {\n            if (isCi) { // avoid android studio source root conflicts\n                sourceSets.main.java.srcDirs += coverageSourceDirs\n            }\n        }\n    }\n}\n\ncompileJava.enabled = false\n\ntasks.jacocoTestReport.dependsOn tasks.configureCoverageReport\ntasks.coveralls.dependsOn tasks.configureCoverageReport\n\njacocoTestReport {\n    reports {\n        xml.enabled = true\n        html.enabled = true\n    }\n}"
  },
  {
    "path": "circle.yml",
    "content": "machine:\n  java:\n    # latest wiremock version needs java 8\n    version: oraclejdk8\n  environment:\n    # auth for the coveralls report\n    COVERALLS_REPO_TOKEN: mHJjy4h8zt9RIIBKg8sBosF5JkKsFk139\n\n    # chooce network device for tests with wiremock support and emulator\n    TEST_MOCK_IFACE: eth0\n\ntest:\n  pre:\n  # emulator startup need some minutes that's why start it before first build/test steps for build speed up\n    - emulator -avd circleci-android22 -no-audio -no-window:\n        background: true\n        parallel: true\n\n  override:\n    # Build the code\n    - ./gradlew app:assembleDebug\n\n    # Execute Unit Tests\n    - ./gradlew app:test\n\n    # start wiremock to support tests with network communication\n    - tools/src/main/resources/start-wiremock.sh:\n          # start at background to use wiremock in next build steps\n          background: true\n\n    # Execute Component Tests\n    - ./gradlew appCt:test\n\n    # Check lint hints\n    - ./gradlew app:lint\n\n    # Build instrumented test code\n    # fix apk not build https://code.google.com/p/android/issues/detail?id=180689\n    - ./gradlew appIt:assembleDebug\n\n    # ensure that the emulator is ready to use\n    - circle-android wait-for-boot\n    # the necessary sleep duration may change with time and depends on the pre tasks length.\n    # When all pre tasks are run long enough then waiting will not be necessary anymore.\n    # This sleep should avoid the com.android.builder.testing.api.DeviceException: com.android.ddmlib.ShellCommandUnresponsiveException\n    - sleep 60\n    # at least remove the look screen\n    - adb shell input keyevent 82\n\n    # later we collect the logs from test run\n    - adb logcat -d\n\n    # execute tests on emulator\n    - ./gradlew appIt:connectedCheck\n\n    # Create coverage report\n    - ./gradlew jacocoTestReport\n\n    # copy test results\n    - mv app/build/reports/tests/debug $CIRCLE_TEST_REPORTS/AppUnitTests\n    - mv appCt/build/test-report $CIRCLE_TEST_REPORTS/ComponentTests\n    - mv appIt/build/reports/androidTests/connected $CIRCLE_TEST_REPORTS/AndroidTests\n    - mv build/reports/jacoco/test/html $CIRCLE_TEST_REPORTS/CodeCoverageReport\n\n    # copy lint report\n    - mkdir $CIRCLE_TEST_REPORTS/Lint\n    - mv app/build/outputs/lint-results_files $CIRCLE_TEST_REPORTS/Lint\n    - mv app/build/outputs/lint-results.html $CIRCLE_TEST_REPORTS/Lint/lint-app-results.html\n\n    # circleCi proper test value feature\n    - mkdir $CIRCLE_TEST_REPORTS/junit\n    - find */build/test-results -name \"*.xml\" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \\;\n    - find */build/outputs/androidTest-results/ -name \"*.xml\" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \\;\n\n    # collect logs from emulator\n    - adb logcat -d > $CIRCLE_ARTIFACTS/logcat_emulator.txt\n\n# Only executed if all tasks are successful\ndeployment:\n\n  # report coverage to coveralls\n  coverage:\n    branch: [master, rewrite]\n    commands:\n    - ./gradlew coveralls"
  },
  {
    "path": "docs/build.gradle",
    "content": "apply plugin: \"java\""
  },
  {
    "path": "docs/src/main/resources/adjust_project_to_your_needs.md",
    "content": "[Back to Index](index.md)\n\n# Adjust the project to your needs\n\nStart by cloning the project `git clone https://github.com/nenick/android-gradle-template.git myAppName` and navigate into it `cd myAppName`.\n\n### Create fresh git history\n\nRemove the git folder `rm -rf .git` and create a new history by `git init`.\n\nYou can connect it with an already existing remote repository by:\n\n```\ngit remote add origin <remote_repo_url>\ngit push --all --set-upstream origin\n```\n\n### Prototyping\n\nFor fast prototyping just remove appCt, appIt, tools and docs for a clean code base.\n\n### Remove database support\n\n* clean up the app/build.gradle file from stuff which is added for [database example](database.md)\n* delete the app/src/main/java/com/example/project/database package\n* now delete or adjust other code with compile errors\n\n### Remove network support\n\n* clean up the app/build.gradle file from stuff which is added for [network example](network.md)\n* delete the app/src/main/java/com/example/project/database package\n* now delete or adjust other code with compile errors\n\n---\n\n[Back to Index](index.md)\n"
  },
  {
    "path": "docs/src/main/resources/concepts/function_class.md",
    "content": "[Back to Index](../index.md)\n\n# Function Class\n\nI don't know if this style has a name.\nI took this idea from some scala developer.\n\nThe base idea is to split code for hiding details and easy unit testing.\n\nWhenever you have a more complex class function then create a own class for it with a single public method.\nAdditional convenience methods are also possible.\n\n\n    public class TaskToDoFunction {\n        public <return value> apply(<inout values>) {\n        }\n    }\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/concepts/model_view_presenter.md",
    "content": "[Back to Index](../index.md)\n\n# Model View Presenter\n\n* [Wikipedia.org - Model View Presenter](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter)\n* [AntonioLeiva.com - MVP for Android](http://antonioleiva.com/mvp-android/)\n\nClassic approach of MVP for android is to use the activity/fragment as the view which is controlled by a presenter.\n\n## Android MVP - An Alternate Approach\n\nOriginal article <http://blog.cainwong.com/android-mvp-an-alternate-approach> (until site is back see [cached version](http://webcache.googleusercontent.com/search?q=cache:OgfVapRjNRYJ:blog.cainwong.com/android-mvp-an-alternate-approach/))\nand github project <https://github.com/wongcain/MVP-Simple-Demo>\n\n**The statement about activities and fragments as view:**\n\n*\".. Activities send Intents, start Services, create and execute FragmentTransisitons, etc. All of these complexities are, in my opinion, outside of the scope of what a \"View\" should be concerned with. A View's job is to present data and get input from the user. Ideally, a View should be devoid of business logic, making a unit test of the View unnecessary. ..\"*\n\nThis results in activities/fragments/adapter are treated as presenters and moving all view code into a separated class.\n\n## Following the alternate approach\n\nI like the idea, often I wrote boilerplate code to inform the presenter about the current life cycle.\nThis approach give you still clean separated code but faster and more intuitive development thinking.\n\nThe base for the MVP can be found at *com.example.project.view.common.mvp* for the usage see the example implementations.\n\n\nThe activity is most time only the glue between fragments.\nWhen fragments has something to show they will tell it back through a Show...Listener to the current activity.\nThe root activity may differ between portrait and landscape mode.\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/concepts/package_structure.md",
    "content": "[Back to Index](../index.md)\n\n# Package structure\n\nThe project package structure follows mainly the package by feature approach.\n\n**With strict package by feature approach it becomes hard to distinguish between business feature and view packages.**\n\nFor me I recognised that my work is mostly view and business driven so I need to find fast the related view\nor business package which need to be changed.\n\nWith pure package by layer its mostly very easy to decide where to put new classes (new Activity into package activities)\nbut for package by feature it can become complicated.\nOften you will be confronted with the problem that different features need the same classes.\nCreate new feature package for shared classes may a solution but will end in many packages\ninside one package or in a more structured way with sub packages.\nAfter this step it looks like many developer must think long time about where to put new code because\nthey can't distinguish easy between business and view logic related packages and this may result in a bad mix.\n\n*It's the nature of a layers to use many different features of the lower layer.*\n\nI recommend to use a mix of package by layer and by feature in the following way:\n\n![main package structure](http://yuml.me/a737ade0)\n\n### ..view.concrete_view\n*(replace 'concrete_view' with a describing name for your view, e.g. contact_editor.)*\n\nShows the reader all kinds of views which this application present.\nThe main entry point for UI related development.\nDon't put any business logic into view layer, presentation logic is never business logic but decision logic may be business logic.\nCan be the a full view (activity, fragment, etc) or a partial view (dialog, view group, etc).\nWhen something is changed here the changed view and depending views must be checked.\n\n### ..business.business_feature\n*(replace 'business_feature' with a describing name for your feature, e.g. contact.)*\n\nIts often that multiple views need the same business features.\nShows all the business features supported by this application.\nThe main entry point for business related development.\nWhen something is changed here the changed business feature must checked with the related views.\n\n### ..database.table\n*(replace 'table' with a describing name for your table, e.g. contact.)*\n\nIts often that multiple business features access the same database tables.\nWhen something is changed here there must be a migration script and the database version must be increased.\nThe app update process should be tested for data issues and all related business features.\nContent should not change often like other do. The most parts of this package content may be generated.\n\n### ..network.api\n*(replace 'api' with a describing name for your used api, e.g. facebook.)*\n\nIts not often that two business feature use the same network calls but sometimes they do.\nWhen something is changed here the interaction with real services must be tested and all related business features.\nContent should not change often like other do. The most parts of this package content may be generated.\n\n## Some articles about the package topic\n\n* [CodingTheArchitecture.com - Package by component and architecturally-aligned testing](http://www.codingthearchitecture.com/2015/03/08/package_by_component_and_architecturally_aligned_testing.html\n* [Oracle.com - Naming a Package](https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html\n* [JavaPractices.com - Package by feature, not layer](http://www.javapractices.com/topic/TopicAction.do?Id=205\n* [StackOverflow.com - What strategy do you use for package naming in Java projects and why?](http://stackoverflow.com/questions/533102/what-strategy-do-you-use-for-package-naming-in-java-projects-and-why\n\n## Additional suggestions\n\n### ..view.common.stuff\n*(replace 'stuff' with a describing name for your , e.g. contact.)*\n\nPut here basic stuff used by different views.\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/concepts/project_structure.md",
    "content": "[Back to Index](../index.md)\n\n# Project structure\n\n### app - Application\n\ncontains the app with views, business logic, etc ...\nChecks the details of each unit.\nA unit is the smallest meaningful part of a app.\n\n\n### appCt - Component Tests\n\nTests which will check the integration of different units.\nMost high level logic is proved here.\n\n### appDt - Device Tests\n\nRuns the app on device/emulator to check that all work in a real environment.\n\n### Modules which could be simple folders\n\n*Some modules only are modules instead of simple folders to support the Android Project View. Without they would not be visible.*\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/concepts/testing.md",
    "content": "[Back to Index](../index.md)\n\n# Testing Strategies\n\n## Unit Tests\n\nCheck that your code work technically in isolation like you expected it.\nYour have the choice between different unit tests variants.\n\n**Android Unit Tests** (Historical this was the first existing possibility for unit tests)\n\nThis is the most realistic testing by deploy and run your code on device/emulator.\nIs also the slowest approach because of the device/emulator deployment time.\n\n**Robolectric Unit Tests** (Historical this was the second existing possibility for unit tests)\n\nYou can run tests at JVM but have access functional android code. You will have less issues with\nandroid code compared to pure unit tests and faster then deploy an apk on device/emulator.\n\n**Pure Java Unit Tests** (since android gradle plugin 1.1.0)\n\nThe fastest and most known style of unit testing,\n\n**Its your choice**\n\nI prefer a mix of pure unit tests and robolectric supported unit tests. Whenever possible write\nunit test without robolectric this give you the fastest development cycle (TDD).\n\n## Component Tests\n\nCheck that units work together in combination with database, network, android services, business logic, views, etc...\n\nSome guys say Robolectric is just for unit testing but you can also do your main integration tests.\nTest execution is up to 20x faster than on device/emulator with espresso.\nBut not all android features are supported or must first be configured to your needs.\n\n## Integration Tests\n\nAt least check that your app does run on device.\nAgain you can choose between different approaches, see <http://testdroid.com/tech/top-5-android-testing-frameworks-with-examples>.\nOne concept may be to navigate through each page and feature and take a screenshot.\nAfter each runs you can compare the layout and style to look same the effort. This can be improved with automatic image compare.\n\n\nMy favourite is Espresso because it is the tool with most stable and has fastest test execution.\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/getting_started.md",
    "content": "[Back to Index](index.md)\n\n# Getting Started\n\n## Start Wiremock\n\nWithout the example app sync process will fail.\n\nExecute from project root\n\n* Linux/Mac `tools/src/main/resources/start-wiremock.sh`\n* Windows `java -jar wiremock\\wiremock-1.57-standalone.jar --port 1337 --https-port 1338 --verbose --root-dir 'wiremock\\src\\main\\resources'`\n\nThe app get your current ip at compile time and then try to connect to your wiremock instance.\n\n## Start from commandline\n\nStart an emulator or connect with device.\nThen on commandline navigate into the project root and execute from there following script and check that all works.\n\n* Linux/Mac `tools/src/main/resources/test-all-with-coverage.sh`\n* Windows `tools\\src\\main\\resources\\test-all-with-coverage.bat`\n\n#### Gradle Commands\n\n**unit tests:** `./gradlew app:test`\n\n* append `app:jacocoTestReport` for coverage report\n\n**component tests:** `./gradlew appCt:test`\n\n* append `appCt:jacocoTestReport` for coverage report\n\n**acceptance tests:** `./gradlew appIt:connectedAndroidTest` *(Use `connectedCheck` until bug closed <https://code.google.com/p/android/issues/detail?id=183936>)*\n\n* replace by `appIt:connectedCheck` for coverage report\n\n**combined coverage report:** `./gradlew jacocoTestReport` after you run all tests\n\n\n## Start with Android Studio\n\nImport project into Android Studio.\n\n#### Build Variants settings\n\nChange the build variants test artifact type to unit tests.\nSince we can use a test module for instrumentation tests we don't need to switch between them anymore.\n\n#### Android Studio - Espresso\n\nWhen you are on `Test Artifact: Unit Tests` then you don't get the possibility to start instrumented tests.\nSwitch to `Test Artifact: Instrumentation Tests` and then start/create test run configuration.\nLater this created configuration can still be used when you are on `Test Artifact: Unit Tests` without changing it.\n\nI hope this behavior can be adjusted so that the test module only support instrumented tests and we need no more to switch the test artifact type <https://code.google.com/p/android/issues/detail?id=183931>\n\n#### Android Project View\n\nOn the left top about your project structure you can switch between different project content views.\nI like the minimal Android View, but at project view you can see more files.\nSwitch there to you preferred style.\n\n*Some modules only are modules instead of simple folders to support the Android Project View. Without they would not be visible.*\n\n---\n\n[Back to Index](index.md)"
  },
  {
    "path": "docs/src/main/resources/index.md",
    "content": "[Back to Project](https://github.com/nenick/android-gradle-template)\n\n# Template explanation\n\n## Some basis information\n\n* [Getting Start](getting_started.md)\n* [Adjust Project to your needs](adjust_project_to_your_needs.md)\n\n## Concepts explanation\n\n* [MVP Pattern](concepts/model_view_presenter.md)\n* [Project Structure](concepts/project_structure.md)\n* [Package Structure](concepts/package_structure.md)\n* [Function classes](concepts/function_class.md)\n* [How and what to Test](concepts/testing.md)\n\n## Used tools\n\n* Generate Database Handling [ContentProvider Generator](tools/android_contentprovider_generator.md)\n* Generate Android Boilerplate Code [AndroidAnnotations](tools/androidannotations.md)\n* Tests with [Espresso](tools/espresso.md)\n* Tests with [Espresso tests in own module](tools/espresso_test_module.md)\n* Fluent Assertions [Fest Assertions](tools/fest_assertions.md)\n* Code Coverage report [Coveralls](tools/coveralls.md)\n* Code Coverage report [Jacoco](tools/jacoco.md)\n* Better Time Handling [Joda TimeDate](tools/joda_timedate.md)\n* Generate Json Mapping [Json](tools/jsonschema2pojo.md)\n* Test with robolectric [Robolectric](tools/robolectric.md)\n* Test with robolectric [Robolectric tests in own module](tools/robolectric_test_module.md)\n* Mock REST Services [Wiremock](tools/wiremock.md)\n\n---\n\n[Back to Project](https://github.com/nenick/android-gradle-template)"
  },
  {
    "path": "docs/src/main/resources/tools/android_contentprovider_generator.md",
    "content": "[Back to Index](../index.md)\n\n# Android ContentProvider Generator\n\nCreate tool for generating all necessary database files.\n\n* Table classes with constants\n* ContentProvider implementation\n* CursorWrapper\n* Hook for database updates\n* and many more ...\n\n## Info\n\n* [Project](https://github.com/BoD/android-contentprovider-generator)\n\nCurrent there is an important bug with joins and ids <https://github.com/BoD/android-contentprovider-generator/issues/86>.\nTo avoid this issue you can give a specific projection.\n\n    private final String[] ALL_JOINED_COLUMNS = (String[]) ArrayUtils.addAll(\n                            AddressColumns.ALL_COLUMNS,\n                            ContactColumns.ALL_COLUMNS);\n\n    // multi join example\n    private final String[] ALL_JOINED_COLUMNS = (String[]) ArrayUtils.addAll(\n                            ArrayUtils.addAll(\n                                AddressColumns.ALL_COLUMNS,\n                                ContactColumns.ALL_COLUMNS),\n                            MoreColumns.ALL_COLUMNS);\n\nThe ArrayUtils comes with *compile 'commons-lang:commons-lang:2.6'*\n\n## Add Android ContentProvider Generator to your project\n\nAdd the following snippet to your build.gradle file:\n\n    // this block must be above the first plugin line\n    plugins {\n        id \"de.undercouch.download\" version \"1.2\"\n    }\n\n    // this block can be at the end of the build.gradle or in a separate file\n    def dbSchemaPath = \"src/main/json/database/schema\"\n    def dbClassesPath = \"src/gen/java\"\n    android.sourceSets.main.java.srcDirs += dbClassesPath\n    android.sourceSets.main.java.srcDirs += \"src/main/json\"\n\n    task generateDatabaseFiles << {\n        def generatorVersion = \"1.9.2\"\n\n        # download android contentprovider generator\n        if (!file(\"$buildDir/android_contentprovider_generator-${generatorVersion}-bundle.jar\").exists()) {\n            download {\n                src \"https://github.com/BoD/android-contentprovider-generator/releases/download/v${generatorVersion}/android_contentprovider_generator-${generatorVersion}-bundle.jar\"\n                dest buildDir\n            }\n        }\n\n        # delete last generated files\n        file(dbClassesPath).deleteDir()\n\n        # execute the generator\n        exec {\n            executable \"java\"\n            args = [\"-jar\", \"$buildDir/android_contentprovider_generator-${generatorVersion}-bundle.jar\", \"-i\", dbSchemaPath, \"-o\", dbClassesPath]\n        }\n    }\n\nThis snippet add the new task **generateDatabaseFiles** to you gradle tasks.\nThis new Task reads the schema files from $dbSchemaPath and write them to $dbClassesPath.\n\nAfter the generation you will get a hint how to register your new database provider at AndroidManifest.xml\n\n    <application>\n        <provider\n            android:name=\"com.example.project.database.provider.ExampleProvider\"\n            android:authorities=\"com.example.project.database.provider\"\n            android:exported=\"false\" />\n     </application>\n\n### subclass for dependency injection\n\n    @EBean\n    public class ExampleDbProvider extends ExampleProvider {\n    }\n\n### Move SQLiteOpenHelper Callbacks\n\nBy default this class would not be overwritten but with some custom changes to the generation process it does.\nBest is to move it to src/main/java instead of src/gen/java within the same package to keep custom callback implementations.\nAfter each you must delete\n\n---\n\n[Back to Index](../index.md)\n"
  },
  {
    "path": "docs/src/main/resources/tools/androidannotations.md",
    "content": "[Back to Index](../index.md)\n\n# AndroidAnnotations\n\nI decided me for androidannotations instead of dagger, butterknife and co because it just fit perfectly into all my need.\n\n* dependency injection\n* view injection\n* view event\n* background / ui thread\n* REST\n* and many more\n\n## Infos\n\n* [Documentation](https://github.com/excilys/androidannotations/wiki)\n* [Available Annotations](https://github.com/excilys/androidannotations/wiki/AvailableAnnotations)\n* [Latest Release Version](https://github.com/excilys/androidannotations/releases)\n\n## Add AndroidAnnotations to your project\n\nThey have a create documentation so read <https://github.com/excilys/androidannotations/wiki/Building-Project-Gradle>\n\nMore is not necessary, all code generation is automatically be done by a build.\n\nShort overview:\n\n* **buildscript:** classpath 'com.neenbedankt.gradle.plugins:android-apt:1.7'\n* **apply plugin:** 'com.neenbedankt.android-apt'\n* **add config:**\n    apt {\n        arguments {\n            androidManifestFile variant.outputs[0].processResources.manifestFile\n        }\n    }\n* **dependency:** apt \"org.androidannotations:androidannotations:3.3.2\"\n* **dependency:** compile \"org.androidannotations:androidannotations-api:3.3.2\"\n\nWhen you don't use the http support then you must adjust your proguard config to avoid proguard issues.\n-dontwarn org.androidannotations.api.rest.*\n\n## REST Support\n\nAndorid Annotations use Spring for network communication <http://projects.spring.io/spring-android/>\nlatest version <https://maven-repository.com/artifact/org.springframework.android/spring-android-rest-template>\n\n* **dependency:** (optional) compile spring\nhttps://github.com/excilys/androidannotations/wiki/Rest-API\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/tools/circleci.md",
    "content": "[Back to Index](../index.md)\n\n# Circle CI\n\nFor my continues integration I prefer Circle CI because of nice separation of each build step and a way to collect build results.\n\n## emulator\n\nThe emulator is not ready after it is started, it just need one minute more after the script  `circle-android wait-for-boot` report ready.\nAnd its not guaranted that the lock screen is disabled `adb shell input keyevent 82`\n\n## Max memory\n\npreDex use mutiple dex instances which in cobnation fast exceed the 4G memory limit.\n\n## collecting build artifacts\n\ncopy all what you like to the $CIRCLE_TEST_REPORTS location to see them later like the reason why a test has failed.\n\n## proper test value\n\ncircle ci offers possibility to read and show the tests results on a nice screen when you provide\ntest result xml files into $CIRCLE_TEST_REPORTS/junit\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/tools/coveralls.md",
    "content": "[Back to Index](../index.md)\n\n# Cloud Service to host code coverage reports\n\nclasspath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.4.0'\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/tools/espresso.md",
    "content": "[Back to Index](../index.md)\n\nGetting startes wiki: https://code.google.com/p/android-test-kit/wiki/EspressoSetupInstructions\n\nResolve issue http://stackoverflow.com/questions/28999124/resolved-versions-for-app-22-0-0-and-test-app-21-0-3-differ\n\n### insert text issue\n\nhttp://stackoverflow.com/questions/20436968/espresso-typetext-not-working\n\n### Idling Resources to avoid sleep/wait/flaky\n\ncompile 'com.android.support.test.espresso:espresso-contrib:2.2'\n\nsee CountingIdlingResource\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/tools/espresso_test_module.md",
    "content": "[Back to Index](../index.md)\n\nmodule under test need to publish variants: publishNonDefault true\n\nInitial need dummy AndroidManifest.xml at src/main\n\nbase build.gradle\n\n    apply plugin: 'com.android.test'\n\n    android {\n        compileSdkVersion 22\n        buildToolsVersion \"22.0.1\"\n\n        defaultConfig {\n            minSdkVersion 8\n        }\n\n        targetProjectPath ':app'\n        targetVariant 'debug'\n    }\n\n### APK not build issue\n\nworkaround is to call https://code.google.com/p/android/issues/detail?id=180689\n\n---\n\n[Back to Index](../index.md)\n"
  },
  {
    "path": "docs/src/main/resources/tools/fest_assertions.md",
    "content": "[Back to Index](../index.md)\n\n# Fluent Assertion with Android Support\n\nI prefer the fluent style because you must not think so much.\nJust use the smart code completion by pressing \".\" and select what to check.\n\n## Android Support\n\nThe assertJ-android provides extra some checks for android elements like `assertThat( textField ).hasText( \"expected text\" )`\n\n## Setup\n\nAdd to your test dependencies `'com.squareup.assertj:assertj-android:1.1.0'` and use `assertThat( actual ).isEqualTo( expected )` instead of `assertThat( actual, is( expected ))`\n\nImport both assertThat methods to use automatic the correct one.\n\n    import static org.assertj.android.api.Assertions.assertThat;\n    import static org.assertj.core.api.Assertions.assertThat;\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/tools/jacoco.md",
    "content": "[Back to Index](../index.md)\n\n# Jacoco unit tests\n\nsimple unit tests in app module and robolectric supported\n\napply plugin: \"jacoco\"\n\nadd custom jacocoTestReport task (see app/build-jacoco-test-report.gradle)\n\nresult at: app/build/reports/jacoco/index.html\n\n# jacoco component tests\n\napply plugin: \"jacoco\"\n\nto get a report adjust some properties (see appCt/build-jacoco-test-report.gradle)\n\nresult at: appCt/build/reports/jacoco/test/html/com.example.project/index.html\n\n# jacoco integration tests\n\nenable them and use connectedCheck instead of connectedAndroidTest\n\n    buildTypes {\n        debug {\n            testCoverageEnabled = true\n        }\n    }\n\nresults at: result at: appCt/build/reports/jacoco/test/html/com.example.project/index.html\n\n# combined coverage report\n\nsee projectRoot/build-jacoco-test-report.gradle\n\n# Jacoco Version\n\nlooks like some version does no work with android. The version \"0.7.0.201403182114\" looks good.\n\n# Replace AndroidAnnotation with Dagger and ButterKnife\n\n* clean up the app/build.gradle file from stuff which is added for [AndroidAnnotations](tools/androidannotations.md)\n* add dagger and butterknife to the app/build.gradle\n* replace all annotations\n* for jacoco code coverage you will need the following workaround to avoid issues with the generated $$ classes\n\n\n    task jacocoReport(type: JacocoReport) {\n        doFirst {\n            applyDaggerWorkaround('app/build/intermediates/classes/')\n        }\n        // avoid some side effects through revert renaming\n        doLast {\n            revertDaggerWorkaround('app/build/intermediates/classes/')\n        }\n    }\n\n    def applyDaggerWorkaround(String pathWithDaggerClasses) {\n        def filePath = new File(pathWithDaggerClasses)\n        if (filePath.exists()) {\n            filePath.eachFileRecurse { file ->\n                if (file.name.contains('$$')) {\n                    file.renameTo(file.path.replace('$$', '$'))\n                }\n            }\n        }\n    }\n\n    def revertDaggerWorkaround(String pathWithDaggerClasses) {\n        def filePath = new File(pathWithDaggerClasses)\n        if (filePath.exists()) {\n            filePath.eachFileRecurse { file ->\n                if (file.name.contains('$ModuleAdapter')) {\n                    file.renameTo(file.path.replace('$ModuleAdapter', '$$ModuleAdapter'))\n                }\n            }\n        }\n    }\n\n---\n\n[Back to Index](../index.md)\n"
  },
  {
    "path": "docs/src/main/resources/tools/joda_timedate.md",
    "content": "[Back to Index](../index.md)\n\nhttp://stackoverflow.com/questions/5059663/android-java-joda-date-is-slow\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/tools/jsonschema2pojo.md",
    "content": "[Back to Index](../index.md)\n\nhttps://github.com/joelittlejohn/jsonschema2pojo\nhttps://github.com/joelittlejohn/jsonschema2pojo/wiki/Reference\nhttps://github.com/joelittlejohn/jsonschema2pojo/tree/master/jsonschema2pojo-gradle-plugin\n\nclasspath 'org.jsonschema2pojo:jsonschema2pojo-gradle-plugin:0.4.14'\n\napply plugin: 'jsonschema2pojo'\n\n// Required if generating equals, hashCode, or toString methods\n    compile 'commons-lang:commons-lang:3.4'\n    compile 'com.fasterxml.jackson.core:jackson-databind:2.6.1'\n\njsonSchema2Pojo {\n    source = files(\"${project.rootDir}/json/network/schema\")\n    targetDirectory = file(\"${project.rootDir}/src/gen/java\")\n    targetPackage = 'com.example.project.network'\n    useCommonsLang3 = true\n}\n\nhttps://github.com/joelittlejohn/jsonschema2pojo/blob/37a98588312679391f7e660962a8d40de3c826b5/jsonschema2pojo-gradle-plugin/example/android/app/build.gradle\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/tools/robolectric.md",
    "content": "[Back to Index](../index.md)\n\n# Robolectric\n\nIs a create tool for testing your app inside jvm insdead to deploy it on a device or emulator.\n\n## Add Robolectric to your project\n\nThey have getting started site <http://robolectric.org/getting-started/> and some sample projects at <https://github.com/robolectric/robolectric-samples>.\nSome more basic examples can be found at <https://github.com/nenick/AndroidStudioAndRobolectric>\n\nShort overview:\n\n* dependency testCompile 'org.robolectric:robolectric:3.0'\n* use @RunWith(RobolectricGradleTestRunner.class)\n* use @Config(constants = BuildConfig.class, sdk = 21)\n\n### Base class for tests\n\nInstead of adding the annotations every time to you test class you can use a base test.\n\nAdding following snippet to your base class make writing tests more convenient.\n\n    protected Context context;\n\n    @Before\n    public void roboSetup() {\n        context = RuntimeEnvironment.application;\n    }\n\n### Reset Singletons\n\nYou will get strange behavior when you forget to reset your tests. Most times you will get them when you use a database in your tests.\n\n    @After\n    public void finishRobolectricTest() {\n        resetSingleton(ExampleSQLiteOpenHelper.class, \"sInstance\");\n    }\n\n    private void resetSingleton(Class clazz, String fieldName) {\n        java.lang.reflect.Field instance;\n        try {\n            instance = clazz.getDeclaredField(fieldName);\n            instance.setAccessible(true);\n            instance.set(null, null);\n        } catch (Exception e) {\n            throw new RuntimeException();\n        }\n    }\n\n### Use extra shadow modules\n\nList of available extra modules <http://robolectric.org/using-add-on-modules/>\n\nFor apps using classes from v4 support must add *testCompile 'org.robolectric:shadows-support-v4:3.0'* or it may result in unstable tests.\n\n### debugging with shadows\n\nThey may a bit confuse when you try to debug.\n\nWhen you see are in RobolectricInternals#methodInvoked(...) then use step out to reach the expected method.\n\nWhen you reach ShadowWrangler#ShadowMethodPlan#run then step over until *return shadowMethod.invoke(shadow, params);*\nand then step into then you reach the shadowed method and can debug there.\n\n### Create shadows for non android classes\n\nRegister a class which could be shadowed (android classes can be shadowed without extra registration)\n\n    class CustomRobolectricTestRunner {\n        public InstrumentationConfiguration createClassLoaderConfig() {\n            InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder();\n            builder.addInstrumentedClass(MyClass.class.getName());\n            return builder.build();\n        }\n    }\n\nRegister a Shadow for the class\n\n    @Config(constants = BuildConfig.class, sdk = 21, shadows = {ShadowMyClass.class})\n    class RobolectricTestCase {}\n\nMore informations at <http://robolectric.org/custom-shadows/>\n\n### Avoid jumping virtual desktops\n\nI detected this behaviour just on mac os. Every time i run robolectric tests at IDE or on command line it was jumping to another desktop.\n\nOn command line you can avoid it with `export JAVA_TOOL_OPTIONS='-Djava.awt.headless=true'`\n\nIn your IDE set as VM option in your run configuration `-Djava.awt.headless=true`\n\n---\n\nSee also\n\n* [Testing Concept](../concepts/testing.md)\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/tools/robolectric_test_module.md",
    "content": "[Back to Index](../index.md)\n\n# gradle-android-test-plugin\n\nMove some of the robolectric supported tests into an own module to separate simple units from component tests.\n\nFor Robolectric basics see also [Robolectrc](robolectric.md)\n\n### avoid release builds for test runs, and conflict between lint and test runs\n\n** check if issue is gone**\n\n    afterEvaluate {\n\n        def isLintRun = false\n        def isTestRun = false\n\n        gradle.startParameter.taskNames.each {\n            if (it.contains(\"lint\")) {\n                isLintRun = true\n            }\n            if (it.contains(\"test\")) {\n                isTestRun = true\n            }\n        }\n\n        if (isLintRun && isTestRun) {\n            println \"WARNING: tests for release type are disabled for supporting jacoco\"\n            println \"WARNING: run test and lint at same time is not supported\"\n            exit 1\n        }\n\n        if (isTestRun) {\n            tasks.each {\n                if (it.name.contains(\"Release\")) {\n                    it.enabled = false\n                }\n            }\n        }\n    }\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "docs/src/main/resources/tools/wiremock.md",
    "content": "[Back to Index](../index.md)\n\n# Mocking REST Service\n\nhttp://wiremock.org/running-standalone.html\n\n### NoSuchMethodError on Java 7\n\nLatest Wiremock versions needs Java 8. For Java 7 we need older wiremock version. Or you will see errors like:\n\n    ava.lang.NoSuchMethodError: java.util.concurrent.ConcurrentHashMap.keySet()Ljava/util/concurrent/ConcurrentHashMap$KeySetView;\n        at com.github.tomakehurst.wiremock.global.ThreadSafeRequestDelayControl.cancelAllDelays(ThreadSafeRequestDelayControl.java:51)\n        at com.github.tomakehurst.wiremock.global.ThreadSafeRequestDelayControl.clearDelay(ThreadSafeRequestDelayControl.java:38)\n        at com.github.tomakehurst.wiremock.core.WireMockApp.resetMappings(WireMockApp.java:141)\n        at com.github.tomakehurst.wiremock.core.WireMockApp.resetToDefaultMappings(WireMockApp.java:151)\n        at com.github.tomakehurst.wiremock.admin.ResetToDefaultMappingsTask.execute(ResetToDefaultMappingsTask.java:26)\n        at com.github.tomakehurst.wiremock.http.AdminRequestHandler.handleRequest(AdminRequestHandler.java:55)\n        at com.github.tomakehurst.wiremock.http.AbstractRequestHandler.handle(AbstractRequestHandler.java:38)\n        at com.github.tomakehurst.wiremock.jetty6.Jetty6HandlerDispatchingServlet.service(Jetty6HandlerDispatchingServlet.java:98)\n\n---\n\n[Back to Index](../index.md)"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Sun Aug 16 11:19:08 CEST 2015\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.6-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched.\nif $cygwin ; then\n    [ -n \"$JAVA_HOME\" ] && JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\nfi\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >&-\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >&-\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windowz variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\ngoto execute\r\n\r\n:4NT_args\r\n@rem Get arguments from the 4NT Shell from JP Software\r\nset CMD_LINE_ARGS=%$\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "readme.md",
    "content": "# Android - Rapid Test Driven Development\n\n* Combine tools to generate most of the boilerplate code.\n* Examples how to test different aspects of an android application.\n* Clean architecture approach with MVP and package by feature.\n\nFor details see [Project Documentations](docs/src/main/resources/index.md)\n\n**Wishes, improvements, questions and discussions about the stuff here are welcome.**\n\n[![Circle CI](https://circleci.com/gh/nenick/android-gradle-template.svg?style=shield)](https://circleci.com/gh/nenick/android-gradle-template) [![Coverage Status](https://coveralls.io/repos/nenick/android-gradle-template/badge.svg?branch=master)](https://coveralls.io/r/nenick/android-gradle-template?branch=master)\n\n### Last successful tests with\n\n* Android Studio 1.3.2\n* Gradle Build Tools 1.3.0\n* Gradle 2.6\n* Android v22\n* Java 8\n\n### Getting Started\n\nImport the project into Android Studio and start developing. For more details see [Getting Started](docs/src/main/resources/getting_started.md)\n\n"
  },
  {
    "path": "settings.gradle",
    "content": "include 'app', 'appCt', 'appIt'\ninclude 'wiremock', 'docs', 'tools'\n"
  },
  {
    "path": "tools/build.gradle",
    "content": "apply plugin: \"java\""
  },
  {
    "path": "tools/src/main/resources/rename-packages(in development).sh",
    "content": "#!/bin/bash\n\n#\n# Change easy the base package to your needs\n#\n\nfunction printUsage {\n    echo \"\"\n    echo \"Failed: Start script from the project root folder with target package name.\"\n    echo \"> sh scripts/src/main/resources/rename-packages.sh \\\"my.target.name\\\" \"\n    echo \"\"\n}\n\ninitial_base_package=\"com.example.project\"\n\nif [ -z \"$1\" ]; then\n    echo \"Error: Started without target base package.\"\n    printUsage\n    exit 1\nfi\n\nif !([ -d app ]); then\n    echo \"Error: Not started from project root because folder app not found.\"\n    printUsage\n    exit 1\nfi\n\n# rename folders\n\n# change files content"
  },
  {
    "path": "tools/src/main/resources/start-wiremock.sh",
    "content": "#!/bin/bash\n\nfunction killCurrentWiremockInstance {\n\n\n    [ $(ps aux | grep -v grep | grep -c \"wiremock.*standalone\") -gt 0 ] && \\\n        kill -9 $(ps aux | grep -v grep | grep \"wiremock.*standalone\" | awk 'NR==1{print $2}') || \\\n        echo \"No wiremock found to kill\"\n}\n\nkillCurrentWiremockInstance\n\nif [ \"$1\" != \"kill\" ]; then\n    java -jar wiremock/wiremock-1.57-standalone.jar --port 1337 --https-port 1338 --verbose --root-dir 'wiremock/src/main/resources' &\nelse\n    echo \"only kill servers\"\nfi"
  },
  {
    "path": "tools/src/main/resources/test-all-with-coverage.bat",
    "content": "gradlew.bat clean app:test appCt:test appIt:assembleDebug appIt:connectedCheck jacocoTestReport"
  },
  {
    "path": "tools/src/main/resources/test-all-with-coverage.sh",
    "content": "./gradlew clean app:test appCt:test appIt:assembleDebug appIt:connectedCheck jacocoTestReport"
  },
  {
    "path": "wiremock/build.gradle",
    "content": "apply plugin: \"java\""
  },
  {
    "path": "wiremock/src/main/resources/__files/contacts-get.json",
    "content": "{\n  \"contacts\": [\n    {\n      \"id\": \"k345lbhjt5er\",\n      \"firstName\": \"Max\",\n      \"lastName\": \"FromServer\",\n      \"birthDate\": \"1984-11-11\",\n      \"lastModification\" : \"2345678\"\n    },\n    {\n      \"id\": \"v4cn478cn8bz7\",\n      \"firstName\": \"Susi\",\n      \"lastName\": \"FromServer\",\n      \"birthDate\": \"1984-11-11\",\n      \"lastModification\" : \"2345678\"\n    }\n  ]\n}"
  },
  {
    "path": "wiremock/src/main/resources/mappings/contcts-delete.json",
    "content": "{\n  \"request\": {\n    \"method\": \"DELETE\",\n    \"urlPattern\": \"/contacts/.*\"\n  },\n  \"response\": {\n    \"status\": 204\n  }\n}"
  },
  {
    "path": "wiremock/src/main/resources/mappings/contcts-get.json",
    "content": "{\n  \"request\": {\n    \"method\": \"GET\",\n    \"url\": \"/contacts\"\n  },\n  \"response\": {\n    \"status\": 200,\n    \"bodyFileName\": \"/contacts-get.json\",\n    \"headers\": {\n      \"Content-Type\": \"application/json;charset=UTF-8\"\n    }\n  }\n}"
  },
  {
    "path": "wiremock/src/main/resources/mappings/contcts-post.json",
    "content": "{\n  \"request\": {\n    \"method\": \"POST\",\n    \"url\": \"/contacts\"\n  },\n  \"response\": {\n    \"status\": 201\n  }\n}"
  },
  {
    "path": "wiremock/src/main/resources/mappings/contcts-put.json",
    "content": "{\n  \"request\": {\n    \"method\": \"PUT\",\n    \"urlPattern\": \"/contacts/.*\"\n  },\n  \"response\": {\n    \"status\": 204\n  }\n}"
  }
]