[
  {
    "path": ".gitignore",
    "content": "# Created by https://www.gitignore.io/api/android,intellij,gradle\n\n### Android ###\n# Built application files\n*.apk\n*.ap_\n\n# Files for the Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\n\n# Gradle files\n.gradle/\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Log Files\n*.log\n\n# Android Studio Navigation editor temp files\n.navigation/\n\n### Android Patch ###\ngen-external-apklibs\n\n\n### Intellij ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio\n\n*.iml\n\n## Directory-based project format:\n.idea/\n# if you remove the above rule, at least ignore the following:\n\n# User-specific stuff:\n# .idea/workspace.xml\n# .idea/tasks.xml\n# .idea/dictionaries\n\n# Sensitive or high-churn files:\n# .idea/dataSources.ids\n# .idea/dataSources.xml\n# .idea/sqlDataSources.xml\n# .idea/dynamic.xml\n# .idea/uiDesigner.xml\n\n# Gradle:\n# .idea/gradle.xml\n# .idea/libraries\n\n# Mongo Explorer plugin:\n# .idea/mongoSettings.xml\n\n## File-based project format:\n*.ipr\n*.iws\n\n## Plugin-specific files:\n\n# IntelliJ\n/out/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\n\n\n### Gradle ###\n.gradle\nbuild/\n\n# Ignore Gradle GUI config\ngradle-app.setting\n\n# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)\n!gradle-wrapper.jar\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: android\njdk: oraclejdk8\nandroid:\n  components:\n    - tools\n    - build-tools-27.0.3\n    - android-27\n    - extra-android-support\n    - extra-android-m2repository\n  licenses:\n    - 'android-sdk-preview-license-52d11cd2'\n    - 'android-sdk-license-.+'\n    - 'google-gdk-license-.+'\nbefore_install:\n  - yes | sdkmanager \"platforms;android-27\"\ncache:\n  directories:\n    - $HOME/.gradle/caches/\n    - $HOME/.gradle/wrapper/\nbefore_cache:\n  - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock\nscript:\n  - ./gradlew --full-stacktrace -q test\n\n"
  },
  {
    "path": "LICENSE.md",
    "content": "Apache License\n\nVersion 2.0, January 2004\n\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n\"License\" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.\n\n\"Licensor\" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.\n\n\"Legal Entity\" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, \"control\" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.\n\n\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising permissions granted by this License.\n\n\"Source\" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.\n\n\"Object\" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.\n\n\"Work\" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).\n\n\"Derivative Works\" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.\n\n\"Contribution\" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, \"submitted\" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as \"Not a Contribution.\"\n\n\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:\n\nYou must give any other recipients of the Work or Derivative Works a copy of this License; and\nYou must cause any modified files to carry prominent notices stating that You changed the files; and\nYou must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and\nIf the Work includes a \"NOTICE\" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.\n\nYou may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.\n5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: HOW TO APPLY THE APACHE LICENSE TO YOUR WORK\nTo apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets \"[]\" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same \"printed page\" as the copyright notice for easier identification within third-party archives.\n\n```\nCopyright 2015 izumin5210\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```"
  },
  {
    "path": "README.md",
    "content": "# Droidux\n[![Build Status](https://travis-ci.org/izumin5210/Droidux.svg)](https://travis-ci.org/izumin5210/Droidux)\n[![Download](https://api.bintray.com/packages/izumin5210/maven/droidux/images/download.svg) ](https://bintray.com/izumin5210/maven/droidux/_latestVersion)\n[![Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/izumin5210/Droidux/blob/master/LICENSE.md)\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Droidux-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/2892)\n\nDroidux is \"predictable state container\" implementation, inspired by **[Redux][redux]**.\n\n## Features\nDroidux is influenced by [Three principles][three-principles] of Redux.\n\n> * Single source of truth\n>     - The state of your whole application is stored in an object tree inside a single store.\n> * State is read-only\n>     - The only way to mutate the state is to emit an action, an object describing what happened.\n> * Mutations are written as pure functions\n>     - To specify how the state tree is transformed by actions, you write pure reducers.\n>\n> [Three Principles | Redux][three-principles]\n\nFeatures of Droidux are following:\n\n* All mutations can be observed via Flowable from [RxJava][rxjava]\n* All mutations are automatically notified to views via [Data Binding][databinding]\n\n### Data flow\n![Droidux data flow](droidux.png)\n\nsee also: [Introduction to Redux // Speaker Deck](https://speakerdeck.com/axross/introduction-to-redux) (in Japanese)\n\n## Installation\nDroidux depends on [RxJava][rxjava] and [Data Binding][databinding].\nAdd to your project build.gradle file:\n\n```groovy\n\napply plugin: 'com.android.application'\n\ndependencies {\n  compile 'info.izumin.android:droidux:0.6.0'\n  compile 'io.reactivex.rxjava2:rxjava:2.1.8'\n  compile 'io.reactivex.rxjava2:rxandroid:2.0.1'\n  annotationProcessor 'info.izumin.android:droidux-processor:0.6.0'\n}\n```\n\nAnd also you need to setup [Data Binding][databinding].\n\nWhen you use `AsyncAction`, you need to add [droidux-thunk](https://github.com/izumin5210/Droidux/tree/master/middlewares/droidux-thunk).\n\n```groovy\ncompile 'info.izumin.android:droidux-thunk:0.3.0'\n```\n\n## Usage\n### Quick example\n\n```java\n/**\n * This is a state class.\n * It can be as simple as possible implementation, like POJO, or immutable object. \n */\npublic class Counter {\n    private final int count;\n\n    public Counter(int count) {\n        this.count = count;\n    }\n\n    public int getCount() {\n        return count;\n    }\n}\n\n/**\n * This is a reducer class.\n * It should be applied @Reducer annotation is given a state class as an argument.\n * It describe whether the reducer should handle which actions.\n */\n@Reducer(Counter.class)\npublic class CounterReducer {\n\n    /**\n     * This is a method to handle actions.\n     * It should be applied @Dispatchable annotation is given an action class as an parameter.\n     * It describe how to transform the state into the next state when dispatched actions.\n     * It should return the next state instance, and it is preferred instantiate the new state.\n     *\n     * This example handle IncrementCountAction,\n     + and it returns new counter instance that state is incremented.\n     */\n    @Dispatchable(IncrementCountAction.class)\n    public Counter increment(Counter state) {\n        return new Counter(state.getCount() + 1);\n    }\n\n    @Dispatchable(DecrementCountAction.class)\n    public Counter decrement(Counter state) {\n        return new Counter(state.getCount() - 1);\n    }\n\n    @Dispatchable(ClearCountAction.class)\n    public Counter clear() {\n        return new Counter(0);\n    }\n}\n\n\n/**\n * This is a store interface.\n * It should be applied @Store annotation and passing reducer classes as parameters.\n * Droidux generates an implementation of getter method, observe method and dispatch method from user-defined interface.\n */\n@Store(CounterReducer.class)\npublic interface CounterStore extends BaseStore {\n    Counter getCounter();\n    Flowable<Counter> observeCounter();\n}\n\n/**\n * They are action classes. They should extend Action class.\n */\npublic class IncrementCountAction implements Action {}\npublic class DecrementCountAction implements Action {}\npublic class ClearCountAction implements Action {}\n\n\n// Instantiate a Droidux store holding the state of your app.\n// Its class is generated automatically from Reducer class.\n// \n// The instantiating should use Builder class,\n// and it should register a reducer instance and an initial state.\n// \n// Its APIs in this example are following:\n// - Flowable<Action> dispatch(Action action)\n// - Flowable<Counter> observeCounter()\n// - Counter getCounter()\nCounterStore store = DroiduxCounterStore.builder()\n        .setReducer(new CounterReducer(), new Counter(0))\n        .build();                                       // Counter: 0\n\n// You can observe to the updates using RxJava interface. \nstore.observe((counter) -> Log.d(TAG, counter.toString()));\n\n// The only way to mutate the internal state is to dispatch an action.\nstore.dispatch(new IncrementCountAction()).subscribe(); // Counter: 1\nstore.dispatch(new IncrementCountAction()).subscribe(); // Counter: 2\nstore.dispatch(new IncrementCountAction()).subscribe(); // Counter: 3\n\nstore.dispatch(new DecrementCountAction()).subscribe(); // Counter: 2\n\nstore.dispatch(new ClearCountAction()).subscribe();     // Counter: 0\n```\n\n### Data Binding\n\n```java\n// If you use databinding, yor store interface must extend `android.databinding.Observable`.\n@Store(CounterReducer.class)\npublic interface CounterStore extends BaseStore, android.databinding.Observable {\n    // You should annotate the getter method with @Bindable\n    @Bindable Counter getCounter();\n}\n\nCounterStore store = DroiduxCounterStore.builder()\n        // Pass the field id generated by DataBinding annotation processor.\n        .setReducer(new CounterReducer(), new Counter(0), BR.counter)\n        .build();\n```\n\nLayout file is following:\n\n```xml\n<layout>\n    <data>\n        <variable android:name=\"store\" android:type=\"CounterStore\" />\n    </data>\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" >\n        \n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_centerInParent=\"true\"\n            android:text=\"@{store.counter}\" />\n        \n    </RelativeLayout>\n</layout>\n```\n\n\n### Combined store\n\n```java\n@Store({CounterReducer.class, TodoListReducer.class})\nclass RootStore extends BaseStore {\n    Counter getCounter();\n    Flowable<Counter> observeCounter();\n    TodoList getTodoList();\n    Flowable<TodoList> observeTodoList();\n}\n\n\nRootStore store = DroiduxRootStore.builder()\n        .setReducer(new CounterReducer(), new Counter(0))\n        .setReducer(new TodoListReducer(), new TodoList())\n        .addMiddleware(new Logger())\n        .build();\n\nstore.dispatch(new IncrementCountAction()).subscribe();     // Counter: 1, Todo: 0\nstore.dispatch(new AddTodoAction(\"new task\")).subscribe();  // Counter: 1, Todo: 1\n```\n\n### Middleware\n\n```java\nclass Logger extends Middleware<CounterStore> {\n    @Override\n    public Flowable<Action> beforeDispatch(Action action) {\n        Log.d(\"[prev counter]\", String.valueOf(getStore().count()));\n        Log.d(\"[action]\", action.getClass().getSimpleName());\n        return Flowable.just(action);\n    }\n\n    @Override\n    public Flowable<Action> afterDispatch(Action action) {\n        Log.d(\"[next counter]\", String.valueOf(getStore().count()));\n        return Flowable.just(action);\n    }\n}\n\n// Instantiate store class \nCounterStore store = DroiduxCounterStore.builder()\n        .setReducer(new CounterReducer(), new Counter(0))\n        .addMiddleware(new Logger())        // apply logger middleware\n        .build();                           // Counter: 0\n\nstore.dispatch(new IncrementCountAction()).subscribe();\n// logcat:\n// [prev counter]: 0\n// [action]: IncrementCountAction\n// [next counter]: 1\n\nstore.dispatch(new IncrementCountAction()).subscribe();\n// logcat:\n// [prev counter]: 1\n// [action]: IncrementCountAction\n// [next counter]: 2\n\nstore.dispatch(new ClearCountAction()).subscribe();\n// logcat:\n// [prev counter]: 2\n// [action]: ClearCountAction\n// [next counter]: 0\n```\n\n### Undo / Redo\n\n```java\nclass TodoList extends ArrayList<TodoList.Todo> implements UndoableState<TodoList> {\n    @Override\n    public TodoList clone() {\n        // ...\n    }\n\n    public static Todo {\n        // ...\n    }\n}\n\n@Undoable\n@Reducer(TodoList.class)\nclass TodoListReducer {\n    @Dispatchable(AddTodoAction.class)\n    public TodoList add(TodoList state, AddTodoAction action) {\n        // ...\n    }\n\n    @Dispatchable(CompleteTodoAction.class)\n    public TodoList complete(TodoList state, CompleteTodoAction action) {\n        // ...\n    }\n}\n\n@Store(TodoListReducer.class)\npublic interface TodoListStore {\n    TodoList todoList();\n    Flowable<TodoList> observeTodoList();\n}\n\nclass AddTodoAction implements Action {\n    // ...\n}\n\nclass CompleteTodoAction implements Action {\n    // ...\n}\n\n\nTodoListStore store = DroiduxTodoListStore.builder()\n        .setReducer(new TodoListReducer(), new TodoList())\n        .build();\n\nstore.dispatch(new AddTodoAction(\"item 1\")).subscribe();        // [\"item 1\"]\nstore.dispatch(new AddTodoAction(\"item 2\")).subscribe();        // [\"item 1\", \"item 2\"]\nstore.dispatch(new AddTodoAction(\"item 3\")).subscribe();        // [\"item 1\", \"item 2\", \"item 3\"]\nstore.dispatch(new CompleteTodoAction(\"item 2\")).subscribe();   // [\"item 1\", \"item 3\"]\nstore.dispatch(new AddTodoAction(\"item 4\")).subscribe();        // [\"item 1\", \"item 3\", \"item 4\"]\n\nstore.dispatch(new UndoAction(TodoList.class)).subscribe();\n// => [\"item 1\", \"item 3\"]\n\nstore.dispatch(new UndoAction(TodoList.class)).subscribe();\n// => [\"item 1\", \"item 2\", \"item 3\"]\n\nstore.dispatch(new RedoAction(TodoList.class)).subscribe();\n// => [\"item 1\", \"item 3\"]\n```\n\n### Async action\n\nUse [droidux-thunk](https://github.com/izumin5210/Droidux/tree/master/middlewares/droidux-thunk).\n\n```java\nclass FetchTodoListAction implements AsyncAction {\n    private final TodoListApi client;\n\n    public FetchTodoListAction(TodoListApi client) {\n        this.client = client;\n    }\n\n    public Flowable<ReceiveTodoListAction> call(Dispatcher dispatcher) {\n        return dispatcher.dispatch(new DoingFetchAction())\n                .flatMap(_action -> client.fetch())\n                .map(todoList -> {\n                    this.todoList = todoList;\n                    return new ReceiveTodoListAction(todoList);\n                });\n    }\n}\n\nclass ReceiveTodoListAction implements Action {\n    private final TodoList todoList;\n\n    public ReceiveTodoListAction(TodoList todoList) {\n        this.todoList = todoList;\n    }\n\n    public TodoList getTodoList() {\n        return todoList;\n    }\n}\n\n\nTodoListStore store = DroiduxTodoListStore.builder()\n        .setReducer(new TodoListReducer(), new TodoList())\n        .addMiddleware(new ThunkMiddleware())\n        .build();\n\n\nstore.dispatch(new FetchTodoListAction(client)).subscribe();\n```\n\n\n## Examples\n\n* [Counter](https://github.com/izumin5210/Droidux/tree/master/examples/counter)\n* [TodoMVC](https://github.com/izumin5210/Droidux/tree/master/examples/todomvc)\n* [Todos with Undo](https://github.com/izumin5210/Droidux/tree/master/examples/todos-with-undo)\n* [Todos with Dagger 2](https://github.com/izumin5210/Droidux/tree/master/examples/todos-with-dagger)\n\n\n## License\n\n```\nCopyright 2015 izumin5210\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n\n[redux]: https://github.com/reactjs/redux\n[rxjava]: https://github.com/ReactiveX/RxJava\n[three-principles]: http://redux.js.org/docs/introduction/ThreePrinciples.html\n[databinding]: http://developer.android.com/tools/data-binding/guide.html\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        maven { url \"https://jitpack.io\" }\n        maven {\n            url 'https://maven.google.com/'\n            name 'Google'\n        }\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.0.1'\n        classpath 'com.novoda:bintray-release:0.3.4'\n        classpath 'com.github.groovy:groovy-android-gradle-plugin:1b77dd6763'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n        google()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n\next {\n    def versionMajor = 0\n    def versionMinor = 6\n    def versionPatch = 0\n    versionName = \"${versionMajor}.${versionMinor}.${versionPatch}\"\n\n    compileSdkVersion = 27\n    buildToolsVersion = '27.0.3'\n    minSdkVersion = 15\n    targetSdkVersion = compileSdkVersion\n\n    databindingBaseLibraryVersion = '1.0'\n    databindingLibraryVersion = '1.0-rc3'\n    supportLibrariesVersion = '23.1.1'\n    rxJava2Version = '2.1.8'\n    rxAndroid2Version = '2.0.1'\n    spockCoreVersion = '1.0-groovy-2.4'\n    cglibVersion = '2.2'\n}\n"
  },
  {
    "path": "droidux/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "droidux/build.gradle",
    "content": "apply plugin: 'java'\napply plugin: 'groovy'\napply plugin: 'com.novoda.bintray-release'\n\ntargetCompatibility = JavaVersion.VERSION_1_7\nsourceCompatibility = JavaVersion.VERSION_1_7\n\ndependencies {\n    compile \"io.reactivex.rxjava2:rxjava:${project.rxJava2Version}\"\n\n    testCompile \"org.spockframework:spock-core:${project.spockCoreVersion}\"\n    testCompile \"cglib:cglib-nodep:${project.cglibVersion}\"\n}\n\npublish {\n    userOrg = project_bintray_org\n    groupId = project_group\n    artifactId = 'droidux'\n    version = project.versionName\n    description = '\"Predictable state container\" implementation, inspired by Redux for JS.'\n    website = project_url\n}\n"
  },
  {
    "path": "droidux/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 /usr/local/opt/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 android.databinding.**\n-dontwarn java.lang.invoke.*\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/Action.java",
    "content": "package info.izumin.android.droidux;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic interface Action {\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/BaseStore.java",
    "content": "package info.izumin.android.droidux;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.Single;\n\n/**\n * Created by izumin on 12/6/15.\n */\npublic interface BaseStore {\n    Flowable<Action> dispatch(Action action);\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/Dispatcher.java",
    "content": "package info.izumin.android.droidux;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.ListIterator;\n\nimport io.reactivex.Flowable;\nimport io.reactivex.functions.Consumer;\nimport io.reactivex.functions.Function;\n\n/**\n * Created by izumin on 11/28/15.\n */\npublic class Dispatcher {\n    public static final String TAG = Dispatcher.class.getSimpleName();\n\n    private final List<Middleware> middlewares;\n    private final List<StoreImpl> storeImpls;\n\n    public Dispatcher(List<Middleware> middlewares, StoreImpl... storeImpls) {\n        this.middlewares = middlewares;\n        this.storeImpls = Arrays.asList(storeImpls);\n    }\n\n    public Flowable<Action> dispatch(Action action) {\n        return Flowable.just(action)\n                .flatMap(new Function<Action, Flowable<? extends Action>>() {\n                    @Override\n                    public Flowable<? extends Action> apply(Action action) throws Exception {\n                        return applyMiddlewaresBeforeDispatch(action);\n                    }\n                }).doOnNext(new Consumer<Action>() {\n                    @Override\n                    public void accept(Action action) throws Exception {\n                        for (StoreImpl store : storeImpls) {\n                            store.dispatch(action);\n                        }\n                    }\n                })\n                .flatMap(new Function<Action, Flowable<? extends Action>>() {\n                    @Override\n                    public Flowable<? extends Action> apply(Action action) throws Exception {\n                        return applyMiddlewaresAfterDispatch(action);\n                    }\n                });\n    }\n\n    private Flowable<Action> applyMiddlewaresBeforeDispatch(Action action) {\n        Flowable<Action> o = Flowable.just(action);\n\n        for (final Middleware<?> mw : middlewares) {\n            o = o.flatMap(new Function<Action, Flowable<? extends Action>>() {\n                @Override\n                public Flowable<Action> apply(Action a) throws Exception {\n                    return mw.beforeDispatch(a);\n                }\n            });\n        }\n        return o;\n    }\n\n    private Flowable<Action> applyMiddlewaresAfterDispatch(Action action) {\n        Flowable<Action> o = Flowable.just(action);\n        ListIterator<Middleware> iterator = middlewares.listIterator(middlewares.size());\n        while(iterator.hasPrevious()) {\n            final Middleware<?> mw = iterator.previous();\n            o = o.flatMap(new Function<Action, Flowable<? extends Action>>() {\n                @Override\n                public Flowable<Action> apply(Action a) throws Exception {\n                    return mw.afterDispatch(a);\n                }\n            });\n        }\n        return o;\n    }\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/History.java",
    "content": "package info.izumin.android.droidux;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\n\n/**\n * Created by izumin on 11/23/15.\n */\npublic class History<T extends UndoableState<T>> {\n    public static final String TAG = History.class.getSimpleName();\n\n    private static final int DEFAULT_LIMIT = 100;\n\n    private final Deque<T> past;\n    private final Deque<T> future;\n    private T present;\n\n    private int limit = DEFAULT_LIMIT;\n\n    public History(T initialState) {\n        past = new ArrayDeque<>();\n        future = new ArrayDeque<>();\n        present = initialState;\n    }\n\n    public T getPresent() {\n        return present;\n    }\n\n    public void insert(T state) {\n        past.addFirst(present);\n        if (past.size() > limit) {\n            past.removeLast();\n        }\n        future.clear();\n        present = state;\n    }\n\n    public T undo() {\n        if (isUndoable()) {\n            future.addFirst(present);\n            present = past.removeFirst();\n        }\n        return present;\n    }\n\n    public T redo() {\n        if (isRedoable()) {\n            past.addFirst(present);\n            present = future.removeFirst();\n        }\n        return present;\n    }\n\n    public boolean isUndoable() {\n        return past.size() > 0;\n    }\n\n    public boolean isRedoable() {\n        return future.size() > 0;\n    }\n\n    public void setLimit(int limit) {\n        this.limit = limit;\n        while (past.size() > limit) { past.removeLast(); }\n        while (future.size() > limit) { future.removeLast(); }\n    }\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/Middleware.java",
    "content": "package info.izumin.android.droidux;\n\nimport io.reactivex.Flowable;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic abstract class Middleware<S extends BaseStore> {\n    public static final String TAG = Middleware.class.getSimpleName();\n\n    private S store;\n    private Dispatcher dispatcher;\n\n    public void onAttach(S store, Dispatcher dispatcher) {\n        this.store = store;\n        this.dispatcher = dispatcher;\n    }\n\n    protected S getStore() {\n        return store;\n    }\n\n    protected Dispatcher getDispatcher() {\n        return dispatcher;\n    }\n\n    public abstract Flowable<Action> beforeDispatch(Action action);\n    public abstract Flowable<Action> afterDispatch(Action action);\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/OnStateChangedListener.java",
    "content": "package info.izumin.android.droidux;\n\n/**\n * Created by izumin on 12/6/15.\n */\npublic interface OnStateChangedListener<T> {\n    void onStateChanged(T state);\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/StoreImpl.java",
    "content": "package info.izumin.android.droidux;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.Flowable;\nimport io.reactivex.subjects.BehaviorSubject;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic abstract class StoreImpl<T, R> {\n    public static final String TAG = StoreImpl.class.getSimpleName();\n\n    private final BehaviorSubject<T> subject;\n    private T state;\n    private final R reducer;\n    private final Set<OnStateChangedListener<T>> listeners;\n\n    protected StoreImpl(T state, R reducer) {\n        this.state = state;\n        this.reducer = reducer;\n        subject = BehaviorSubject.create();\n        listeners = new HashSet<>();\n    }\n\n    public Flowable<T> observe() {\n        return observe(BackpressureStrategy.DROP);\n    }\n\n    public Flowable<T> observe(BackpressureStrategy strategy) {\n        return subject.toFlowable(strategy);\n    }\n\n    public T getState() {\n        return state;\n    }\n\n    protected void setState(T state) {\n        this.state = state;\n        subject.onNext(state);\n        for (OnStateChangedListener<T> listener : listeners) {\n            listener.onStateChanged(state);\n        }\n    }\n\n    protected R getReducer() {\n        return reducer;\n    }\n\n    public void addListener(OnStateChangedListener<T> listener) {\n        listeners.add(listener);\n    }\n\n    protected abstract void dispatch(Action action);\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/UndoableState.java",
    "content": "package info.izumin.android.droidux;\n\n/**\n * Created by izumin on 11/24/15.\n */\npublic interface UndoableState<T> extends Cloneable {\n    T clone();\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/UndoableStoreImpl.java",
    "content": "package info.izumin.android.droidux;\n\nimport info.izumin.android.droidux.action.HistoryAction;\n\n/**\n * Created by izumin on 11/25/15.\n */\npublic abstract class UndoableStoreImpl<T extends UndoableState<T>, R> extends StoreImpl<T, R> {\n    public static final String TAG = UndoableStoreImpl.class.getSimpleName();\n\n    private final History<T> history;\n\n    protected UndoableStoreImpl(T state, R reducer) {\n        super(state, reducer);\n        history = new History<>(state);\n    }\n\n    @Override\n    protected void dispatch(Action action) {\n        if (HistoryAction.class.isAssignableFrom(action.getClass())) {\n            HistoryAction historyAction = (HistoryAction) action;\n            if (((HistoryAction) action).isAssignableTo(getReducer())) {\n                setStateWithoutKeepingHistory(historyAction.handle(history));\n            }\n        }\n    }\n\n    protected void setStateWithoutKeepingHistory(T state) {\n        super.setState(state);\n    }\n\n    @Override\n    protected void setState(T state) {\n        history.insert(state);\n        super.setState(state);\n    }\n\n    @Override\n    public T getState() {\n        return history.getPresent();\n    }\n\n    public History<T> getHistory() {\n        return history;\n    }\n\n    public boolean isUndoable() {\n        return history.isUndoable();\n    }\n\n    public boolean isRedoable() {\n        return history.isRedoable();\n    }\n\n    public void setLimit(int limit) {\n        history.setLimit(limit);\n    }\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/action/HistoryAction.java",
    "content": "package info.izumin.android.droidux.action;\n\nimport java.lang.annotation.Annotation;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport info.izumin.android.droidux.Action;\nimport info.izumin.android.droidux.History;\nimport info.izumin.android.droidux.UndoableState;\nimport info.izumin.android.droidux.annotation.Reducer;\nimport info.izumin.android.droidux.annotation.Undoable;\n\n/**\n * Created by izumin on 11/24/15.\n */\npublic class HistoryAction implements Action {\n    public static final String TAG = HistoryAction.class.getSimpleName();\n\n    enum Kind {\n        UNDO {\n            @Override\n            <T extends UndoableState<T>> T handle(History<T> history) {\n                return history.undo();\n            }\n        },\n        REDO {\n            @Override\n            <T extends UndoableState<T>> T handle(History<T> history) {\n                return history.redo();\n            }\n        };\n\n        abstract <T extends UndoableState<T>> T handle(History<T> history);\n    }\n\n    private final Kind kind;\n    private final Class targetReducerType;\n\n    public HistoryAction(Kind kind, Class targetReducerType) {\n        for (Class<? extends Annotation> annotationType : getNecessaryAnnotationTypes()) {\n            if (targetReducerType.getAnnotation(annotationType) == null) {\n                throw new IllegalArgumentException();\n            }\n        }\n        this.kind = kind;\n        this.targetReducerType = targetReducerType;\n    }\n\n    public <R> boolean isAssignableTo(R reducer) {\n        return targetReducerType.equals(reducer.getClass());\n    }\n\n    public <T extends UndoableState<T>> T handle(History<T> history) {\n        return kind.handle(history);\n    }\n\n    protected Set<Class<? extends Annotation>> getNecessaryAnnotationTypes() {\n        return new HashSet<Class<? extends Annotation>>() {{\n            add(Reducer.class);\n            add(Undoable.class);\n        }};\n    }\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/action/RedoAction.java",
    "content": "package info.izumin.android.droidux.action;\n\n/**\n * Created by izumin on 11/24/15.\n */\npublic class RedoAction extends HistoryAction {\n    public static final String TAG = RedoAction.class.getSimpleName();\n\n    public RedoAction(Class targetReducerType) {\n        super(Kind.REDO, targetReducerType);\n    }\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/action/UndoAction.java",
    "content": "package info.izumin.android.droidux.action;\n\n/**\n * Created by izumin on 11/24/15.\n */\npublic class UndoAction extends HistoryAction {\n    public static final String TAG = UndoAction.class.getSimpleName();\n\n    public UndoAction(Class targetReducerType) {\n        super(Kind.UNDO, targetReducerType);\n    }\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/annotation/Dispatchable.java",
    "content": "package info.izumin.android.droidux.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Created by izumin on 11/2/15.\n */\n@Retention(RetentionPolicy.CLASS)\n@Target(ElementType.METHOD)\npublic @interface Dispatchable {\n    Class<?> value();\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/annotation/Reducer.java",
    "content": "package info.izumin.android.droidux.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Created by izumin on 11/2/15.\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface Reducer {\n    Class<?> value();\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/annotation/Store.java",
    "content": "package info.izumin.android.droidux.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Created by izumin on 11/2/15.\n */\n@Retention(RetentionPolicy.CLASS)\n@Target(ElementType.TYPE)\npublic @interface Store {\n    Class<?>[] value() default {};\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/annotation/Undoable.java",
    "content": "package info.izumin.android.droidux.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * Created by izumin on 11/23/15.\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface Undoable {\n}\n"
  },
  {
    "path": "droidux/src/main/java/info/izumin/android/droidux/exception/NotInitializedException.java",
    "content": "package info.izumin.android.droidux.exception;\n\n/**\n * Created by izumin on 11/8/15.\n */\npublic class NotInitializedException extends RuntimeException {\n    public NotInitializedException(String message) {\n        super(message);\n    }\n}\n"
  },
  {
    "path": "droidux/src/test/groovy/info/izumin/android/droidux/DispatcherTest.groovy",
    "content": "package info.izumin.android.droidux\n\nimport io.reactivex.Flowable\nimport spock.lang.Specification\n\n/**\n * Created by izumin on 11/24/15.\n */\nclass DispatcherTest extends Specification {\n\n    def store1\n    def store2\n    def middleware1\n    def middleware2\n    def action\n    def dispatcher\n\n    def setup() {\n        store1 = Mock(StoreImpl.class, constructorArgs: [null, null])\n        store2 = Mock(StoreImpl.class, constructorArgs: [null, null])\n        middleware1 = Mock(Middleware.class)\n        middleware2 = Mock(Middleware.class)\n        action = Mock(Action.class)\n\n        def middlewares = new ArrayList<Middleware>()\n        middlewares.add(middleware1)\n        middlewares.add(middleware2)\n\n        dispatcher = new Dispatcher(middlewares, store1, store2)\n    }\n\n    def \"#dispatch()\"() {\n        when:\n        dispatcher.dispatch(action).subscribe()\n\n        then:\n        1 * middleware1.beforeDispatch(action) >> Flowable.just(action)\n\n        then:\n        1 * middleware2.beforeDispatch(action) >> Flowable.just(action)\n\n        then:\n        1 * store1.dispatch(action)\n\n        then:\n        1 * store2.dispatch(action)\n\n        then:\n        1 * middleware2.afterDispatch(action) >> Flowable.just(action)\n\n        then:\n        1 * middleware1.afterDispatch(action) >> Flowable.just(action)\n    }\n}\n"
  },
  {
    "path": "droidux/src/test/groovy/info/izumin/android/droidux/HistoryTest.groovy",
    "content": "package info.izumin.android.droidux\n\nimport spock.lang.Specification;\n\n/**\n * Created by izumin on new Counter(1)new Counter(1)/new Counter(2)new Counter(4)/new Counter(1)new Counter(5).\n */\nclass HistoryTest extends Specification {\n\n    def history\n    def past\n    def future\n\n    static class Counter implements UndoableState<Counter> {\n        def count\n\n        Counter(count) {\n            this.count = count\n        }\n\n        @Override\n        boolean equals(Object o) {\n            return (o instanceof Counter) && (o.hashCode() == hashCode())\n        }\n\n        @Override\n        int hashCode() {\n            return count\n        }\n\n        @Override\n        Counter clone() {\n            return new Counter(count)\n        }\n    }\n\n    def setup() {\n        history = new History<Counter>(new Counter(0))\n        past = History.metaClass.getAttribute(history, \"past\")\n        future = History.metaClass.getAttribute(history, \"future\")\n    }\n\n    def getPresent() {\n        History.metaClass.getAttribute(history, \"present\")\n    }\n\n    def \"#insert()\"() {\n        when:\n        history.insert(new Counter(1))\n\n        then:\n        getPresent() == new Counter(1)\n\n        when:\n        history.insert(new Counter(3))\n\n        then:\n        getPresent() == new Counter(3)\n    }\n\n    def \"#undo()\"() {\n        when:\n        history.insert(new Counter(1))\n\n        then:\n        past.size() == 1\n        history.undo() == new Counter(0)\n        past.size() == 0\n\n        when:\n        history.insert(new Counter(3))\n        history.insert(new Counter(5))\n\n        then:\n        past.size() == 2\n        history.undo() == new Counter(3)\n        past.size() == 1\n        history.undo() == new Counter(0)\n        past.size() == 0\n        history.undo() == new Counter(0)\n    }\n\n    def \"#redo()\"() {\n        when:\n        history.insert(new Counter(1))\n        history.undo()\n\n        then:\n        future.size() == 1\n        history.redo() == new Counter(1)\n        future.size() == 0\n\n        when:\n        history.insert(new Counter(3))\n        history.insert(new Counter(5))\n        history.undo()\n        history.undo()\n\n        then:\n        future.size() == 2\n        history.redo() == new Counter(3)\n        future.size() == 1\n        history.redo() == new Counter(5)\n        future.size() == 0\n        history.redo() == new Counter(5)\n\n        when:\n        history.insert(new Counter(8))\n        history.insert(new Counter(7))\n        history.undo()\n        history.undo()\n\n        then:\n        future.size() == 2\n        history.insert(new Counter(4))\n        future.size() == 0\n    }\n\n    def \"#setLimit()\"() {\n        when:\n        history.setLimit(3)\n        history.insert(new Counter(1))\n\n        then:\n        past.size() == 1\n\n        when:\n        history.insert(new Counter(2))\n\n        then:\n        past.size() == 2\n\n        when:\n        history.insert(new Counter(3))\n\n        then:\n        past.size() == 3\n\n        when:\n        history.insert(new Counter(4))\n\n        then:\n        past.size() == 3\n        history.undo() == new Counter(3)\n        history.undo() == new Counter(2)\n        history.undo() == new Counter(1)\n        history.undo() == new Counter(1)\n\n        when:\n        history.insert(new Counter(7))\n        history.insert(new Counter(8))\n        history.insert(new Counter(6))\n        history.insert(new Counter(5))\n\n        then:\n        past.size() == 3\n        history.setLimit(2)\n        past.size() == 2\n        history.undo() == new Counter(6)\n        history.undo() == new Counter(8)\n        history.undo() == new Counter(8)\n    }\n}\n"
  },
  {
    "path": "droidux/src/test/groovy/info/izumin/android/droidux/action/HistoryActionTest.groovy",
    "content": "package info.izumin.android.droidux.action\n\nimport info.izumin.android.droidux.UndoableState\nimport info.izumin.android.droidux.annotation.Reducer\nimport info.izumin.android.droidux.annotation.Undoable\nimport spock.lang.Specification\n\n/**\n * Created by izumin on 12/5/15.\n */\nclass HistoryActionTest extends Specification {\n\n    class Counter implements UndoableState<Counter> {\n        @Override Counter clone() {\n            return new Counter()\n        }\n    }\n\n    class SubUndoableDummyReducer extends UndoableDummyReducer {}\n\n    @Undoable @Reducer(Counter.class)\n    class UndoableDummyReducer {}\n\n    @Reducer(String.class)\n    class DummyReducer {}\n\n    class DummyClass {}\n\n    def \"when pass the class annotated with @Reducer and @Undoable to the constructor\"() {\n        when:\n        new HistoryAction(HistoryAction.Kind.UNDO, UndoableDummyReducer.class)\n\n        then:\n        noExceptionThrown()\n    }\n\n    def \"when pass the class is not annotated with @Reducer to the constructor\"() {\n        when:\n        new HistoryAction(HistoryAction.Kind.UNDO, DummyReducer.class)\n\n        then:\n        thrown(IllegalArgumentException.class)\n    }\n\n    def \"when pass the class that has no annotations to the constructor\"() {\n        when:\n        new HistoryAction(HistoryAction.Kind.UNDO, DummyClass.class)\n\n        then:\n        thrown(IllegalArgumentException.class)\n    }\n\n    def \"isAssignableTo()\"() {\n        setup:\n        def action = new HistoryAction(HistoryAction.Kind.UNDO, UndoableDummyReducer.class)\n\n        expect:\n        action.isAssignableTo(reducer) == result\n\n        where:\n        reducer                         | result\n        new UndoableDummyReducer()      | true\n        new Object()                    | false\n        new DummyReducer()              | false\n        new SubUndoableDummyReducer()   | false\n    }\n}\n"
  },
  {
    "path": "droidux-processor/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "droidux-processor/build.gradle",
    "content": "import org.gradle.internal.jvm.Jvm\n\napply plugin: 'java'\napply plugin: 'com.novoda.bintray-release'\n\ntargetCompatibility = JavaVersion.VERSION_1_7\nsourceCompatibility = JavaVersion.VERSION_1_7\n\nsourceSets {\n    main {\n        java {\n            srcDirs = ['src/main/java', '../droidux/src/main/java']\n        }\n    }\n}\n\ndependencies {\n    compile 'com.squareup:javapoet:1.7.0'\n    compile 'com.google.auto:auto-common:0.6'\n    compile 'com.google.auto.service:auto-service:1.0-rc2'\n\n    compile \"io.reactivex.rxjava2:rxjava:${project.rxJava2Version}\"\n    compile \"com.android.databinding:baseLibrary:${project.databindingBaseLibraryVersion}\"\n    compile fileTree(dir: './libs', includes: ['*.jar'])\n\n    testCompile 'junit:junit:4.12'\n    testCompile 'org.assertj:assertj-core:2.2.0'\n    testCompile 'org.mockito:mockito-core:1.10.19'\n    testCompile 'com.google.testing.compile:compile-testing:0.6'\n    testCompile files(Jvm.current().getToolsJar())\n    testCompile 'com.google.android:android:4.1.1.4'\n}\n\npublish {\n    userOrg = project_bintray_org\n    groupId = project_group\n    artifactId = 'droidux-processor'\n    version = project.versionName\n    description = 'Code generator for info.izumin.android.droidux'\n    website = project_url\n}\n\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/AbstractProcessingStep.java",
    "content": "package info.izumin.android.droidux.processor;\n\nimport com.google.auto.common.BasicAnnotationProcessor;\nimport com.squareup.javapoet.JavaFile;\n\nimport java.io.IOException;\n\nimport javax.annotation.processing.Filer;\n\n/**\n * Created by izumin on 11/26/15.\n */\npublic abstract class AbstractProcessingStep implements BasicAnnotationProcessor.ProcessingStep {\n    public static final String TAG = AbstractProcessingStep.class.getSimpleName();\n\n    private final Filer filer;\n\n    public AbstractProcessingStep(Filer filer) {\n        this.filer = filer;\n    }\n\n    protected void write(JavaFile file) {\n        try {\n            file.writeTo(filer);\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/DroiduxProcessor.java",
    "content": "package info.izumin.android.droidux.processor;\n\nimport com.google.auto.common.BasicAnnotationProcessor;\nimport com.google.auto.service.AutoService;\nimport com.google.common.collect.ImmutableList;\n\nimport javax.annotation.processing.Filer;\nimport javax.annotation.processing.Processor;\nimport javax.lang.model.SourceVersion;\n\n@AutoService(Processor.class)\npublic class DroiduxProcessor extends BasicAnnotationProcessor {\n\n    @Override\n    public SourceVersion getSupportedSourceVersion() {\n        return SourceVersion.latestSupported();\n    }\n\n    @Override\n    protected Iterable<? extends ProcessingStep> initSteps() {\n        return ImmutableList.<ProcessingStep>of(\n                new ReducerProcessingStep(getFiler()),\n                new StoreProcessingStep(getFiler())\n        );\n    }\n\n    private Filer getFiler() {\n        return processingEnv.getFiler();\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/ReducerProcessingStep.java",
    "content": "package info.izumin.android.droidux.processor;\n\nimport com.google.common.collect.ImmutableSet;\nimport com.google.common.collect.SetMultimap;\n\nimport java.lang.annotation.Annotation;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport javax.annotation.processing.Filer;\nimport javax.lang.model.element.Element;\n\nimport info.izumin.android.droidux.annotation.Reducer;\n\n/**\n * Created by izumin on 11/26/15.\n */\npublic class ReducerProcessingStep extends AbstractProcessingStep {\n    public static final String TAG = ReducerProcessingStep.class.getSimpleName();\n\n    public ReducerProcessingStep(Filer filer) {\n        super(filer);\n    }\n\n    @Override\n    public Set<? extends Class<? extends Annotation>> annotations() {\n        return ImmutableSet.<Class<? extends Annotation>>of(Reducer.class);\n    }\n\n    @Override\n    public Set<Element> process(SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {\n//        for (Element element : elementsByAnnotation.get(Reducer.class)) {\n//            write(new StoreImplClassGenerator(new ReducerModel((TypeElement) element)).createJavaFile());\n//        }\n        return new HashSet<>();\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/StoreProcessingStep.java",
    "content": "package info.izumin.android.droidux.processor;\n\nimport com.google.common.collect.ImmutableSet;\nimport com.google.common.collect.SetMultimap;\n\nimport java.lang.annotation.Annotation;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport javax.annotation.processing.Filer;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.TypeElement;\n\nimport info.izumin.android.droidux.annotation.Store;\nimport info.izumin.android.droidux.processor.generator.StoreClassGenerator;\nimport info.izumin.android.droidux.processor.generator.StoreImplClassGenerator;\nimport info.izumin.android.droidux.processor.model.StoreImplModel;\nimport info.izumin.android.droidux.processor.model.StoreModel;\n\n/**\n * Created by izumin on 11/26/15.\n */\npublic class StoreProcessingStep extends AbstractProcessingStep {\n    public static final String TAG = StoreProcessingStep.class.getSimpleName();\n\n    public StoreProcessingStep(Filer filer) {\n        super(filer);\n    }\n\n    @Override\n    public Set<? extends Class<? extends Annotation>> annotations() {\n        return ImmutableSet.<Class<? extends Annotation>>of(Store.class);\n    }\n\n    @Override\n    public Set<Element> process(SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {\n        for (Element element : elementsByAnnotation.get(Store.class)) {\n            StoreModel model = new StoreModel((TypeElement) element);\n            for (StoreImplModel storeImplModel : model.getStoreImplModels()) {\n                write(new StoreImplClassGenerator(storeImplModel).createJavaFile());\n            }\n            write(new StoreClassGenerator(model).createJavaFile());\n        }\n        return new HashSet<>();\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/exception/InvalidDispatchableDeclarationException.java",
    "content": "package info.izumin.android.droidux.processor.exception;\n\n/**\n * Created by izumin on 11/7/15.\n */\npublic class InvalidDispatchableDeclarationException extends RuntimeException {\n    public InvalidDispatchableDeclarationException(String message) {\n        super(message);\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/exception/InvalidReducerDeclarationException.java",
    "content": "package info.izumin.android.droidux.processor.exception;\n\n/**\n * Created by izumin on 11/8/15.\n */\npublic class InvalidReducerDeclarationException extends RuntimeException {\n    public InvalidReducerDeclarationException(String message) {\n        super(message);\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/exception/InvalidStoreDelcarationException.java",
    "content": "package info.izumin.android.droidux.processor.exception;\n\n/**\n * Created by izumin on 11/24/15.\n */\npublic class InvalidStoreDelcarationException extends RuntimeException {\n    public InvalidStoreDelcarationException(String message) {\n        super(message);\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/generator/StoreBuilderClassGenerator.java",
    "content": "package info.izumin.android.droidux.processor.generator;\n\nimport com.google.common.base.Function;\nimport com.google.common.base.Predicate;\nimport com.google.common.collect.FluentIterable;\nimport com.squareup.javapoet.FieldSpec;\nimport com.squareup.javapoet.MethodSpec;\nimport com.squareup.javapoet.TypeName;\nimport com.squareup.javapoet.TypeSpec;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.lang.model.element.Modifier;\n\nimport info.izumin.android.droidux.Middleware;\nimport info.izumin.android.droidux.exception.NotInitializedException;\nimport info.izumin.android.droidux.processor.model.BuilderModel;\nimport info.izumin.android.droidux.processor.model.ReducerModel;\nimport info.izumin.android.droidux.processor.model.StoreImplModel;\nimport info.izumin.android.droidux.processor.model.StoreModel;\n\nimport static info.izumin.android.droidux.processor.util.PoetUtils.getParameterSpec;\nimport static info.izumin.android.droidux.processor.util.StringUtils.getLowerCamelFromUpperCamel;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class StoreBuilderClassGenerator {\n    public static final String TAG = StoreBuilderClassGenerator.class.getSimpleName();\n\n    static final String ERROR_MESSAGE_NOT_INITIALIZED_EXCEPTION = \"$T has not been initialized.\";\n\n    private final BuilderModel builderModel;\n\n    public StoreBuilderClassGenerator(StoreModel storeModel) {\n        builderModel = storeModel.getBuilderModel();\n    }\n\n    public TypeSpec createBuilderTypeSpec() {\n        return TypeSpec.classBuilder(builderModel.getClassName().simpleName())\n                .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)\n                .addFields(createFieldSpecs())\n                .addMethod(createAddMiddlewareMethodSpec())\n                .addMethod(createBuilderConstructor())\n                .addMethods(createReducerSetterMethodSpecs())\n                .addMethods(createReducerAndStateSetterMethodSpecs())\n                .addMethod(createBuildMethodSpec())\n                .build();\n    }\n\n    private List<FieldSpec> createFieldSpecs() {\n        List<FieldSpec> specs = new ArrayList<>();\n        specs.add(FieldSpec.builder(BuilderModel.MIDDLEWARES_TYPE,\n                BuilderModel.MIDDLEWARES_VARIABLE_NAME, Modifier.FINAL, Modifier.PRIVATE).build());\n        specs.addAll(FluentIterable.from(builderModel.getReducerModels())\n                .transform(new Function<ReducerModel, FieldSpec>() {\n                    @Override\n                    public FieldSpec apply(ReducerModel input) {\n                        return FieldSpec.builder(input.getClassName(),\n                                input.getVariableName(), Modifier.PRIVATE).build();\n                    }\n                })\n                .toList());\n        specs.addAll(FluentIterable.from(builderModel.getReducerModels())\n                .transform(new Function<ReducerModel, FieldSpec>() {\n                    @Override\n                    public FieldSpec apply(ReducerModel input) {\n                        return FieldSpec.builder(input.getState(),\n                                input.getStateVariableName(), Modifier.PRIVATE).build();\n                    }\n                })\n                .toList());\n        specs.addAll(FluentIterable.from(builderModel.getStoreModel().getStoreImplModels())\n                .filter(new Predicate<StoreImplModel>() {\n                    @Override\n                    public boolean apply(StoreImplModel input) {\n                        return input.isBindable();\n                    }\n                })\n                .transform(new Function<StoreImplModel, FieldSpec>() {\n                    @Override\n                    public FieldSpec apply(StoreImplModel input) {\n                        return FieldSpec.builder(TypeName.INT, input.getFieldIdName(), Modifier.PRIVATE)\n                                .build();\n                    }\n                })\n                .toList());\n        return specs;\n    }\n\n    private MethodSpec createBuilderConstructor() {\n        return MethodSpec.constructorBuilder()\n                .addModifiers(Modifier.PRIVATE)\n                .addStatement(\"$N = new $T<>()\", BuilderModel.MIDDLEWARES_VARIABLE_NAME, ArrayList.class)\n                .build();\n    }\n\n    private MethodSpec createAddMiddlewareMethodSpec() {\n        return MethodSpec.methodBuilder(BuilderModel.ADD_MIDDLEWARE_METHOD_NAME)\n                .addModifiers(Modifier.PUBLIC)\n                .returns(builderModel.getClassName())\n                .addParameter(getParameterSpec(Middleware.class))\n                .addStatement(\"$N.add($N)\", BuilderModel.MIDDLEWARES_VARIABLE_NAME,\n                        getLowerCamelFromUpperCamel(Middleware.class.getName()))\n                .addStatement(\"return this\")\n                .build();\n    }\n\n    private List<MethodSpec> createReducerSetterMethodSpecs() {\n        return FluentIterable.from(builderModel.getStoreModel().getStoreImplModels())\n                .transform(new Function<StoreImplModel, MethodSpec>() {\n                    @Override\n                    public MethodSpec apply(StoreImplModel input) {\n                        MethodSpec.Builder builder = MethodSpec.methodBuilder(BuilderModel.REDUCER_SETTER_METHOD_NAME)\n                                .addModifiers(Modifier.PUBLIC)\n                                .returns(builderModel.getClassName())\n                                .addParameter(getParameterSpec(input.getReducerModel().getClassName()));\n                        if (input.isBindable()) {\n                            builder = builder.addParameter(TypeName.INT, input.getFieldIdName())\n                                    .addStatement(\"this.$N = $N\", input.getFieldIdName(), input.getFieldIdName());\n                        }\n                        return builder.addStatement(\"this.$N = $N\", input.getReducerModel().getVariableName(), input.getReducerModel().getVariableName())\n                                .addStatement(\"return this\")\n                                .build();\n                    }\n                })\n                .toList();\n    }\n\n    private List<MethodSpec> createReducerAndStateSetterMethodSpecs() {\n        return FluentIterable.from(builderModel.getStoreModel().getStoreImplModels())\n                .transform(new Function<StoreImplModel, MethodSpec>() {\n                    @Override\n                    public MethodSpec apply(StoreImplModel input) {\n                        MethodSpec.Builder builder = MethodSpec.methodBuilder(BuilderModel.REDUCER_SETTER_METHOD_NAME)\n                                .addModifiers(Modifier.PUBLIC)\n                                .returns(builderModel.getClassName())\n                                .addParameter(getParameterSpec(input.getReducerModel().getClassName()))\n                                .addParameter(getParameterSpec(input.getState()));\n                        if (input.isBindable()) {\n                            builder = builder.addParameter(TypeName.INT, input.getFieldIdName());\n                        }\n                        builder = builder.addStatement(\"this.$N = $N\", input.getStateVariableName(), input.getStateVariableName());\n                        if (input.isBindable()) {\n                            builder = builder.addStatement(\"return $N($N, $N)\", BuilderModel.REDUCER_SETTER_METHOD_NAME, input.getReducerModel().getVariableName(), input.getFieldIdName());\n                        } else {\n                            builder = builder.addStatement(\"return $N($N)\", BuilderModel.REDUCER_SETTER_METHOD_NAME, input.getReducerModel().getVariableName());\n                        }\n                        return builder.build();\n                    }\n                })\n                .toList();\n    }\n\n    private MethodSpec createBuildMethodSpec() {\n        MethodSpec.Builder builder = MethodSpec.methodBuilder(BuilderModel.BUILD_METHOD_NAME)\n                .addModifiers(Modifier.PUBLIC)\n                .returns(builderModel.getStoreModel().getClassName());\n\n        for (ReducerModel reducerModel : builderModel.getReducerModels()) {\n            builder = builder\n                    .beginControlFlow(\"if ($N == null)\", reducerModel.getVariableName())\n                    .addStatement(\"throw new $T(\\\"\" + ERROR_MESSAGE_NOT_INITIALIZED_EXCEPTION + \"\\\")\",\n                            NotInitializedException.class, reducerModel.getClassName())\n                    .endControlFlow();\n        }\n\n        return builder\n                .addStatement(\"return new $T(this)\", builderModel.getStoreModel().getClassName())\n                .build();\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/generator/StoreClassGenerator.java",
    "content": "package info.izumin.android.droidux.processor.generator;\n\nimport android.databinding.BaseObservable;\n\nimport com.google.common.base.Function;\nimport com.google.common.base.Joiner;\nimport com.google.common.collect.FluentIterable;\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.FieldSpec;\nimport com.squareup.javapoet.JavaFile;\nimport com.squareup.javapoet.MethodSpec;\nimport com.squareup.javapoet.ParameterizedTypeName;\nimport com.squareup.javapoet.TypeName;\nimport com.squareup.javapoet.TypeSpec;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.lang.model.element.Modifier;\n\nimport info.izumin.android.droidux.Action;\nimport info.izumin.android.droidux.Middleware;\nimport info.izumin.android.droidux.OnStateChangedListener;\nimport info.izumin.android.droidux.processor.model.BuilderModel;\nimport info.izumin.android.droidux.processor.model.DispatcherModel;\nimport info.izumin.android.droidux.processor.model.StoreImplModel;\nimport info.izumin.android.droidux.processor.model.StoreMethodModel;\nimport info.izumin.android.droidux.processor.model.StoreModel;\nimport io.reactivex.Flowable;\nimport io.reactivex.Single;\n\nimport static info.izumin.android.droidux.processor.util.PoetUtils.getOverrideAnnotation;\nimport static info.izumin.android.droidux.processor.util.PoetUtils.getParameterSpec;\nimport static info.izumin.android.droidux.processor.util.StringUtils.getLowerCamelFromUpperCamel;\n\n/**\n * Created by izumin on 11/3/15.\n */\npublic class StoreClassGenerator {\n    public static final String TAG = StoreClassGenerator.class.getSimpleName();\n\n    private final StoreModel storeModel;\n\n    public StoreClassGenerator(StoreModel storeModel) {\n        this.storeModel = storeModel;\n    }\n\n    public JavaFile createJavaFile() {\n        return JavaFile.builder(storeModel.getClassName().packageName(), createTypeSpec())\n                .skipJavaLangImports(true).build();\n    }\n\n    private TypeSpec createTypeSpec() {\n        return TypeSpec.classBuilder(storeModel.getClassName().simpleName())\n                .addModifiers(Modifier.PUBLIC, Modifier.FINAL)\n                .addSuperinterface(storeModel.getInterfaceName())\n                .superclass(TypeName.get(BaseObservable.class))\n                .addFields(createFieldSpecs())\n                .addMethod(createConstructor())\n                .addMethod(createBuilderMethodSpec())\n                .addMethods(createGetterMethodSpecs())\n                .addMethod(createDispatchMethodSpec())\n                .addType(new StoreBuilderClassGenerator(storeModel).createBuilderTypeSpec())\n                .build();\n    }\n\n    private List<FieldSpec> createFieldSpecs() {\n        List<FieldSpec> specs = new ArrayList<>();\n        specs.addAll(FluentIterable.from(storeModel.getStoreImplModels())\n                .transform(new Function<StoreImplModel, FieldSpec>() {\n                    @Override\n                    public FieldSpec apply(StoreImplModel input) {\n                        return FieldSpec.builder(input.getClassName(), input.getVariableName(),\n                                Modifier.PRIVATE, Modifier.FINAL).build();\n                    }\n                }).toList());\n        specs.add(DispatcherModel.fieldSpec());\n        return specs;\n    }\n\n    private MethodSpec createConstructor() {\n        MethodSpec.Builder builder = MethodSpec.constructorBuilder()\n                .addModifiers(Modifier.PROTECTED)\n                .addParameter(getParameterSpec(storeModel.getBuilderModel().getClassName(), Modifier.FINAL));\n\n        for (StoreImplModel storeImpl : storeModel.getStoreImplModels()) {\n            builder = builder.addStatement(\"$N = new $T($N.$N, $N.$N)\",\n                    storeImpl.getVariableName(), storeImpl.getClassName(),\n                    BuilderModel.VARIABLE_NAME, storeImpl.getStateVariableName(),\n                    BuilderModel.VARIABLE_NAME, storeImpl.getReducerModel().getVariableName());\n\n            if (storeImpl.isBindable()) {\n                TypeSpec listener = TypeSpec.anonymousClassBuilder(\"\")\n                        .addSuperinterface(ParameterizedTypeName.get(ClassName.get(OnStateChangedListener.class), storeImpl.getState()))\n                        .addMethod(\n                                MethodSpec.methodBuilder(StoreImplModel.ON_STATE_CHANGED_METHOD_NAME)\n                                        .addAnnotation(getOverrideAnnotation())\n                                        .addModifiers(Modifier.PUBLIC)\n                                        .addParameter(getParameterSpec(storeImpl.getState()))\n                                        .addStatement(\"$N($N.$N)\",\n                                                StoreImplModel.NOTIFY_PROPERTY_CHANGED_METHOD_NAME,\n                                                BuilderModel.VARIABLE_NAME,\n                                                storeImpl.getFieldIdName())\n                                        .build()\n                        )\n                        .build();\n                builder = builder.addStatement(\"$N.$N($L)\", storeImpl.getVariableName(),\n                        StoreImplModel.ADD_LISTENER_METHOD_NAME, listener);\n            }\n        }\n\n        final String middlewareFiledName = \"middleware\";\n        return builder\n                .addStatement(\"$N = new $N($N.$N, $N)\",\n                        DispatcherModel.VARIABLE_NAME, DispatcherModel.CLASS_NAME,\n                        BuilderModel.VARIABLE_NAME, BuilderModel.MIDDLEWARES_VARIABLE_NAME,\n                        FluentIterable.from(storeModel.getStoreImplModels())\n                                .transform(new Function<StoreImplModel, String>() {\n                                    @Override\n                                    public String apply(StoreImplModel input) {\n                                        return input.getVariableName();\n                                    }\n                                }).join(Joiner.on(\", \")))\n                .beginControlFlow(\"for ($T $N : $N.$N)\", Middleware.class, middlewareFiledName,\n                        BuilderModel.VARIABLE_NAME, StoreModel.MIDDLEWARES_FIELD_NAME)\n                .addStatement(\"$N.$N(this, $N)\", middlewareFiledName,\n                        StoreModel.ATTACH_MIDDLEWARE_METHOD_NAME, DispatcherModel.VARIABLE_NAME)\n                .endControlFlow()\n                .build();\n    }\n\n    private MethodSpec createBuilderMethodSpec() {\n        return MethodSpec.methodBuilder(StoreModel.BUILDER_METHOD_NAME)\n                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n                .returns(storeModel.getBuilderModel().getClassName())\n                .addStatement(\"return new $T()\", storeModel.getBuilderModel().getClassName())\n                .build();\n    }\n\n    private List<MethodSpec> createGetterMethodSpecs() {\n        return FluentIterable.from(storeModel.getMethodModels())\n                .transform(new Function<StoreMethodModel, MethodSpec>() {\n                    @Override\n                    public MethodSpec apply(StoreMethodModel input) {\n                        return MethodSpec.methodBuilder(input.getName())\n                                .addAnnotation(getOverrideAnnotation())\n                                .addModifiers(Modifier.PUBLIC)\n                                .returns(TypeName.get(input.getReturnType()))\n                                .addParameters(input.getParameters())\n                                .addCode(input.getCodeBlock())\n                                .build();\n                    }\n                })\n                .toList();\n    }\n\n    private MethodSpec createDispatchMethodSpec() {\n        return MethodSpec.methodBuilder(StoreModel.DISPATCH_METHOD_NAME)\n                .addAnnotation(getOverrideAnnotation())\n                .addModifiers(Modifier.PUBLIC)\n                .returns(ParameterizedTypeName.get(ClassName.get(Flowable.class), ClassName.get(Action.class)))\n                .addParameter(getParameterSpec(Action.class))\n                .addStatement(\"return $N.$N($N)\",\n                        DispatcherModel.VARIABLE_NAME, DispatcherModel.DISPATCH_METHOD_NAME,\n                        getLowerCamelFromUpperCamel(ClassName.get(Action.class).simpleName()))\n                .build();\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/generator/StoreImplClassGenerator.java",
    "content": "package info.izumin.android.droidux.processor.generator;\n\nimport com.google.common.base.Function;\nimport com.google.common.base.Joiner;\nimport com.google.common.collect.FluentIterable;\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.CodeBlock;\nimport com.squareup.javapoet.JavaFile;\nimport com.squareup.javapoet.MethodSpec;\nimport com.squareup.javapoet.ParameterizedTypeName;\nimport com.squareup.javapoet.TypeName;\nimport com.squareup.javapoet.TypeSpec;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.lang.model.element.Modifier;\n\nimport info.izumin.android.droidux.Action;\nimport info.izumin.android.droidux.StoreImpl;\nimport info.izumin.android.droidux.UndoableStoreImpl;\nimport info.izumin.android.droidux.processor.model.DispatchableModel;\nimport info.izumin.android.droidux.processor.model.StoreImplModel;\n\nimport static info.izumin.android.droidux.processor.util.PoetUtils.getOverrideAnnotation;\nimport static info.izumin.android.droidux.processor.util.PoetUtils.getParameterSpec;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class StoreImplClassGenerator {\n    public static final String TAG = StoreImplClassGenerator.class.getSimpleName();\n\n    private final StoreImplModel storeImplModel;\n\n    public StoreImplClassGenerator(StoreImplModel storeImplModel) {\n        this.storeImplModel = storeImplModel;\n    }\n\n    public JavaFile createJavaFile() {\n        return JavaFile.builder(storeImplModel.getPackageName(), createTypeSpec())\n                .skipJavaLangImports(true).build();\n    }\n\n    private TypeSpec createTypeSpec() {\n        return TypeSpec.classBuilder(storeImplModel.getClassName().simpleName())\n                .addModifiers(Modifier.FINAL)\n                .superclass(ParameterizedTypeName.get(ClassName.get(storeImplModel.isUndoable() ? UndoableStoreImpl.class : StoreImpl.class),\n                        storeImplModel.getState(), storeImplModel.getReducerModel().getClassName()))\n                .addMethod(createConstructor())\n                .addMethod(createMethodSpec())\n                .build();\n    }\n\n    private MethodSpec createConstructor() {\n        return MethodSpec.constructorBuilder()\n                .addModifiers(Modifier.PROTECTED)\n                .addParameter(storeImplModel.getState(), StoreImplModel.STATE_VARIABLE_NAME)\n                .addParameter(storeImplModel.getReducerModel().getClassName(), StoreImplModel.REDUCER_VARIABLE_NAME)\n                .addStatement(\"super($N, $N)\", StoreImplModel.STATE_VARIABLE_NAME, StoreImplModel.REDUCER_VARIABLE_NAME)\n                .build();\n    }\n\n    private MethodSpec createMethodSpec() {\n        return MethodSpec.methodBuilder(StoreImplModel.DISPATCH_METHOD_NAME)\n                .addAnnotation(getOverrideAnnotation())\n                .addModifiers(Modifier.PROTECTED)\n                .returns(TypeName.VOID)\n                .addParameter(getParameterSpec(Action.class))\n                .addCode(createCodeBlock())\n                .build();\n    }\n\n    private CodeBlock createCodeBlock() {\n        CodeBlock.Builder builder = CodeBlock.builder();\n        final String ACTION_FIELD =  \"action\";\n        final String ACTION_CLASS_FIELD =  \"actionClass\";\n        final String RESULT_FIELD = \"result\";\n        final String STATE_GETTER = storeImplModel.isUndoable() ? \"getState().clone()\" : \"getState()\";\n\n        if (storeImplModel.isUndoable()) {\n            builder = builder.addStatement(\"super.$N($N)\",\n                    StoreImplModel.DISPATCH_METHOD_NAME, ACTION_FIELD);\n        }\n\n        builder = builder.addStatement(\"Class<? extends $T> $N = $N.getClass()\",\n                Action.class, ACTION_CLASS_FIELD, ACTION_FIELD)\n                .addStatement(\"$T $N = null\", storeImplModel.getState(), RESULT_FIELD);\n\n        for (final DispatchableModel dispatchableModel : storeImplModel.getReducerModel().getDispatchableModels()) {\n            final List<Object> args = new ArrayList<>();\n            args.add(RESULT_FIELD);\n            args.add(StoreImplModel.REDUCER_GETTER_METHOD_NAME);\n            args.add(dispatchableModel.getMethodName());\n            final String format = \"$N = $N().$N(\" + FluentIterable.from(dispatchableModel.getArguments())\n                    .transform(new Function<ClassName, String>() {\n                        @Override\n                        public String apply(ClassName input) {\n                            if (input.simpleName().equals(dispatchableModel.getAction().simpleName())) {\n                                args.add(dispatchableModel.getAction());\n                                args.add(ACTION_FIELD);\n                                return \"($T) $N\";\n                            } else if (input.simpleName().equals(storeImplModel.getState().simpleName())) {\n                                return STATE_GETTER;\n                            } else {\n                                return \"\";\n                            }\n                        }\n                    }).join(Joiner.on(\", \")) + \")\";\n\n            builder = builder.beginControlFlow(\"if ($T.class.isAssignableFrom($N))\",\n                    dispatchableModel.getAction(), ACTION_CLASS_FIELD)\n                    .addStatement(format, args.toArray())\n                    .endControlFlow();\n        }\n\n        return builder\n                .beginControlFlow(\"if ($N != null)\", RESULT_FIELD)\n                .addStatement(\"setState($N)\", RESULT_FIELD)\n                .endControlFlow()\n                .build();\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/model/BuilderModel.java",
    "content": "package info.izumin.android.droidux.processor.model;\n\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.ParameterizedTypeName;\n\nimport java.util.List;\n\nimport info.izumin.android.droidux.Middleware;\n\nimport static info.izumin.android.droidux.processor.util.StringUtils.getLowerCamelFromUpperCamel;\n\n/**\n * Created by izumin on 11/28/15.\n */\npublic class BuilderModel {\n    public static final String TAG = BuilderModel.class.getSimpleName();\n\n    public static final String CLASS_NAME = \"Builder\";\n    public static final String VARIABLE_NAME = getLowerCamelFromUpperCamel(CLASS_NAME);\n\n    public static final String ADD_MIDDLEWARE_METHOD_NAME = \"addMiddleware\";\n    public static final String STATE_SETTER_METHOD_NAME = \"setInitialState\";\n    public static final String REDUCER_SETTER_METHOD_NAME = \"setReducer\";\n    public static final String BUILD_METHOD_NAME = \"build\";\n\n    public static final ParameterizedTypeName MIDDLEWARES_TYPE =\n            ParameterizedTypeName.get(List.class, Middleware.class);\n    public static final String MIDDLEWARES_VARIABLE_NAME = \"middlewares\";\n\n    private final ClassName className;\n\n    private final StoreModel storeModel;\n    private final List<ReducerModel> reducerModels;\n\n    public BuilderModel(StoreModel storeModel) {\n        this.storeModel = storeModel;\n        this.className = storeModel.getClassName().nestedClass(CLASS_NAME);\n        this.reducerModels = storeModel.getReducerModels();\n    }\n\n    public StoreModel getStoreModel() {\n        return storeModel;\n    }\n\n    public ClassName getClassName() {\n        return className;\n    }\n\n    public List<ReducerModel> getReducerModels() {\n        return reducerModels;\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/model/DispatchableModel.java",
    "content": "package info.izumin.android.droidux.processor.model;\n\nimport com.google.auto.common.MoreTypes;\nimport com.google.common.base.Function;\nimport com.google.common.collect.FluentIterable;\nimport com.squareup.javapoet.ClassName;\n\nimport java.util.List;\n\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.VariableElement;\n\nimport info.izumin.android.droidux.annotation.Dispatchable;\nimport info.izumin.android.droidux.processor.validator.DispatchableValidator;\n\nimport static com.google.auto.common.MoreTypes.asTypeElement;\nimport static info.izumin.android.droidux.processor.util.AnnotationUtils.getTypeFromAnnotation;\n\n/**\n * Created by izumin on 11/3/15.\n */\npublic class DispatchableModel {\n    public static final String TAG = DispatchableModel.class.getSimpleName();\n\n    private final ExecutableElement element;\n    private final ReducerModel reducerModel;\n    private final ClassName action;\n    private final String methodName;\n\n    private final List<ClassName> arguments;\n\n    public DispatchableModel(ExecutableElement element, ReducerModel reducerModel) {\n        this.element = element;\n        this.reducerModel = reducerModel;\n        this.methodName = element.getSimpleName().toString();\n        this.action = ClassName.get(asTypeElement(getTypeFromAnnotation(element, Dispatchable.class, \"value\")));\n        this.arguments = FluentIterable.from(element.getParameters())\n                .transform(new Function<VariableElement, ClassName>() {\n                    @Override\n                    public ClassName apply(VariableElement input) {\n                        return ClassName.get(MoreTypes.asTypeElement(input.asType()));\n                    }\n                }).toList();\n\n        DispatchableValidator.validate(this);\n    }\n\n    public ClassName getAction() {\n        return action;\n    }\n\n    public String getMethodName() {\n        return methodName;\n    }\n\n    public int argumentCount() {\n        return element.getParameters().size();\n    }\n\n    public ExecutableElement getElement() {\n        return element;\n    }\n\n    public List<ClassName> getArguments() {\n        return arguments;\n    }\n\n    public ClassName getReducerClassName() {\n        return reducerModel.getClassName();\n    }\n    public ClassName getState() {\n        return reducerModel.getState();\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/model/DispatcherModel.java",
    "content": "package info.izumin.android.droidux.processor.model;\n\nimport com.squareup.javapoet.FieldSpec;\n\nimport javax.lang.model.element.Modifier;\n\nimport info.izumin.android.droidux.Dispatcher;\n\nimport static info.izumin.android.droidux.processor.util.StringUtils.getLowerCamelFromUpperCamel;\n\n/**\n * Created by izumin on 11/28/15.\n */\npublic class DispatcherModel {\n    public static final String TAG = DispatcherModel.class.getSimpleName();\n\n    public static final Class CLASS = Dispatcher.class;\n    public static final String CLASS_NAME = \"Dispatcher\";\n    public static final String VARIABLE_NAME = getLowerCamelFromUpperCamel(CLASS_NAME);\n\n    public static final String DISPATCH_METHOD_NAME = \"dispatch\";\n\n    public static FieldSpec fieldSpec() {\n        return FieldSpec.builder(CLASS, VARIABLE_NAME, Modifier.PRIVATE, Modifier.FINAL).build();\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/model/ReducerModel.java",
    "content": "package info.izumin.android.droidux.processor.model;\n\nimport com.squareup.javapoet.ClassName;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.TypeElement;\n\nimport info.izumin.android.droidux.annotation.Dispatchable;\nimport info.izumin.android.droidux.annotation.Reducer;\nimport info.izumin.android.droidux.annotation.Undoable;\nimport info.izumin.android.droidux.processor.util.StringUtils;\nimport info.izumin.android.droidux.processor.validator.ReducerValidator;\n\nimport static com.google.auto.common.MoreTypes.asTypeElement;\nimport static info.izumin.android.droidux.processor.util.AnnotationUtils.findMethodsByAnnotation;\nimport static info.izumin.android.droidux.processor.util.AnnotationUtils.getTypeFromAnnotation;\n\n/**\n * Created by izumin on 11/3/15.\n */\npublic class ReducerModel {\n    public static final String TAG = ReducerModel.class.getSimpleName();\n\n    public static final String CLASS_NAME_SUFFIX = \"Reducer\";\n\n    private final TypeElement element;\n    private final TypeElement stateElement;\n    private final ClassName state;\n    private final ClassName className;\n\n    private final String qualifiedName;\n    private final String packageName;\n    private final String variableName;\n    private String stateName;\n    private String stateVariableName;\n\n    private final boolean isUndoable;\n\n    private List<DispatchableModel> dispatchableModels;\n\n    public ReducerModel(TypeElement element) {\n        this.element = element;\n        this.stateElement = asTypeElement(getTypeFromAnnotation(element, Reducer.class, \"value\"));\n        this.state = ClassName.get(stateElement);\n        this.stateName = state.simpleName();\n        this.stateVariableName = StringUtils.getLowerCamelFromUpperCamel(stateName);\n\n        this.isUndoable = element.getAnnotation(Undoable.class) != null;\n\n        this.className = ClassName.get(element);\n\n        this.qualifiedName = element.getQualifiedName().toString();\n        this.packageName = StringUtils.getPackageName(qualifiedName);\n        this.variableName = StringUtils.getLowerCamelFromUpperCamel(className.simpleName());\n\n        this.dispatchableModels = new ArrayList<>();\n        for (ExecutableElement el : findMethodsByAnnotation(element, Dispatchable.class)) {\n            dispatchableModels.add(new DispatchableModel(el, this));\n        }\n\n        ReducerValidator.validate(this);\n    }\n\n    public TypeElement getElement() {\n        return element;\n    }\n\n    public TypeElement getStateElement() {\n        return stateElement;\n    }\n\n    public ClassName getState() {\n        return state;\n    }\n\n    public ClassName getClassName() {\n        return className;\n    }\n\n    public String getQualifiedName() {\n        return qualifiedName;\n    }\n\n    public String getPackageName() {\n        return packageName;\n    }\n\n    public String getVariableName() {\n        return variableName;\n    }\n\n    public String getStateName() {\n        return stateName;\n    }\n\n    public String getStateVariableName() {\n        return stateVariableName;\n    }\n\n    public List<DispatchableModel> getDispatchableModels() {\n        return dispatchableModels;\n    }\n\n    public boolean isUndoable() {\n        return isUndoable;\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/model/StoreImplModel.java",
    "content": "package info.izumin.android.droidux.processor.model;\n\nimport com.squareup.javapoet.ClassName;\n\nimport static info.izumin.android.droidux.processor.util.StringUtils.getLowerCamelFromUpperCamel;\nimport static info.izumin.android.droidux.processor.util.StringUtils.replaceSuffix;\n\n/**\n * Created by izumin on 11/3/15.\n */\npublic class StoreImplModel {\n    public static final String TAG = StoreImplModel.class.getSimpleName();\n\n    public static final String REDUCER_VARIABLE_NAME = \"reducer\";\n    public static final String STATE_VARIABLE_NAME = \"state\";\n    public static final String DISPATCH_METHOD_NAME = \"dispatch\";\n    public static final String STATE_GETTER_METHOD_NAME = \"getState\";\n    public static final String REDUCER_GETTER_METHOD_NAME = \"getReducer\";\n    public static final String STATE_OBSERVE_METHOD_NAME = \"observe\";\n    public static final String ADD_LISTENER_METHOD_NAME = \"addListener\";\n    public static final String ON_STATE_CHANGED_METHOD_NAME = \"onStateChanged\";\n    public static final String NOTIFY_PROPERTY_CHANGED_METHOD_NAME = \"notifyPropertyChanged\";\n\n    private static final String CLASS_NAME_SUFFIX = \"StoreImpl\";\n    private static final String REDUCER_CLASS_NAME_SUFFIX = \"Reducer\";\n    private static final String FIELD_ID_SUFFIX = \"FieldId\";\n\n    private final ClassName className;\n\n    private final String variableName;\n    private final String storeImplName;\n\n    private final StoreModel storeModel;\n    private final ReducerModel reducerModel;\n\n    private boolean isBindable = false;\n\n    public StoreImplModel(StoreModel storeModel, ReducerModel reducerModel) {\n        this.storeModel = storeModel;\n        this.reducerModel = reducerModel;\n\n        this.storeImplName = replaceSuffix(reducerModel.getClassName().simpleName(),\n                REDUCER_CLASS_NAME_SUFFIX, CLASS_NAME_SUFFIX);\n\n        this.variableName = getLowerCamelFromUpperCamel(storeImplName);\n        this.className = ClassName.bestGuess(storeModel.getClassName() + \"_\" + storeImplName);\n    }\n\n    public ClassName getState() {\n        return reducerModel.getState();\n    }\n\n    public String getPackageName() {\n        return storeModel.getClassName().packageName();\n    }\n\n    public String getStateName() {\n        return reducerModel.getStateName();\n    }\n\n    public String getStateVariableName() {\n        return reducerModel.getStateVariableName();\n    }\n\n    public boolean isUndoable() {\n        return reducerModel.isUndoable();\n    }\n\n    public String getStoreImplName() {\n        return storeImplName;\n    }\n\n    public ClassName getClassName() {\n        return className;\n    }\n\n    public String getVariableName() {\n        return variableName;\n    }\n\n    public ReducerModel getReducerModel() {\n        return reducerModel;\n    }\n\n    public String getFieldIdName() {\n        return getStateVariableName() + FIELD_ID_SUFFIX;\n    }\n\n    public boolean isBindable() {\n        return isBindable;\n    }\n\n    public void setIsBindable(boolean isBindable) {\n        this.isBindable = isBindable;\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/model/StoreMethodModel.java",
    "content": "package info.izumin.android.droidux.processor.model;\n\nimport android.databinding.Bindable;\n\nimport com.google.auto.common.MoreTypes;\nimport com.google.common.base.Function;\nimport com.google.common.base.Predicate;\nimport com.google.common.collect.FluentIterable;\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.CodeBlock;\nimport com.squareup.javapoet.ParameterSpec;\nimport com.squareup.javapoet.TypeName;\n\nimport java.util.List;\n\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.VariableElement;\nimport javax.lang.model.type.DeclaredType;\n\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.Flowable;\n\n/**\n * Created by izumin on 11/28/15.\n */\npublic class StoreMethodModel {\n    public static final String TAG = StoreMethodModel.class.getSimpleName();\n\n    enum Kind {\n        DISPATCH,\n        GETTER,\n        OBSERVE,\n        OBSERVE_WITH_BPS,\n        UNKNOWN\n    }\n\n    private static final Class OBSERVE_METHOD_CLASS = Flowable.class;\n    private static final Class BACKPRESSURE_STRATEGY_PARAM_CLASS = BackpressureStrategy.class;\n\n    private final ExecutableElement element;\n    private final StoreModel storeModel;\n    private final Kind kind;\n    private final DeclaredType returnType;\n    private boolean isBindable = false;\n    private String bpsParamName = \"\";\n\n    public StoreMethodModel(ExecutableElement element, StoreModel storeModel) {\n        this.element = element;\n        this.storeModel = storeModel;\n\n        List<TypeName> states = FluentIterable.from(storeModel.getStoreImplModels())\n                .transform(new Function<StoreImplModel, TypeName>() {\n                    @Override\n                    public TypeName apply(StoreImplModel input) {\n                        return input.getState();\n                    }\n                }).toList();\n\n        returnType = MoreTypes.asDeclared(element.getReturnType());\n\n        if (states.contains(ClassName.get(returnType))) {\n            kind = Kind.GETTER;\n            isBindable = element.getAnnotation(Bindable.class) != null;\n        } else if (getName().equals(DispatcherModel.DISPATCH_METHOD_NAME)) {\n            kind = Kind.DISPATCH;\n        } else if (MoreTypes.isTypeOf(OBSERVE_METHOD_CLASS, returnType.asElement().asType())\n                && states.contains(ClassName.get(returnType.getTypeArguments().get(0)))) {\n            if (element.getParameters() != null\n                    && !element.getParameters().isEmpty()\n                    && MoreTypes.isTypeOf(BACKPRESSURE_STRATEGY_PARAM_CLASS, element.getParameters().get(0).asType())) {\n                bpsParamName = element.getParameters().get(0).getSimpleName().toString();\n                kind = Kind.OBSERVE_WITH_BPS;\n            } else {\n                kind = Kind.OBSERVE;\n            }\n        } else {\n            kind = Kind.UNKNOWN;\n        }\n    }\n\n    public String getName() {\n        return element.getSimpleName().toString();\n    }\n\n    public DeclaredType getReturnType() {\n        return returnType;\n    }\n\n    public CodeBlock getCodeBlock() {\n        switch (kind) {\n            case GETTER:\n                return CodeBlock.builder().addStatement(\"return $N.$N()\",\n                        FluentIterable.from(storeModel.getStoreImplModels())\n                                .filter(new Predicate<StoreImplModel>() {\n                                    @Override\n                                    public boolean apply(StoreImplModel input) {\n                                        return ClassName.get(returnType).equals(input.getState());\n                                    }\n                                })\n                                .get(0).getVariableName(),\n                        StoreImplModel.STATE_GETTER_METHOD_NAME).build();\n            case OBSERVE:\n                return CodeBlock.builder().addStatement(\"return $N.$N()\",\n                        FluentIterable.from(storeModel.getStoreImplModels())\n                                .filter(new Predicate<StoreImplModel>() {\n                                    @Override\n                                    public boolean apply(StoreImplModel input) {\n                                        return ClassName.get(returnType.getTypeArguments().get(0)).equals(input.getState());\n                                    }\n                                })\n                                .get(0).getVariableName(),\n                        StoreImplModel.STATE_OBSERVE_METHOD_NAME).build();\n            case OBSERVE_WITH_BPS:\n                return CodeBlock.builder().addStatement(\"return $N.$N(\" + bpsParamName + \")\",\n                        FluentIterable.from(storeModel.getStoreImplModels())\n                                .filter(new Predicate<StoreImplModel>() {\n                                    @Override\n                                    public boolean apply(StoreImplModel input) {\n                                        return ClassName.get(returnType.getTypeArguments().get(0)).equals(input.getState());\n                                    }\n                                })\n                                .get(0).getVariableName(),\n                        StoreImplModel.STATE_OBSERVE_METHOD_NAME).build();\n            case DISPATCH:\n                return CodeBlock.builder()\n                        .addStatement(\"return $N.$N($N)\", DispatcherModel.VARIABLE_NAME,\n                                DispatcherModel.DISPATCH_METHOD_NAME, getParameters().get(0).name)\n                        .build();\n        }\n        return CodeBlock.builder().build();\n    }\n\n    public List<ParameterSpec> getParameters() {\n        return FluentIterable.from(element.getParameters())\n                .transform(new Function<VariableElement, ParameterSpec>() {\n                    @Override\n                    public ParameterSpec apply(VariableElement input) {\n                        return ParameterSpec.builder(TypeName.get(input.asType()),\n                                input.getSimpleName().toString()).build();\n                    }\n                }).toList();\n    }\n\n    public boolean isBindable() {\n        return isBindable;\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/model/StoreModel.java",
    "content": "package info.izumin.android.droidux.processor.model;\n\nimport com.google.common.base.Function;\nimport com.google.common.base.Predicate;\nimport com.google.common.collect.FluentIterable;\nimport com.squareup.javapoet.ClassName;\n\nimport java.util.List;\n\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.type.TypeMirror;\n\nimport info.izumin.android.droidux.annotation.Store;\nimport info.izumin.android.droidux.processor.validator.StoreValidator;\n\nimport static com.google.auto.common.MoreTypes.asTypeElement;\nimport static info.izumin.android.droidux.processor.util.AnnotationUtils.getTypesFromAnnotation;\n\n/**\n * Created by izumin on 11/3/15.\n */\npublic class StoreModel {\n    public static final String TAG = StoreModel.class.getSimpleName();\n\n    public static final String MIDDLEWARES_FIELD_NAME = \"middlewares\";\n    public static final String ATTACH_MIDDLEWARE_METHOD_NAME = \"onAttach\";\n    public static final String BUILDER_METHOD_NAME = \"builder\";\n    public static final String DISPATCH_METHOD_NAME = \"dispatch\";\n\n    private static final String CLASS_NAME_PREFIX = \"Droidux\";\n\n    private final TypeElement element;\n\n    private final ClassName interfaceName;\n    private final ClassName className;\n\n    private final List<ReducerModel> reducerModels;\n    private final List<StoreImplModel> storeImplModels;\n    private final List<StoreMethodModel> methodModels;\n    private final BuilderModel builderModel;\n\n    public StoreModel(TypeElement element) {\n        this.element = element;\n        this.interfaceName = ClassName.get(element);\n        this.className = ClassName.get(interfaceName.packageName(), CLASS_NAME_PREFIX + interfaceName.simpleName());\n\n        StoreValidator.validate(this);\n\n        reducerModels = FluentIterable.from(getTypesFromAnnotation(element, Store.class, \"value\"))\n                .transform(new Function<TypeMirror, ReducerModel>() {\n                    @Override\n                    public ReducerModel apply(TypeMirror input) {\n                        return new ReducerModel(asTypeElement(input));\n                    }\n                }).toList();\n\n        storeImplModels = FluentIterable.from(reducerModels)\n                .transform(new Function<ReducerModel, StoreImplModel>() {\n                    @Override\n                    public StoreImplModel apply(ReducerModel input) {\n                        return new StoreImplModel(StoreModel.this, input);\n                    }\n                }).toList();\n\n        methodModels = FluentIterable.from(element.getEnclosedElements())\n                .filter(ExecutableElement.class)\n                .transform(new Function<ExecutableElement, StoreMethodModel>() {\n                    @Override\n                    public StoreMethodModel apply(ExecutableElement input) {\n                        return new StoreMethodModel(input, StoreModel.this);\n                    }\n                })\n                .toList();\n\n        for (final StoreImplModel storeImplModel : storeImplModels) {\n            storeImplModel.setIsBindable(FluentIterable.from(methodModels)\n                    .filter(new Predicate<StoreMethodModel>() {\n                        @Override\n                        public boolean apply(StoreMethodModel input) {\n                            return ClassName.get(input.getReturnType()).equals(storeImplModel.getState());\n                        }\n                    })\n                    .anyMatch(new Predicate<StoreMethodModel>() {\n                        @Override\n                        public boolean apply(StoreMethodModel input) {\n                            return input.isBindable();\n                        }\n                    }));\n        }\n\n        this.builderModel = new BuilderModel(this);\n    }\n\n    public TypeElement getElement() {\n        return element;\n    }\n\n    public ClassName getInterfaceName() {\n        return interfaceName;\n    }\n\n    public ClassName getClassName() {\n        return className;\n    }\n\n    public List<ReducerModel> getReducerModels() {\n        return reducerModels;\n    }\n\n    public List<StoreImplModel> getStoreImplModels() {\n        return storeImplModels;\n    }\n\n    public List<StoreMethodModel> getMethodModels() {\n        return methodModels;\n    }\n\n    public BuilderModel getBuilderModel() {\n        return builderModel;\n    }\n\n    public boolean isBindable() {\n        return FluentIterable.from(methodModels)\n                .anyMatch(new Predicate<StoreMethodModel>() {\n                    @Override\n                    public boolean apply(StoreMethodModel input) {\n                        return input.isBindable();\n                    }\n                });\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/util/AnnotationUtils.java",
    "content": "package info.izumin.android.droidux.processor.util;\n\nimport com.google.common.base.Function;\nimport com.google.common.base.Predicate;\nimport com.google.common.collect.FluentIterable;\nimport com.google.common.collect.ImmutableList;\n\nimport java.lang.annotation.Annotation;\nimport java.util.List;\n\nimport javax.lang.model.element.AnnotationMirror;\nimport javax.lang.model.element.AnnotationValue;\nimport javax.lang.model.element.AnnotationValueVisitor;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.type.TypeMirror;\nimport javax.lang.model.util.SimpleAnnotationValueVisitor6;\n\nimport static com.google.auto.common.AnnotationMirrors.getAnnotationValue;\nimport static com.google.auto.common.MoreElements.getAnnotationMirror;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic final class AnnotationUtils {\n    public static final String TAG = AnnotationUtils.class.getSimpleName();\n\n    private AnnotationUtils() {\n        throw new AssertionError(\"constructor of the utility class should not be called\");\n    }\n\n    public static List<ExecutableElement> findMethodsByAnnotation(Element element, final Class<? extends Annotation> clazz) {\n        return FluentIterable.from(element.getEnclosedElements())\n                .filter(new Predicate<Element>() {\n                    @Override\n                    public boolean apply(Element input) {\n                        return input.getAnnotation(clazz) != null;\n                    }\n                })\n                .transform(new Function<Element, ExecutableElement>() {\n                    @Override\n                    public ExecutableElement apply(Element input) {\n                        return (ExecutableElement) input;\n                    }\n                })\n                .toList();\n    }\n\n    public static TypeMirror getTypeFromAnnotation(Element element, Class<? extends Annotation> annotationType, String argName) {\n        AnnotationMirror am = getAnnotationMirror(element, annotationType).get();\n        AnnotationValue av = getAnnotationValue(am, argName);\n        return TO_TYPE.visit(av);\n    }\n\n    public static List<TypeMirror> getTypesFromAnnotation(Element element, Class<? extends Annotation> annotationType, String argName) {\n        AnnotationMirror am = getAnnotationMirror(element, annotationType).get();\n        AnnotationValue av = getAnnotationValue(am, argName);\n        return TO_LIST_OF_TYPE.visit(av);\n    }\n\n    private static final AnnotationValueVisitor<ImmutableList<TypeMirror>, Void> TO_LIST_OF_TYPE = new SimpleAnnotationValueVisitor6<ImmutableList<TypeMirror>, Void>() {\n        @Override\n        public ImmutableList<TypeMirror> visitArray(List<? extends AnnotationValue> vals, Void aVoid) {\n            return FluentIterable.from(vals).transform(new Function<AnnotationValue, TypeMirror>() {\n                @Override\n                public TypeMirror apply(AnnotationValue input) {\n                    return TO_TYPE.visit(input);\n                }\n            }).toList();\n        }\n    };\n\n    private static final AnnotationValueVisitor<TypeMirror, Void> TO_TYPE = new SimpleAnnotationValueVisitor6<TypeMirror, Void>() {\n        @Override\n        public TypeMirror visitType(TypeMirror t, Void aVoid) {\n            return t;\n        }\n    };\n}"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/util/PoetUtils.java",
    "content": "package info.izumin.android.droidux.processor.util;\n\nimport com.squareup.javapoet.AnnotationSpec;\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.ParameterSpec;\nimport com.squareup.javapoet.TypeName;\n\nimport java.lang.annotation.Annotation;\n\nimport javax.lang.model.element.Modifier;\n\nimport static info.izumin.android.droidux.processor.util.StringUtils.getLowerCamelFromUpperCamel;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic final class PoetUtils {\n    public static final String TAG = PoetUtils.class.getSimpleName();\n\n    private PoetUtils() {\n        throw new AssertionError(\"constructor of the utility class should not be called\");\n    }\n\n    public static ParameterSpec getParameterSpec(ClassName className, Modifier... modifiers) {\n        return ParameterSpec.builder(\n                className.box(),\n                getLowerCamelFromUpperCamel(className.simpleName()),\n                modifiers\n        ).build();\n    }\n\n    public static ParameterSpec getParameterSpec(Class<?> clazz, Modifier... modifiers) {\n        return ParameterSpec.builder(\n                TypeName.get(clazz),\n                getLowerCamelFromUpperCamel(clazz.getSimpleName()),\n                modifiers\n        ).build();\n    }\n\n    public static AnnotationSpec getOverrideAnnotation() {\n        return getAnnotationSpec(Override.class);\n    }\n\n    public static AnnotationSpec getAnnotationSpec(Class<? extends Annotation> clazz) {\n        return AnnotationSpec.builder(clazz).build();\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/util/StringUtils.java",
    "content": "package info.izumin.android.droidux.processor.util;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic final class StringUtils {\n    public static final String TAG = StringUtils.class.getSimpleName();\n\n    private StringUtils() {\n        throw new AssertionError(\"constructor of the utility class should not be called\");\n    }\n\n    public static String getPackageName(String qualifiedName) {\n        return qualifiedName.substring(0, qualifiedName.lastIndexOf(\".\"));\n    }\n\n    public static String getClassName(String qualifiedName) {\n        return qualifiedName.substring(qualifiedName.lastIndexOf(\".\") + 1);\n    }\n\n    public static String replaceSuffix(String base, String target, String replacement) {\n        return base.substring(0, base.lastIndexOf(target)) + replacement;\n    }\n\n    public static String getLowerCamelFromUpperCamel(String upperCamel) {\n        upperCamel = getClassName(getClassName(upperCamel));\n        return upperCamel.substring(0, 1).toLowerCase() + upperCamel.substring(1);\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/validator/DispatchableValidator.java",
    "content": "package info.izumin.android.droidux.processor.validator;\n\nimport com.squareup.javapoet.ClassName;\n\nimport javax.lang.model.element.VariableElement;\n\nimport info.izumin.android.droidux.processor.exception.InvalidDispatchableDeclarationException;\nimport info.izumin.android.droidux.processor.model.DispatchableModel;\n\nimport static com.google.auto.common.MoreTypes.asTypeElement;\n\n/**\n * Created by izumin on 11/29/15.\n */\npublic final class DispatchableValidator {\n    private DispatchableValidator() {\n        throw new AssertionError(\"constructor of the utility class should not be called\");\n    }\n\n    public static void validate(DispatchableModel model) {\n        for (VariableElement element : model.getElement().getParameters()) {\n            if (!isAction(model, element) && !isState(model, element)) {\n                throw new InvalidDispatchableDeclarationException(\n                        \"@Dispatchable method can have arguments only state or action. \"\n                                + methodName(model) + \" has more than one invalid argument.\"\n                );\n            }\n        }\n\n        if (!isValidReturnType(model)) {\n            throw new InvalidDispatchableDeclarationException(\n                    \"@Dispatchable method must return new state. \"\n                            + \"But \" + methodName(model) + \" returns invalid type.\"\n            );\n        }\n    }\n\n    private static boolean isAction(DispatchableModel model, VariableElement element) {\n        return model.getAction().equals(ClassName.get(asTypeElement(element.asType())));\n    }\n\n    private static boolean isState(DispatchableModel model, VariableElement element) {\n        return model.getState().equals(ClassName.get(asTypeElement(element.asType())));\n    }\n\n    private static boolean isValidReturnType(DispatchableModel model) {\n        return ClassName.get(asTypeElement(model.getElement().getReturnType()))\n                .equals(model.getState());\n    }\n\n    private static String argName(VariableElement element) {\n        return \"[\" + element.asType().toString() + \" \" + element.getSimpleName() + \"]\";\n    }\n\n    private static String methodName(DispatchableModel model) {\n        return model.getReducerClassName().simpleName() + \"#\" + model.getMethodName() + \"()\";\n    }\n}"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/validator/ReducerValidator.java",
    "content": "package info.izumin.android.droidux.processor.validator;\n\nimport com.google.auto.common.MoreTypes;\nimport com.google.common.base.Function;\nimport com.google.common.collect.FluentIterable;\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.TypeName;\n\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.type.TypeMirror;\n\nimport info.izumin.android.droidux.UndoableState;\nimport info.izumin.android.droidux.processor.exception.InvalidReducerDeclarationException;\nimport info.izumin.android.droidux.processor.model.ReducerModel;\n\n/**\n * Created by izumin on 11/29/15.\n */\npublic final class ReducerValidator {\n    private ReducerValidator() {\n        throw new AssertionError(\"constructor of the utility class should not be called\");\n    }\n\n    public static void validate(ReducerModel model) {\n        if (!isValidClassName(model)) {\n            throw new InvalidReducerDeclarationException(\n                    \"@Reducer class name must end with \\\"\" + ReducerModel.CLASS_NAME_SUFFIX + \"\\\". \"\n                            + \"\\\"\" + model.getClassName().simpleName() + \"\\\" has invalid class name.\"\n            );\n        }\n\n        if (model.isUndoable() && !hasUndoableState(model.getStateElement())) {\n            throw new InvalidReducerDeclarationException(\n                    \"@Reducer class annotated with @Undoable must have the state implements \\\"UndoableState<T>\\\". \"\n                            + model.getState().simpleName() + \" state of \" + model.getClassName().simpleName() + \" does not implement it.\"\n            );\n        }\n    }\n\n    private static boolean isValidClassName(ReducerModel model) {\n        return model.getClassName().simpleName().endsWith(ReducerModel.CLASS_NAME_SUFFIX);\n    }\n\n    private static boolean hasUndoableState(TypeElement stateElement) {\n        return FluentIterable.from(stateElement.getInterfaces())\n                .transform(new Function<TypeMirror, TypeName>() {\n                    @Override\n                    public TypeName apply(TypeMirror input) {\n                        return ClassName.get(MoreTypes.asTypeElement(input));\n                    }\n                })\n                .contains(TypeName.get(UndoableState.class));\n    }\n}"
  },
  {
    "path": "droidux-processor/src/main/java/info/izumin/android/droidux/processor/validator/StoreValidator.java",
    "content": "package info.izumin.android.droidux.processor.validator;\n\nimport com.google.auto.common.MoreTypes;\nimport com.google.common.base.Predicate;\nimport com.google.common.collect.FluentIterable;\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.TypeName;\n\nimport javax.lang.model.type.TypeMirror;\n\nimport info.izumin.android.droidux.BaseStore;\nimport info.izumin.android.droidux.annotation.Reducer;\nimport info.izumin.android.droidux.annotation.Store;\nimport info.izumin.android.droidux.processor.exception.InvalidStoreDelcarationException;\nimport info.izumin.android.droidux.processor.model.StoreModel;\n\nimport static info.izumin.android.droidux.processor.util.AnnotationUtils.getTypesFromAnnotation;\n\n/**\n * Created by izumin on 11/29/15.\n */\npublic final class StoreValidator {\n    private StoreValidator() {\n        throw new AssertionError(\"constructor of the utility class should not be called\");\n    }\n\n    public static void validate(StoreModel model) {\n        if (!hasAnnotatedReducers(model)) {\n            throw new InvalidStoreDelcarationException(\n                    \"Values of @Store annotation must have only classes annotated with \\\"@Reducer\\\".\"\n                            + \"But \" + model.getInterfaceName().simpleName() + \" has invalid value.\"\n            );\n        }\n\n        if (!doesExtendBaseStore(model)) {\n            throw new InvalidStoreDelcarationException(\n                    \"The interface that is annotated @Store must extend \\\"BaseStore\\\".\"\n            );\n        }\n    }\n\n    private static boolean hasAnnotatedReducers(StoreModel model) {\n        return FluentIterable.from(getTypesFromAnnotation(model.getElement(), Store.class, \"value\"))\n                .filter(new Predicate<TypeMirror>() {\n                    @Override\n                    public boolean apply(TypeMirror input) {\n                        return MoreTypes.asTypeElement(input).getAnnotation(Reducer.class) == null;\n                    }\n                }).size() == 0;\n    }\n\n    private static boolean doesExtendBaseStore(StoreModel model) {\n        return FluentIterable.from(model.getElement().getInterfaces())\n                .anyMatch(new Predicate<TypeMirror>() {\n                    @Override\n                    public boolean apply(TypeMirror input) {\n                        return TypeName.get(BaseStore.class).equals(ClassName.get(input));\n                    }\n                });\n    }\n}"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/DroiduxProcessorTest.java",
    "content": "package info.izumin.android.droidux.processor;\n\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\n\nimport javax.tools.JavaFileObject;\n\nimport info.izumin.android.droidux.processor.fixture.Source;\nimport io.reactivex.BackpressureStrategy;\n\nimport static com.google.common.truth.Truth.assert_;\nimport static com.google.testing.compile.JavaFileObjects.forSourceLines;\nimport static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class DroiduxProcessorTest {\n    public static final String TAG = DroiduxProcessorTest.class.getSimpleName();\n\n    @Rule\n    public ExpectedException expectedException = ExpectedException.none();\n\n    private static void assertJavaSource(JavaFileObject target, JavaFileObject generated, JavaFileObject... rest) {\n        assert_().about(javaSource())\n                .that(target)\n                .processedWith(new DroiduxProcessor())\n                .compilesWithoutError()\n                .and()\n                .generatesSources(generated, rest);\n    }\n\n    @Test\n    public void singleReducer() {\n        assertJavaSource(\n                forSourceLines(\"RootStore\", Source.Counter.TARGET),\n                forSourceLines(\"DroiduxRootStore_CounterStoreImpl\", Source.StoreImpl.COUNTER),\n                forSourceLines(\"DroiduxRootStore\", Source.Counter.GENERATED_STORE)\n        );\n    }\n\n    @Test\n    public void singleReducer_with_BackpressureStrategySpecification() {\n        assertJavaSource(\n                forSourceLines(\"RootStore\", Source.CounterWithBackpressureStrategy.TARGET),\n                forSourceLines(\"DroiduxRootStore_CounterStoreImpl\", Source.StoreImpl.COUNTER),\n                forSourceLines(\"DroiduxRootStore\", Source.CounterWithBackpressureStrategy.GENERATED_STORE)\n        );\n    }\n\n    @Test\n    public void singleReducerBindable() {\n        assertJavaSource(\n                forSourceLines(\"RootStore\", Source.BindableCounter.TARGET),\n                forSourceLines(\"DroiduxRootStore_CounterStoreImpl\", Source.StoreImpl.COUNTER),\n                forSourceLines(\"DroiduxRootStore\", Source.BindableCounter.GENERATED_STORE)\n        );\n    }\n\n    @Test\n    public void combinedTwoReducers() {\n        assertJavaSource(\n                forSourceLines(\"RootStore\", Source.CombinedTwoReducers.TARGET),\n                forSourceLines(\"DroiduxRootStore_CounterStoreImpl\", Source.StoreImpl.COUNTER),\n                forSourceLines(\"DroiduxRootStore_TodoListStoreImpl\", Source.StoreImpl.TODO_LIST),\n                forSourceLines(\"DroiduxRootStore\", Source.CombinedTwoReducers.GENERATED)\n        );\n    }\n\n    @Test\n    public void combinedReducerAndBindableReducer() {\n        assertJavaSource(\n                forSourceLines(\"RootStore\", Source.CombinedReducerAndBindableReducer.TARGET),\n                forSourceLines(\"DroiduxRootStore_CounterStoreImpl\", Source.StoreImpl.COUNTER),\n                forSourceLines(\"DroiduxRootStore_TodoListStoreImpl\", Source.StoreImpl.TODO_LIST),\n                forSourceLines(\"DroiduxRootStore\", Source.CombinedReducerAndBindableReducer.GENERATED)\n        );\n    }\n\n    @Test\n    public void dispatchableMethodTakesWrongStateType() {\n        expectedException.expect(RuntimeException.class);\n        expectedException.expectMessage(\n                \"@Dispatchable method can have arguments only state or action. \"\n                        + \"CounterReducer#increment() has more than one invalid argument.\"\n        );\n        assertJavaSource(\n                forSourceLines(\"CounterStore\", Source.DispatchableTakesWrongStateType.TARGET),\n                forSourceLines(\"DroiduxCounterStore_CounterStoreImpl\", Source.EMPTY),\n                forSourceLines(\"DroiduxCounterStore\", Source.EMPTY)\n        );\n    }\n\n    @Test\n    public void dispatchableMethodTakesWrongActionType() {\n        expectedException.expect(RuntimeException.class);\n        expectedException.expectMessage(\n                \"@Dispatchable method can have arguments only state or action. \"\n                        + \"TodoListReducer#addItem() has more than one invalid argument.\"\n        );\n        assertJavaSource(\n                forSourceLines(\"TodoListStore\", Source.DispatchableTakesWrongActionType.TARGET),\n                forSourceLines(\"DroiduxTodoListStore_TodoListStoreImpl\", Source.EMPTY),\n                forSourceLines(\"DroiduxTodoListStore\", Source.EMPTY)\n        );\n    }\n\n\n    @Test\n    public void dispatchableMethodReturnsWrongType() {\n        expectedException.expect(RuntimeException.class);\n        expectedException.expectMessage(\n                \"@Dispatchable method can have arguments only state or action. \"\n                        + \"CounterReducer#increment() has more than one invalid argument.\"\n        );\n        assertJavaSource(\n                forSourceLines(\"CounterStore\", Source.DispatchableTakesExtraArguments.TARGET),\n                forSourceLines(\"DroiduxCounterStore_CounterStoreImpl\", Source.EMPTY),\n                forSourceLines(\"DroiduxCounterStore\", Source.EMPTY)\n        );\n    }\n\n    @Test\n    public void dispatchableMethodShouldReturnState() {\n        expectedException.expect(RuntimeException.class);\n        expectedException.expectMessage(\n                \"@Dispatchable method must return new state. \"\n                        + \"But CounterReducer#increment() returns invalid type.\"\n        );\n        assertJavaSource(\n                forSourceLines(\"CounterStore\", Source.DispatchableMethosReturnsWrongType.TARGET),\n                forSourceLines(\"DroiduxCounterStore_CounterStoreImpl\", Source.EMPTY),\n                forSourceLines(\"DroiduxCounterStore\", Source.EMPTY)\n        );\n    }\n\n    @Test\n    public void reducerWithoutSuffix() {\n        expectedException.expect(RuntimeException.class);\n        expectedException.expectMessage(\n                \"@Reducer class name must end with \\\"Reducer\\\". \\\"CounterReduce\\\" has invalid class name.\"\n        );\n        assertJavaSource(\n                forSourceLines(\"CounterStore\", Source.ReducerWithoutSuffix.TARGET),\n                forSourceLines(\"DroiduxCounterStore_CounterStoreImpl\", Source.EMPTY),\n                forSourceLines(\"DroiduxCounterStore\", Source.EMPTY)\n        );\n    }\n\n    @Test\n    public void undoableReducerWithoutUndoableState() {\n        expectedException.expect(RuntimeException.class);\n        expectedException.expectMessage(\n                \"@Reducer class annotated with @Undoable must have the state implements \\\"UndoableState<T>\\\". \"\n                        + \"Counter state of CounterReducer does not implement it.\"\n        );\n        assertJavaSource(\n                forSourceLines(\"CounterStore\", Source.UndoableReducerWithoutUndoableState.TARGET),\n                forSourceLines(\"DroiduxCounterStore_CounterStoreImpl\", Source.EMPTY),\n                forSourceLines(\"DroiduxCounterStore\", Source.EMPTY)\n        );\n    }\n\n    @Test\n    public void storeHasClassThatIsNotAnnotatedWithReducer() {\n        expectedException.expect(RuntimeException.class);\n        expectedException.expectMessage(\n                \"Values of @Store annotation must have only classes annotated with \\\"@Reducer\\\".\"\n                        + \"But CounterStore has invalid value.\"\n        );\n        assertJavaSource(\n                forSourceLines(\"CounterStore\", Source.StoreHasInvalidValue.TARGET),\n                forSourceLines(\"DroiduxCounterStore_CounterStoreImpl\", Source.EMPTY),\n                forSourceLines(\"DroiduxCounterStore\", Source.EMPTY)\n        );\n    }\n\n    @Test\n    public void storeNotExtendBaseStore() {\n        expectedException.expect(RuntimeException.class);\n        expectedException.expectMessage(\n                \"The interface that is annotated @Store must extend \\\"BaseStore\\\".\"\n        );\n        assertJavaSource(\n                forSourceLines(\"CounterStore\", Source.StoreNotExtendsBaseStore.TARGET),\n                forSourceLines(\"DroiduxCounterStore_CounterStoreImpl\", Source.EMPTY),\n                forSourceLines(\"DroiduxCounterStore\", Source.EMPTY)\n        );\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/Counter.java",
    "content": "package info.izumin.android.droidux.processor.fixture;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class Counter {\n    public static final String TAG = Counter.class.getSimpleName();\n\n    private int count;\n\n    public Counter(int count) {\n        this.count = count;\n    }\n\n    public int getCount() {\n        return count;\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/CounterReducer.java",
    "content": "package info.izumin.android.droidux.processor.fixture;\n\nimport info.izumin.android.droidux.annotation.Dispatchable;\nimport info.izumin.android.droidux.annotation.Reducer;\nimport info.izumin.android.droidux.processor.fixture.action.ClearCountAction;\nimport info.izumin.android.droidux.processor.fixture.action.IncrementCountAction;\nimport info.izumin.android.droidux.processor.fixture.action.InitializeCountAction;\nimport info.izumin.android.droidux.processor.fixture.action.SquareCountAction;\n\n/**\n * Created by izumin on 11/3/15.\n */\n@Reducer(Counter.class)\npublic class CounterReducer {\n    @Dispatchable(IncrementCountAction.class)\n    public Counter increment(Counter state, IncrementCountAction action) {\n        return new Counter(state.getCount() + action.getValue());\n    }\n\n    @Dispatchable(SquareCountAction.class)\n    public Counter square(Counter state) {\n        return new Counter(state.getCount() * state.getCount());\n    }\n\n    @Dispatchable(InitializeCountAction.class)\n    public Counter initialize(InitializeCountAction action) {\n        return new Counter(action.getValue());\n    }\n\n    @Dispatchable(ClearCountAction.class)\n    public Counter clear() {\n        return new Counter(0);\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/Source.java",
    "content": "package info.izumin.android.droidux.processor.fixture;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic final class Source {\n    public static final String TAG = Source.class.getSimpleName();\n\n    public static final String[] EMPTY = {};\n\n    public static final class StoreImpl {\n        public static final String[] COUNTER = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.StoreImpl;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.ClearCountAction;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.IncrementCountAction;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.InitializeCountAction;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.SquareCountAction;\",\n                \"\",\n                \"final class DroiduxRootStore_CounterStoreImpl extends StoreImpl<Counter, CounterReducer> {\",\n                \"    protected DroiduxRootStore_CounterStoreImpl(Counter state, CounterReducer reducer) {\",\n                \"        super(state, reducer);\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    protected void dispatch(Action action) {\",\n                \"        Class<? extends Action> actionClass = action.getClass();\",\n                \"        Counter result = null;\",\n                \"        if (IncrementCountAction.class.isAssignableFrom(actionClass)) {\",\n                \"            result = getReducer().increment(getState(), (IncrementCountAction) action);\",\n                \"        }\",\n                \"        if (SquareCountAction.class.isAssignableFrom(actionClass)) {\",\n                \"            result = getReducer().square(getState());\",\n                \"        }\",\n                \"        if (InitializeCountAction.class.isAssignableFrom(actionClass)) {\",\n                \"            result = getReducer().initialize((InitializeCountAction) action);\",\n                \"        }\",\n                \"        if (ClearCountAction.class.isAssignableFrom(actionClass)) {\",\n                \"            result = getReducer().clear();\",\n                \"        }\",\n                \"        if (result != null) {\",\n                \"            setState(result);\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n\n        public static final String[] TODO_LIST = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.UndoableStoreImpl;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoList;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoListReducer;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.AddTodoItemAction;\",\n                \"\",\n                \"final class DroiduxRootStore_TodoListStoreImpl extends UndoableStoreImpl<TodoList, TodoListReducer> {\",\n                \"    protected DroiduxCounterStore_CounterStoreImpl(TodoList state, TodoListReducer reducer) {\",\n                \"        super(state, reducer);\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    protected void dispatch(Action action) {\",\n                \"        super.dispatch(action);\",\n                \"        Class<? extends Action> actionClass = action.getClass();\",\n                \"        TodoList result = null;\",\n                \"        if (AddTodoItemAction.class.isAssignableFrom(actionClass)) {\",\n                \"            result = getReducer().add(getState().clone(), (AddTodoItemAction) action);\",\n                \"        }\",\n                \"        if (result != null) {\",\n                \"            setState(result);\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class Counter {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import io.reactivex.Flowable;\",\n                \"@Store({CounterReducer.class})\",\n                \"public interface RootStore extends BaseStore {\",\n                \"    Counter counter();\",\n                \"    Flowable<Counter> observeCounter();\",\n                \"}\"\n        };\n\n        public static final String[] GENERATED_STORE = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"\",\n                \"import android.databinding.BaseObservable;\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.Dispatcher;\",\n                \"import info.izumin.android.droidux.Middleware;\",\n                \"import info.izumin.android.droidux.exception.NotInitializedException;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import io.reactivex.Flowable;\",\n                \"import java.util.ArrayList;\",\n                \"import java.util.List;\",\n                \"\",\n                \"public final class DroiduxRootStore extends BaseObservable implements RootStore {\",\n                \"    private final DroiduxRootStore_CounterStoreImpl counterStoreImpl;\",\n                \"    private final Dispatcher dispatcher;\",\n                \"\",\n                \"    protected DroiduxRootStore(final Builder builder) {\",\n                \"        counterStoreImpl= new DroiduxRootStore_CounterStoreImpl(builder.counter, builder.counterReducer);\",\n                \"        dispatcher = new Dispatcher(builder.middlewares, counterStoreImpl);\",\n                \"        for (Middleware middleware : builder.middlewares) {\",\n                \"            middleware.onAttach(this, dispatcher);\",\n                \"        }\",\n                \"    }\",\n                \"\",\n                \"    public static Builder builder() {\",\n                \"        return new Builder();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Counter counter() {\",\n                \"        return counterStoreImpl.getState();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Counter> observeCounter() {\",\n                \"        return counterStoreImpl.observe();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Action> dispatch(Action action) {\",\n                \"        return dispatcher.dispatch(action)\",\n                \"    }\",\n                \"\",\n                \"    public static final class Builder {\",\n                \"        private final List<Middleware> middlewares;\",\n                \"        private CounterReducer counterReducer;\",\n                \"        private Counter counter;\",\n                \"\",\n                \"        private Builder() {\",\n                \"            middlewares = new ArrayList<>();\",\n                \"        }\",\n                \"\",\n                \"        public Builder addMiddleware(Middleware middleware) {\",\n                \"            middlewares.add(middleware);\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(CounterReducer counterReducer) {\",\n                \"            this.counterReducer = counterReducer;\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(CounterReducer counterReducer, Counter counter) {\",\n                \"            this.counter = counter;\",\n                \"            return setReducer(counterReducer);\",\n                \"        }\",\n                \"\",\n                \"        public DroiduxRootStore build() {\",\n                \"            if (counterReducer == null) {\",\n                \"                throw new NotInitializedException(\\\"CounterReducer has not been initialized.\\\");\",\n                \"            }\",\n                \"            return new DroiduxRootStore(this);\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class CounterWithBackpressureStrategy {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import io.reactivex.BackpressureStrategy;\",\n                \"import io.reactivex.Flowable;\",\n                \"@Store({CounterReducer.class})\",\n                \"public interface RootStore extends BaseStore {\",\n                \"    Counter counter();\",\n                \"    Flowable<Counter> observeCounter();\",\n                \"    Flowable<Counter> observeCounter(BackpressureStrategy strategy);\",\n                \"}\"\n        };\n\n        public static final String[] GENERATED_STORE = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"\",\n                \"import android.databinding.BaseObservable;\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.Dispatcher;\",\n                \"import info.izumin.android.droidux.Middleware;\",\n                \"import info.izumin.android.droidux.exception.NotInitializedException;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import io.reactivex.BackpressureStrategy;\",\n                \"import io.reactivex.Flowable;\",\n                \"import java.util.ArrayList;\",\n                \"import java.util.List;\",\n                \"\",\n                \"public final class DroiduxRootStore extends BaseObservable implements RootStore {\",\n                \"    private final DroiduxRootStore_CounterStoreImpl counterStoreImpl;\",\n                \"    private final Dispatcher dispatcher;\",\n                \"\",\n                \"    protected DroiduxRootStore(final Builder builder) {\",\n                \"        counterStoreImpl= new DroiduxRootStore_CounterStoreImpl(builder.counter, builder.counterReducer);\",\n                \"        dispatcher = new Dispatcher(builder.middlewares, counterStoreImpl);\",\n                \"        for (Middleware middleware : builder.middlewares) {\",\n                \"            middleware.onAttach(this, dispatcher);\",\n                \"        }\",\n                \"    }\",\n                \"\",\n                \"    public static Builder builder() {\",\n                \"        return new Builder();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Counter counter() {\",\n                \"        return counterStoreImpl.getState();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Counter> observeCounter() {\",\n                \"        return counterStoreImpl.observe();\",\n                \"    }\",\n                \"\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Counter> observeCounter(BackpressureStrategy strategy) {\",\n                \"        return counterStoreImpl.observe(strategy);\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Action> dispatch(Action action) {\",\n                \"        return dispatcher.dispatch(action)\",\n                \"    }\",\n                \"\",\n                \"    public static final class Builder {\",\n                \"        private final List<Middleware> middlewares;\",\n                \"        private CounterReducer counterReducer;\",\n                \"        private Counter counter;\",\n                \"\",\n                \"        private Builder() {\",\n                \"            middlewares = new ArrayList<>();\",\n                \"        }\",\n                \"\",\n                \"        public Builder addMiddleware(Middleware middleware) {\",\n                \"            middlewares.add(middleware);\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(CounterReducer counterReducer) {\",\n                \"            this.counterReducer = counterReducer;\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(CounterReducer counterReducer, Counter counter) {\",\n                \"            this.counter = counter;\",\n                \"            return setReducer(counterReducer);\",\n                \"        }\",\n                \"\",\n                \"        public DroiduxRootStore build() {\",\n                \"            if (counterReducer == null) {\",\n                \"                throw new NotInitializedException(\\\"CounterReducer has not been initialized.\\\");\",\n                \"            }\",\n                \"            return new DroiduxRootStore(this);\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class BindableCounter {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import android.databinding.Bindable;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import io.reactivex.Flowable;\",\n                \"@Store({CounterReducer.class})\",\n                \"public interface RootStore extends BaseStore, android.databinding.Observable {\",\n                \"    @Bindable Counter counter();\",\n                \"    Flowable<Counter> observeCounter();\",\n                \"}\"\n        };\n\n        public static final String[] GENERATED_STORE = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"\",\n                \"import android.databinding.BaseObservable;\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.Dispatcher;\",\n                \"import info.izumin.android.droidux.Middleware;\",\n                \"import info.izumin.android.droidux.OnStateChangedListener;\",\n                \"import info.izumin.android.droidux.exception.NotInitializedException;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import io.reactivex.Flowable;\",\n                \"import java.util.ArrayList;\",\n                \"import java.util.List;\",\n                \"\",\n                \"public final class DroiduxRootStore extends BaseObservable implements RootStore {\",\n                \"    private final DroiduxRootStore_CounterStoreImpl counterStoreImpl;\",\n                \"    private final Dispatcher dispatcher;\",\n                \"\",\n                \"    protected DroiduxRootStore(final Builder builder) {\",\n                \"        counterStoreImpl = new DroiduxRootStore_CounterStoreImpl(builder.counter, builder.counterReducer);\",\n                \"        counterStoreImpl.addListener(new OnStateChangedListener<Counter>() {\",\n                \"            @Override\",\n                \"            public void onStateChanged(Counter counter) {\",\n                \"                notifyPropertyChanged(builder.counterFieldId);\",\n                \"            }\",\n                \"        });\",\n                \"        dispatcher = new Dispatcher(builder.middlewares, counterStoreImpl);\",\n                \"        for (Middleware middleware : builder.middlewares) {\",\n                \"            middleware.onAttach(this, dispatcher);\",\n                \"        }\",\n                \"    }\",\n                \"\",\n                \"    public static Builder builder() {\",\n                \"        return new Builder();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Counter counter() {\",\n                \"        return counterStoreImpl.getState();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Counter> observeCounter() {\",\n                \"        return counterStoreImpl.observe();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Action> dispatch(Action action) {\",\n                \"        return dispatcher.dispatch(action)\",\n                \"    }\",\n                \"\",\n                \"    public static final class Builder {\",\n                \"        private final List<Middleware> middlewares;\",\n                \"        private CounterReducer counterReducer;\",\n                \"        private Counter counter;\",\n                \"        private int counterFieldId;\",\n                \"\",\n                \"        private Builder() {\",\n                \"            middlewares = new ArrayList<>();\",\n                \"        }\",\n                \"\",\n                \"        public Builder addMiddleware(Middleware middleware) {\",\n                \"            middlewares.add(middleware);\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(CounterReducer counterReducer, int counterFieldId) {\",\n                \"            this.counterFieldId = counterFieldId;\",\n                \"            this.counterReducer = counterReducer;\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(CounterReducer counterReducer, Counter counter, int counterFieldId) {\",\n                \"            this.counter = counter;\",\n                \"            return setReducer(counterReducer, counterFieldId);\",\n                \"        }\",\n                \"\",\n                \"        public DroiduxRootStore build() {\",\n                \"            if (counterReducer == null) {\",\n                \"                throw new NotInitializedException(\\\"CounterReducer has not been initialized.\\\");\",\n                \"            }\",\n                \"            return new DroiduxRootStore(this);\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class CombinedTwoReducers {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoListReducer;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoList;\",\n                \"import io.reactivex.Flowable;\",\n                \"@Store({CounterReducer.class, TodoListReducer.class})\",\n                \"public interface RootStore extends BaseStore {\",\n                \"    Counter counter();\",\n                \"    Flowable<Counter> observeCounter();\",\n                \"    TodoList todoList();\",\n                \"    Flowable<TodoList> observeTodoList();\",\n                \"}\"\n        };\n\n        public static final String[] GENERATED = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"\",\n                \"import android.databinding.BaseObservable;\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.Dispatcher;\",\n                \"import info.izumin.android.droidux.Middleware;\",\n                \"import info.izumin.android.droidux.exception.NotInitializedException;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoList;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoListReducer;\",\n                \"import io.reactivex.Flowable;\",\n                \"import java.util.ArrayList;\",\n                \"import java.util.List;\",\n                \"\",\n                \"public final class DroiduxRootStore extends BaseObservable implements RootStore {\",\n                \"    private final DroiduxRootStore_CounterStoreImpl counterStoreImpl;\",\n                \"    private final DroiduxRootStore_TodoListStoreImpl todoListStoreImpl;\",\n                \"    private final Dispatcher dispatcher;\",\n                \"\",\n                \"    protected DroiduxRootStore(final Builder builder) {\",\n                \"        counterStoreImpl= new DroiduxRootStore_CounterStoreImpl(builder.counter, builder.counterReducer);\",\n                \"        todoListStoreImpl= new DroiduxRootStore_TodoListStoreImpl(builder.todoList, builder.todoListReducer);\",\n                \"        dispatcher = new Dispatcher(builder.middlewares, counterStoreImpl, todoListStoreImpl);\",\n                \"        for (Middleware middleware : builder.middlewares) {\",\n                \"            middleware.onAttach(this, dispatcher);\",\n                \"        }\",\n                \"    }\",\n                \"\",\n                \"    public static Builder builder() {\",\n                \"        return new Builder();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Counter counter() {\",\n                \"        return counterStoreImpl.getState();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Counter> observeCounter() {\",\n                \"        return counterStoreImpl.observe();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public TodoList todoList() {\",\n                \"        return todoListStoreImpl.getState();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<TodoList> observeTodoList() {\",\n                \"        return todoListStoreImpl.observe();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Action> dispatch(Action action) {\",\n                \"        return dispatcher.dispatch(action)\",\n                \"    }\",\n                \"\",\n                \"    public static final class Builder {\",\n                \"        private final List<Middleware> middlewares;\",\n                \"        private CounterReducer counterReducer;\",\n                \"        private TodoListReducer todoListReducer;\",\n                \"        private Counter counter;\",\n                \"        private TodoList todoList;\",\n                \"        \",\n                \"        private Builder() {\",\n                \"            middlewares = new ArrayList<>();\",\n                \"        }\",\n                \"\",\n                \"        public Builder addMiddleware(Middleware middleware) {\",\n                \"            middlewares.add(middleware);\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(CounterReducer counterReducer) {\",\n                \"            this.counterReducer = counterReducer;\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(TodoListReducer todoListReducer) {\",\n                \"            this.todoListReducer = todoListReducer;\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(CounterReducer counterReducer, Counter counter) {\",\n                \"            this.counter = counter;\",\n                \"            return setReducer(counterReducer);\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(TodoListReducer todoListReducer, TodoList todoList) {\",\n                \"            this.todoList = todoList;\",\n                \"            return setReducer(todoListReducer);\",\n                \"        }\",\n                \"\",\n                \"        public DroiduxRootStore build() {\",\n                \"            if (counterReducer == null) {\",\n                \"                throw new NotInitializedException(\\\"CounterReducer has not been initialized.\\\");\",\n                \"            }\",\n                \"            if (todoListReducer == null) {\",\n                \"                throw new NotInitializedException(\\\"TodoListReducer has not been initialized.\\\");\",\n                \"            }\",\n                \"            return new DroiduxRootStore(this);\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class CombinedReducerAndBindableReducer {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import android.databinding.Bindable;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoListReducer;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoList;\",\n                \"import io.reactivex.Flowable;\",\n                \"@Store({CounterReducer.class, TodoListReducer.class})\",\n                \"public interface RootStore extends BaseStore, android.databinding.Observable {\",\n                \"    Counter counter();\",\n                \"    Flowable<Counter> observeCounter();\",\n                \"    @Bindable TodoList todoList();\",\n                \"    Flowable<TodoList> observeTodoList();\",\n                \"}\"\n        };\n\n        public static final String[] GENERATED = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"\",\n                \"import android.databinding.BaseObservable;\",\n                \"import info.izumin.android.droidux.Action;\",\n                \"import info.izumin.android.droidux.Dispatcher;\",\n                \"import info.izumin.android.droidux.Middleware;\",\n                \"import info.izumin.android.droidux.OnStateChangedListener;\",\n                \"import info.izumin.android.droidux.exception.NotInitializedException;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"import info.izumin.android.droidux.processor.fixture.CounterReducer;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoList;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoListReducer;\",\n                \"import io.reactivex.Flowable;\",\n                \"import java.util.ArrayList;\",\n                \"import java.util.List;\",\n                \"\",\n                \"public final class DroiduxRootStore extends BaseObservable implements RootStore {\",\n                \"    private final DroiduxRootStore_CounterStoreImpl counterStoreImpl;\",\n                \"    private final DroiduxRootStore_TodoListStoreImpl todoListStoreImpl;\",\n                \"    private final Dispatcher dispatcher;\",\n                \"\",\n                \"    protected DroiduxRootStore(final Builder builder) {\",\n                \"        counterStoreImpl= new DroiduxRootStore_CounterStoreImpl(builder.counter, builder.counterReducer);\",\n                \"        todoListStoreImpl= new DroiduxRootStore_TodoListStoreImpl(builder.todoList, builder.todoListReducer);\",\n                \"        todoListStoreImpl.addListener(new OnStateChangedListener<TodoList>() {\",\n                \"            @Override\",\n                \"            public void onStateChanged(TodoList todoList) {\",\n                \"                notifyPropertyChanged(builder.todoListFieldId);\",\n                \"            }\",\n                \"        });\",\n                \"        dispatcher = new Dispatcher(builder.middlewares, counterStoreImpl, todoListStoreImpl);\",\n                \"        for (Middleware middleware : builder.middlewares) {\",\n                \"            middleware.onAttach(this, dispatcher);\",\n                \"        }\",\n                \"    }\",\n                \"\",\n                \"    public static Builder builder() {\",\n                \"        return new Builder();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Counter counter() {\",\n                \"        return counterStoreImpl.getState();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Counter> observeCounter() {\",\n                \"        return counterStoreImpl.observe();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public TodoList todoList() {\",\n                \"        return todoListStoreImpl.getState();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<TodoList> observeTodoList() {\",\n                \"        return todoListStoreImpl.observe();\",\n                \"    }\",\n                \"\",\n                \"    @Override\",\n                \"    public Flowable<Action> dispatch(Action action) {\",\n                \"        return dispatcher.dispatch(action)\",\n                \"    }\",\n                \"\",\n                \"    public static final class Builder {\",\n                \"        private final List<Middleware> middlewares;\",\n                \"        private CounterReducer counterReducer;\",\n                \"        private TodoListReducer todoListReducer;\",\n                \"        private Counter counter;\",\n                \"        private TodoList todoList;\",\n                \"        private int todoListFieldId;\",\n                \"        \",\n                \"        private Builder() {\",\n                \"            middlewares = new ArrayList<>();\",\n                \"        }\",\n                \"\",\n                \"        public Builder addMiddleware(Middleware middleware) {\",\n                \"            middlewares.add(middleware);\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(CounterReducer counterReducer) {\",\n                \"            this.counterReducer = counterReducer;\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(TodoListReducer todoListReducer, int todoListFieldId) {\",\n                \"            this.todoListFieldId = todoListFieldId;\",\n                \"            this.todoListReducer = todoListReducer;\",\n                \"            return this;\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(CounterReducer counterReducer, Counter counter) {\",\n                \"            this.counter = counter;\",\n                \"            return setReducer(counterReducer);\",\n                \"        }\",\n                \"\",\n                \"        public Builder setReducer(TodoListReducer todoListReducer, TodoList todoList, int todoListFieldId) {\",\n                \"            this.todoList = todoList;\",\n                \"            return setReducer(todoListReducer, todoListFieldId);\",\n                \"        }\",\n                \"\",\n                \"        public DroiduxRootStore build() {\",\n                \"            if (counterReducer == null) {\",\n                \"                throw new NotInitializedException(\\\"CounterReducer has not been initialized.\\\");\",\n                \"            }\",\n                \"            if (todoListReducer == null) {\",\n                \"                throw new NotInitializedException(\\\"TodoListReducer has not been initialized.\\\");\",\n                \"            }\",\n                \"            return new DroiduxRootStore(this);\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class DispatchableTakesWrongStateType {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.annotation.Dispatchable;\",\n                \"import info.izumin.android.droidux.annotation.Reducer;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.IncrementCountAction;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"@Store(CounterStore.CounterReducer.class)\",\n                \"public interface CounterStore extends BaseStore {\",\n                \"    @Reducer(Counter.class)\",\n                \"    public static class CounterReducer {\",\n                \"        @Dispatchable(IncrementCountAction.class)\",\n                \"        public Counter increment(Object state, IncrementCountAction action) {\",\n                \"            return null;\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class DispatchableTakesWrongActionType {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.annotation.Dispatchable;\",\n                \"import info.izumin.android.droidux.annotation.Reducer;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.AddTodoItemAction;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.CompleteTodoItemAction;\",\n                \"import info.izumin.android.droidux.processor.fixture.TodoList;\",\n                \"@Store(TodoListStore.TodoListReducer.class)\",\n                \"public interface TodoListStore extends BaseStore {\",\n                \"    @Reducer(TodoList.class)\",\n                \"    public static class TodoListReducer {\",\n                \"        @Dispatchable(CompleteTodoItemAction.class)\",\n                \"        public TodoList addItem(TodoList state, AddTodoItemAction action) {\",\n                \"            return null;\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class DispatchableTakesExtraArguments {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.annotation.Dispatchable;\",\n                \"import info.izumin.android.droidux.annotation.Reducer;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.IncrementCountAction;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"@Store(CounterStore.CounterReducer.class)\",\n                \"public interface CounterStore extends BaseStore {\",\n                \"    @Reducer(Counter.class)\",\n                \"    public static class CounterReducer {\",\n                \"        @Dispatchable(IncrementCountAction.class)\",\n                \"        public Counter increment(Counter state, IncrementCountAction action, String extra) {\",\n                \"            return null;\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class DispatchableMethosReturnsWrongType{\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.annotation.Dispatchable;\",\n                \"import info.izumin.android.droidux.annotation.Reducer;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.IncrementCountAction;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"@Store(CounterStore.CounterReducer.class)\",\n                \"public interface CounterStore extends BaseStore {\",\n                \"    @Reducer(Counter.class)\",\n                \"    public static class CounterReducer {\",\n                \"        @Dispatchable(IncrementCountAction.class)\",\n                \"        public Object increment(Counter state, IncrementCountAction action) {\",\n                \"            return null;\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class ReducerWithoutSuffix {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.annotation.Dispatchable;\",\n                \"import info.izumin.android.droidux.annotation.Reducer;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.processor.fixture.action.IncrementCountAction;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"@Store(CounterStore.CounterReduce.class)\",\n                \"public interface CounterStore extends BaseStore {\",\n                \"    @Reducer(Counter.class)\",\n                \"    public static class CounterReduce {\",\n                \"        @Dispatchable(IncrementCountAction.class)\",\n                \"        public Counter increment(Counter state, IncrementCountAction action) {\",\n                \"            return null;\",\n                \"        }\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class UndoableReducerWithoutUndoableState {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.annotation.Reducer;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.annotation.Undoable;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"@Store(CounterStore.CounterReducer.class)\",\n                \"public interface CounterStore extends BaseStore {\",\n                \"    @Undoable\",\n                \"    @Reducer(Counter.class)\",\n                \"    public static class CounterReducer {\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class StoreHasInvalidValue {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"@Store(CounterStore.CounterReducer.class)\",\n                \"public interface CounterStore extends BaseStore {\",\n                \"    public static class CounterReducer {\",\n                \"    }\",\n                \"}\"\n        };\n    }\n\n    public static class StoreNotExtendsBaseStore {\n        public static final String[] TARGET = {\n                \"package info.izumin.android.droidux.sample;\",\n                \"import info.izumin.android.droidux.BaseStore;\",\n                \"import info.izumin.android.droidux.annotation.Reducer;\",\n                \"import info.izumin.android.droidux.annotation.Store;\",\n                \"import info.izumin.android.droidux.processor.fixture.Counter;\",\n                \"@Store(CounterStore.CounterReducer.class)\",\n                \"public interface CounterStore {\",\n                \"    @Reducer(Counter.class)\",\n                \"    public static class CounterReducer {\",\n                \"    }\",\n                \"}\"\n        };\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/TodoList.java",
    "content": "package info.izumin.android.droidux.processor.fixture;\n\nimport java.util.ArrayList;\n\nimport info.izumin.android.droidux.UndoableState;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class TodoList extends ArrayList<TodoList.Item> implements UndoableState<TodoList> {\n\n    @Override\n    public TodoList clone() {\n        return (TodoList) super.clone();\n    }\n\n    public static class Item {\n        private String body;\n        private boolean isCompleted;\n\n        public Item(String body) {\n            this.body = body;\n            this.isCompleted = false;\n        }\n\n        public String getBody() {\n            return body;\n        }\n\n        public boolean isCompleted() {\n            return isCompleted;\n        }\n\n        public void setCompleted(boolean isCompleted) {\n            this.isCompleted = isCompleted;\n        }\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/TodoListReducer.java",
    "content": "package info.izumin.android.droidux.processor.fixture;\n\nimport info.izumin.android.droidux.annotation.Dispatchable;\nimport info.izumin.android.droidux.annotation.Reducer;\nimport info.izumin.android.droidux.annotation.Undoable;\nimport info.izumin.android.droidux.processor.fixture.action.AddTodoItemAction;\n\n/**\n * Created by izumin on 11/3/15.\n */\n@Undoable\n@Reducer(TodoList.class)\npublic class TodoListReducer {\n    @Dispatchable(AddTodoItemAction.class)\n    public TodoList add(TodoList state, AddTodoItemAction action) {\n        TodoList newState = new TodoList();\n        newState.addAll(state);\n        newState.add(new TodoList.Item(action.getValue()));\n        return newState;\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/action/AddTodoItemAction.java",
    "content": "package info.izumin.android.droidux.processor.fixture.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class AddTodoItemAction implements Action {\n    public static final String TAG = AddTodoItemAction.class.getSimpleName();\n\n    private final String value;\n\n    public AddTodoItemAction(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return value;\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/action/ClearCountAction.java",
    "content": "package info.izumin.android.droidux.processor.fixture.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class ClearCountAction implements Action {\n    public static final String TAG = ClearCountAction.class.getSimpleName();\n\n    public ClearCountAction() {\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/action/CompleteTodoItemAction.java",
    "content": "package info.izumin.android.droidux.processor.fixture.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class CompleteTodoItemAction implements Action {\n    public static final String TAG = CompleteTodoItemAction.class.getSimpleName();\n\n    private final int id;\n\n    public CompleteTodoItemAction(int id) {\n        this.id = id;\n    }\n\n    public int getId() {\n        return id;\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/action/IncrementCountAction.java",
    "content": "package info.izumin.android.droidux.processor.fixture.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class IncrementCountAction implements Action {\n    public static final String TAG = IncrementCountAction.class.getSimpleName();\n\n    private final int value;\n\n    public IncrementCountAction(int value) {\n        this.value = value;\n    }\n\n    public int getValue() {\n        return value;\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/action/InitializeCountAction.java",
    "content": "package info.izumin.android.droidux.processor.fixture.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class InitializeCountAction implements Action {\n    public static final String TAG = InitializeCountAction.class.getSimpleName();\n\n    private final int value;\n\n    public InitializeCountAction(int value) {\n        this.value = value;\n    }\n\n    public int getValue() {\n        return value;\n    }\n}\n"
  },
  {
    "path": "droidux-processor/src/test/java/info/izumin/android/droidux/processor/fixture/action/SquareCountAction.java",
    "content": "package info.izumin.android.droidux.processor.fixture.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/2/15.\n */\npublic class SquareCountAction implements Action {\n    public static final String TAG = SquareCountAction.class.getSimpleName();\n\n    public SquareCountAction() {\n    }\n}\n"
  },
  {
    "path": "examples/counter/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "examples/counter/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion project.compileSdkVersion\n    buildToolsVersion project.buildToolsVersion\n\n    defaultConfig {\n        applicationId \"info.izumin.android.droidux.example.counter\"\n        minSdkVersion project.minSdkVersion\n        targetSdkVersion project.targetSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    packagingOptions {\n        exclude 'META-INF/services/javax.annotation.processing.Processor'\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    dataBinding {\n        enabled = true\n    }\n}\n\ndependencies {\n    compile \"io.reactivex.rxjava2:rxjava:${project.rxJava2Version}\"\n    compile \"io.reactivex.rxjava2:rxandroid:${project.rxAndroid2Version}\"\n    compile project(':droidux')\n    annotationProcessor project(':droidux-processor')\n    compile project(':middlewares:droidux-thunk')\n    compile \"com.android.support:appcompat-v7:${project.supportLibrariesVersion}\"\n    compile \"com.android.support:design:${project.supportLibrariesVersion}\"\n}\n"
  },
  {
    "path": "examples/counter/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 /usr/local/opt/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"
  },
  {
    "path": "examples/counter/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=\"info.izumin.android.droidux.example.counter\">\n\n    <application android:allowBackup=\"true\" android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\" android:supportsRtl=\"true\" android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/counter/src/main/java/info/izumin/android/droidux/example/counter/Counter.java",
    "content": "package info.izumin.android.droidux.example.counter;\n\n/**\n * Created by izumin on 12/6/15.\n */\npublic class Counter {\n    public static final String TAG = Counter.class.getSimpleName();\n\n    private final int count;\n\n    public Counter(int count) {\n        this.count = count;\n    }\n\n    public int getCount() {\n        return count;\n    }\n}\n"
  },
  {
    "path": "examples/counter/src/main/java/info/izumin/android/droidux/example/counter/CounterReducer.java",
    "content": "package info.izumin.android.droidux.example.counter;\n\nimport info.izumin.android.droidux.annotation.Dispatchable;\nimport info.izumin.android.droidux.annotation.Reducer;\nimport info.izumin.android.droidux.example.counter.action.DecrementCountAction;\nimport info.izumin.android.droidux.example.counter.action.IncrementCountAction;\n\n/**\n * Created by izumin on 12/6/15.\n */\n@Reducer(Counter.class)\npublic class CounterReducer {\n    public static final String TAG = CounterReducer.class.getSimpleName();\n\n    @Dispatchable(IncrementCountAction.class)\n    public Counter increment(Counter state) {\n        return new Counter(state.getCount() + 1);\n    }\n\n    @Dispatchable(DecrementCountAction.class)\n    public Counter decrement(Counter state) {\n        return new Counter(state.getCount() - 1);\n    }\n}\n"
  },
  {
    "path": "examples/counter/src/main/java/info/izumin/android/droidux/example/counter/MainActivity.java",
    "content": "package info.izumin.android.droidux.example.counter;\n\nimport android.databinding.DataBindingUtil;\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.View;\n\nimport info.izumin.android.droidux.example.counter.action.DecrementCountAction;\nimport info.izumin.android.droidux.example.counter.action.IncrementCountAction;\nimport info.izumin.android.droidux.example.counter.databinding.ActivityMainBinding;\n\npublic class MainActivity extends AppCompatActivity implements MainEventHandlers {\n\n    private RootStore store;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);\n\n        store = DroiduxRootStore.builder()\n                .setReducer(new CounterReducer(), new Counter(0), BR.counter)\n                .build();\n\n        binding.setHandlers(this);\n        binding.setStore(store);\n    }\n\n    @Override\n    public void onClickBtnIncrement(View v) {\n        store.dispatch(new IncrementCountAction()).subscribe();\n    }\n\n    @Override\n    public void onClickBtnDecrement(View v) {\n        store.dispatch(new DecrementCountAction()).subscribe();\n    }\n}\n"
  },
  {
    "path": "examples/counter/src/main/java/info/izumin/android/droidux/example/counter/MainEventHandlers.java",
    "content": "package info.izumin.android.droidux.example.counter;\n\nimport android.view.View;\n\n/**\n * Created by izumin on 12/6/15.\n */\npublic interface MainEventHandlers {\n    void onClickBtnIncrement(View v);\n    void onClickBtnDecrement(View v);\n}\n"
  },
  {
    "path": "examples/counter/src/main/java/info/izumin/android/droidux/example/counter/RootStore.java",
    "content": "package info.izumin.android.droidux.example.counter;\n\nimport android.databinding.Bindable;\n\nimport info.izumin.android.droidux.BaseStore;\nimport info.izumin.android.droidux.annotation.Store;\n\n/**\n * Created by izumin on 12/6/15.\n */\n@Store(CounterReducer.class)\npublic interface RootStore extends BaseStore, android.databinding.Observable {\n    @Bindable Counter getCounter();\n}\n"
  },
  {
    "path": "examples/counter/src/main/java/info/izumin/android/droidux/example/counter/action/DecrementCountAction.java",
    "content": "package info.izumin.android.droidux.example.counter.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 12/6/15.\n */\npublic class DecrementCountAction implements Action {\n    public static final String TAG = DecrementCountAction.class.getSimpleName();\n}\n"
  },
  {
    "path": "examples/counter/src/main/java/info/izumin/android/droidux/example/counter/action/IncrementCountAction.java",
    "content": "package info.izumin.android.droidux.example.counter.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 12/6/15.\n */\npublic class IncrementCountAction implements Action {\n    public static final String TAG = IncrementCountAction.class.getSimpleName();\n}\n"
  },
  {
    "path": "examples/counter/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\" >\n\n    <data>\n        <variable name=\"handlers\" type=\"info.izumin.android.droidux.example.counter.MainEventHandlers\" />\n        <variable name=\"store\" type=\"info.izumin.android.droidux.example.counter.RootStore\" />\n    </data>\n\n    <RelativeLayout\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=\"info.izumin.android.droidux.example.counter.MainActivity\">\n\n        <TextView\n            android:id=\"@+id/text_counter\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginTop=\"@dimen/counter_vertical_margin\"\n            android:layout_marginBottom=\"@dimen/counter_vertical_margin\"\n            android:layout_centerInParent=\"true\"\n            android:textSize=\"@dimen/text_size_display3\"\n            android:text=\"@{String.valueOf(store.counter.getCount())}\"\n            tools:text=\"16\" />\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_below=\"@id/text_counter\"\n            android:orientation=\"horizontal\"\n            android:gravity=\"center_horizontal\" >\n\n            <Button\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/btn_increment\"\n                android:onClick=\"@{handlers.onClickBtnIncrement}\"/>\n\n            <Button\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"@string/btn_decrement\"\n                android:onClick=\"@{handlers.onClickBtnDecrement}\"/>\n        </LinearLayout>\n\n    </RelativeLayout>\n</layout>\n"
  },
  {
    "path": "examples/counter/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "examples/counter/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\n    <dimen name=\"counter_vertical_margin\">32dp</dimen>\n\n    <dimen name=\"text_size_display3\">56sp</dimen>\n</resources>\n"
  },
  {
    "path": "examples/counter/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Counter</string>\n\n    <string name=\"btn_increment\">+</string>\n    <string name=\"btn_decrement\">-</string>\n</resources>\n"
  },
  {
    "path": "examples/counter/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        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/counter/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": "examples/todomvc/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "examples/todomvc/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion project.compileSdkVersion\n    buildToolsVersion project.buildToolsVersion\n\n    defaultConfig {\n        applicationId \"info.izumin.android.droidux.example.todomvc\"\n        minSdkVersion project.minSdkVersion\n        targetSdkVersion project.targetSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    packagingOptions {\n        exclude 'META-INF/services/javax.annotation.processing.Processor'\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    dataBinding {\n        enabled = true\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    testCompile 'junit:junit:4.12'\n    compile \"io.reactivex.rxjava2:rxjava:${project.rxJava2Version}\"\n    compile \"io.reactivex.rxjava2:rxandroid:${project.rxAndroid2Version}\"\n    compile project(':droidux')\n    annotationProcessor project(':droidux-processor')\n    compile \"com.android.support:appcompat-v7:${project.supportLibrariesVersion}\"\n    compile \"com.android.support:design:${project.supportLibrariesVersion}\"\n    compile 'com.google.code.gson:gson:2.4'\n}\n"
  },
  {
    "path": "examples/todomvc/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 /usr/local/opt/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"
  },
  {
    "path": "examples/todomvc/src/androidTest/java/info/izumin/android/droidux/ApplicationTest.java",
    "content": "package info.izumin.android.droidux;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"http://d.android.com/tools/testing/testing_android.html\">Testing Fundamentals</a>\n */\npublic class ApplicationTest extends ApplicationTestCase<Application> {\n    public ApplicationTest() {\n        super(Application.class);\n    }\n}"
  },
  {
    "path": "examples/todomvc/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=\"info.izumin.android.droidux.example.todomvc\" >\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\"\n        android:name=\".App\" >\n        <activity\n            android:name=\".MainActivity\"\n            android:label=\"@string/title_activity_main\"\n            android:theme=\"@style/AppTheme\" >\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    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/App.java",
    "content": "package info.izumin.android.droidux.example.todomvc;\n\nimport android.app.Application;\n\nimport java.util.ArrayList;\n\nimport info.izumin.android.droidux.example.todomvc.entity.TodoList;\nimport info.izumin.android.droidux.example.todomvc.middleware.Logger;\nimport info.izumin.android.droidux.example.todomvc.reducer.TodoListReducer;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class App extends Application {\n    public static final String TAG = App.class.getSimpleName();\n\n    private RootStore store;\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        store = DroiduxRootStore.builder()\n                .addMiddleware(new Logger())\n                .setReducer(new TodoListReducer(), new TodoList(new ArrayList<>()))\n                .build();\n    }\n\n    public RootStore getStore() {\n        return store;\n    }\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/MainActivity.java",
    "content": "package info.izumin.android.droidux.example.todomvc;\n\nimport android.databinding.DataBindingUtil;\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.Menu;\nimport android.view.MenuItem;\n\npublic class MainActivity extends AppCompatActivity {\n    public static final String TAG = MainActivity.class.getSimpleName();\n\n    private RootStore store;\n    private MainActivityHelper helper;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        DataBindingUtil.setContentView(this, R.layout.activity_main);\n        store = ((App) getApplication()).getStore();\n        helper = new MainActivityHelper(this);\n        helper.onCreate();\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        getMenuInflater().inflate(R.menu.main_manu, menu);\n        return true;\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        return helper.onOptionItemSelected(item) || super.onOptionsItemSelected(item);\n    }\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/MainActivityHelper.java",
    "content": "package info.izumin.android.droidux.example.todomvc;\n\nimport android.support.v7.app.AlertDialog;\nimport android.view.MenuItem;\nimport android.widget.Button;\nimport android.widget.EditText;\nimport android.widget.ListView;\nimport android.widget.Toast;\n\nimport info.izumin.android.droidux.example.todomvc.action.AddTodoAction;\nimport info.izumin.android.droidux.example.todomvc.action.ClearCompletedTodoAction;\nimport info.izumin.android.droidux.example.todomvc.action.DeleteTodoAction;\nimport info.izumin.android.droidux.example.todomvc.action.ToggleCompletedTodoAction;\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.Flowable;\nimport io.reactivex.Single;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.subjects.PublishSubject;\nimport io.reactivex.subjects.SingleSubject;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class MainActivityHelper {\n    public static final String TAG = MainActivityHelper.class.getSimpleName();\n\n    private MainActivity activity;\n    private RootStore store;\n\n    private EditText editNewTodo;\n    private Button btnAddTodo;\n    private ListView listTodo;\n\n    public MainActivityHelper(MainActivity activity) {\n        this.activity = activity;\n    }\n\n    public void onCreate() {\n        store = ((App) activity.getApplication()).getStore();\n\n        editNewTodo = (EditText) activity.findViewById(R.id.edit_new_todo);\n        btnAddTodo = (Button) activity.findViewById(R.id.btn_add_todo);\n        listTodo = (ListView) activity.findViewById(R.id.list_todo);\n\n        observeOnClickBtnAddTodo()\n                .filter(s -> !s.isEmpty())\n                .flatMap(s -> store.dispatch(new AddTodoAction(s)))\n                .subscribeOn(AndroidSchedulers.mainThread())\n                .subscribe(action -> {\n                    editNewTodo.setText(\"\");\n                    Toast.makeText(activity, R.string.toast_add_todo, Toast.LENGTH_SHORT).show();\n                });\n\n        observeOnClickListItem()\n                .flatMap(id -> store.dispatch(new ToggleCompletedTodoAction(id.intValue())))\n                .subscribe();\n\n        observeOnLongClickListItem()\n                .flatMap(id -> store.dispatch(new DeleteTodoAction(id)))\n                .subscribeOn(AndroidSchedulers.mainThread())\n                .subscribe(action -> {\n                    Toast.makeText(activity, R.string.toast_delete_todo, Toast.LENGTH_SHORT).show();\n                });\n\n        listTodo.setAdapter(new TodoListAdapter(activity));\n    }\n\n    public boolean onOptionItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case R.id.menu_clear_completed_todo:\n                store.dispatch(new ClearCompletedTodoAction()).subscribe();\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    private Flowable<String> observeOnClickBtnAddTodo() {\n        PublishSubject<String> subject = PublishSubject.create();\n        btnAddTodo.setOnClickListener(v -> subject.onNext(editNewTodo.getText().toString()));\n        return subject.toFlowable(BackpressureStrategy.DROP);\n    }\n\n    private Flowable<Long> observeOnClickListItem() {\n        PublishSubject<Long> subject = PublishSubject.create();\n        listTodo.setOnItemClickListener((parent, view, position, id) -> subject.onNext(id));\n        return subject.toFlowable(BackpressureStrategy.DROP);\n    }\n\n    private Flowable<Long> observeOnLongClickListItem() {\n        PublishSubject<Long> subject = PublishSubject.create();\n        listTodo.setOnItemLongClickListener((parent, view, position, id) -> {\n            new AlertDialog.Builder(activity)\n                    .setTitle(R.string.dialog_delete_todo_title)\n                    .setMessage(activity.getString(R.string.dialog_delete_todo_message,\n                            store.todoList().getTodoById((int) id).getText()))\n                    .setPositiveButton(R.string.dialog_delete_todo_btn_positive, (dialog, which) -> {\n                        subject.onNext(id);\n                    })\n                    .setNeutralButton(R.string.dialog_delete_todo_btn_neutral, (dialog, which) -> {\n                        dialog.dismiss();\n                    })\n                    .show();\n            return true;\n        });\n        return subject.toFlowable(BackpressureStrategy.DROP);\n    }\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/RootStore.java",
    "content": "package info.izumin.android.droidux.example.todomvc;\n\nimport info.izumin.android.droidux.BaseStore;\nimport info.izumin.android.droidux.annotation.Store;\nimport info.izumin.android.droidux.example.todomvc.entity.TodoList;\nimport info.izumin.android.droidux.example.todomvc.reducer.TodoListReducer;\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.Flowable;\n\n/**\n * Created by izumin on 11/29/15.\n */\n@Store(TodoListReducer.class)\npublic interface RootStore extends BaseStore {\n    TodoList todoList();\n    Flowable<TodoList> observeTodoList();\n    Flowable<TodoList> observeTodoList(BackpressureStrategy strategy);\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/TodoListAdapter.java",
    "content": "package info.izumin.android.droidux.example.todomvc;\n\nimport android.content.Context;\nimport android.databinding.DataBindingUtil;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\n\nimport info.izumin.android.droidux.example.todomvc.databinding.ListItemTodoBinding;\nimport info.izumin.android.droidux.example.todomvc.entity.TodoList;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class TodoListAdapter extends BaseAdapter {\n    public static final String TAG = TodoListAdapter.class.getSimpleName();\n\n    private static final int LAYOUT_RES_ID = R.layout.list_item_todo;\n\n    private final LayoutInflater inflater;\n    private final RootStore store;\n\n    public TodoListAdapter(Context context) {\n        super();\n        this.inflater = LayoutInflater.from(context);\n        this.store = ((App) context.getApplicationContext()).getStore();\n        this.store.observeTodoList().subscribe(todoList -> notifyDataSetChanged());\n    }\n\n    @Override\n    public int getCount() {\n        return store.todoList().getTodoList().size();\n    }\n\n    @Override\n    public TodoList.Todo getItem(int position) {\n        return store.todoList().getTodoList().get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return getItem(position).getId();\n    }\n\n    @Override\n    public View getView(int position, View convertView, ViewGroup parent) {\n        ListItemTodoBinding binding;\n        if (convertView == null) {\n            binding = DataBindingUtil.inflate(inflater, LAYOUT_RES_ID, parent, false);\n            convertView = binding.getRoot();\n            convertView.setTag(binding);\n        } else {\n            binding = (ListItemTodoBinding) convertView.getTag();\n        }\n\n        binding.setTodo(getItem(position));\n\n        return convertView;\n    }\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/action/AddTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todomvc.action;\n\nimport com.google.gson.Gson;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class AddTodoAction implements Action {\n    public static final String TAG = AddTodoAction.class.getSimpleName();\n\n    private final String text;\n\n    public AddTodoAction(String text) {\n        this.text = text;\n    }\n\n    public String getText() {\n        return text;\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/action/ClearCompletedTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todomvc.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class ClearCompletedTodoAction implements Action {\n    public static final String TAG = ClearCompletedTodoAction.class.getSimpleName();\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/action/DeleteTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todomvc.action;\n\nimport com.google.gson.Gson;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class DeleteTodoAction implements Action {\n    public static final String TAG = DeleteTodoAction.class.getSimpleName();\n\n    private final long id;\n\n    public DeleteTodoAction(long id) {\n        this.id = id;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/action/ToggleCompletedTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todomvc.action;\n\nimport com.google.gson.Gson;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class ToggleCompletedTodoAction implements Action {\n    public static final String TAG = ToggleCompletedTodoAction.class.getSimpleName();\n\n    private final int id;\n\n    public ToggleCompletedTodoAction(int id) {\n        this.id = id;\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/entity/TodoList.java",
    "content": "package info.izumin.android.droidux.example.todomvc.entity;\n\nimport com.google.gson.Gson;\n\nimport java.util.List;\n\nimport io.reactivex.Observable;\n\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class TodoList {\n    public static final String TAG = TodoList.class.getSimpleName();\n\n    private List<Todo> todoList;\n\n    public TodoList(List<Todo> todoList) {\n        this.todoList = todoList;\n    }\n\n    public List<Todo> getTodoList() {\n        return todoList;\n    }\n\n    public Todo getTodoById(int id) {\n        return Observable.fromIterable(getTodoList())\n                .filter(todo -> id == todo.getId()).blockingFirst();\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n\n    public static class Todo {\n        private final int id;\n        private final boolean completed;\n        private final String text;\n\n        public Todo(int id, String text) {\n            this.id = id;\n            this.text = text;\n            this.completed = false;\n        }\n\n        public Todo(int id, String text, boolean isCompleted) {\n            this.id = id;\n            this.text = text;\n            this.completed = isCompleted;\n        }\n\n        public int getId() {\n            return id;\n        }\n\n        public boolean isCompleted() {\n            return completed;\n        }\n\n        public String getText() {\n            return text;\n        }\n\n        @Override\n        public String toString() {\n            return new Gson().toJson(this);\n        }\n    }\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/middleware/Logger.java",
    "content": "package info.izumin.android.droidux.example.todomvc.middleware;\n\nimport android.util.Log;\n\nimport info.izumin.android.droidux.Action;\nimport info.izumin.android.droidux.Middleware;\nimport info.izumin.android.droidux.example.todomvc.RootStore;\nimport io.reactivex.Flowable;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class Logger extends Middleware<RootStore> {\n    public static final String TAG = Logger.class.getSimpleName();\n\n    @Override\n    public Flowable<Action> beforeDispatch(Action action) {\n        Log.d(\"[prev todo]\", getStore().todoList().toString());\n        Log.d(\"[\" + action.getClass().getSimpleName() + \"]\", action.toString());\n        return Flowable.just(action);\n    }\n\n    @Override\n    public Flowable<Action> afterDispatch(Action action) {\n        Log.d(\"[next todo]\", getStore().todoList().toString());\n        return Flowable.just(action);\n    }\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/java/info/izumin/android/droidux/example/todomvc/reducer/TodoListReducer.java",
    "content": "package info.izumin.android.droidux.example.todomvc.reducer;\n\nimport java.util.List;\n\nimport info.izumin.android.droidux.annotation.Dispatchable;\nimport info.izumin.android.droidux.annotation.Reducer;\nimport info.izumin.android.droidux.example.todomvc.action.AddTodoAction;\nimport info.izumin.android.droidux.example.todomvc.action.ClearCompletedTodoAction;\nimport info.izumin.android.droidux.example.todomvc.action.DeleteTodoAction;\nimport info.izumin.android.droidux.example.todomvc.action.ToggleCompletedTodoAction;\nimport info.izumin.android.droidux.example.todomvc.entity.TodoList;\nimport io.reactivex.Observable;\n\n\n/**\n * Created by izumin on 11/4/15.\n */\n@Reducer(TodoList.class)\npublic class TodoListReducer {\n    public static final String TAG = TodoListReducer.class.getSimpleName();\n\n    @Dispatchable(AddTodoAction.class)\n    public TodoList onAddedTodo(TodoList state, AddTodoAction action) {\n        List<TodoList.Todo> list = state.getTodoList();\n        if (list.isEmpty()) {\n            list.add(new TodoList.Todo(0, action.getText()));\n            return new TodoList(list);\n        }\n        int id = Observable.fromIterable(list)\n                .reduce((todo, todo2) -> (todo.getId() < todo2.getId()) ? todo2 : todo)\n                .blockingGet()\n                .getId();\n        list.add(new TodoList.Todo(id + 1, action.getText()));\n        return new TodoList(list);\n    }\n\n    @Dispatchable(ToggleCompletedTodoAction.class)\n    public TodoList onCompletedTodo(TodoList state, ToggleCompletedTodoAction action) {\n        return new TodoList(Observable.fromIterable(state.getTodoList())\n                .map(todo -> {\n                    if (todo.getId() == action.getId()) {\n                        return new TodoList.Todo(todo.getId(), todo.getText(), !todo.isCompleted());\n                    }\n                    return todo;\n                })\n                .toList().blockingGet()\n        );\n    }\n\n    @Dispatchable(ClearCompletedTodoAction.class)\n    public TodoList onClearCompletedTodo(TodoList state, ClearCompletedTodoAction action) {\n        return new TodoList(Observable.fromIterable(state.getTodoList())\n                .filter(todo -> !todo.isCompleted()).toList().blockingGet()\n        );\n    }\n\n    @Dispatchable(DeleteTodoAction.class)\n    public TodoList onDeletedTodo(TodoList state, DeleteTodoAction action) {\n        return new TodoList(Observable.fromIterable(state.getTodoList())\n                .filter(todo -> todo.getId() != action.getId()).toList().blockingGet()\n        );\n    }\n}\n"
  },
  {
    "path": "examples/todomvc/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <data>\n    </data>\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n        android:paddingRight=\"@dimen/activity_horizontal_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\"\n        android:paddingBottom=\"@dimen/activity_vertical_margin\"\n        tools:context=\".MainActivity\" >\n\n        <ListView\n            android:id=\"@+id/list_todo\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_above=\"@+id/btn_add_todo\" />\n\n        <EditText\n            android:id=\"@+id/edit_new_todo\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_toLeftOf=\"@+id/btn_add_todo\"\n            android:hint=\"@string/edit_new_todo_hint\" />\n\n        <Button\n            android:id=\"@+id/btn_add_todo\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_alignParentBottom=\"true\"\n            android:text=\"@string/btn_add_todo\" />\n    </RelativeLayout>\n</layout>\n"
  },
  {
    "path": "examples/todomvc/src/main/res/layout/list_item_todo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\" >\n    <data>\n        <import type=\"info.izumin.android.droidux.example.todomvc.entity.TodoList.Todo\" />\n        <variable name=\"todo\" type=\"Todo\" />\n    </data>\n    <LinearLayout\n        android:orientation=\"horizontal\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n        android:paddingRight=\"@dimen/activity_horizontal_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\"\n        android:paddingBottom=\"@dimen/activity_vertical_margin\" >\n\n        <CheckBox android:id=\"@+id/checkbox_todo\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:focusable=\"false\"\n            android:checked=\"@{todo.isCompleted()}\"/>\n\n        <TextView android:id=\"@+id/text_todo\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:focusable=\"false\"\n            android:text=\"@{todo.getText()}\"\n            tools:text=\"sample text\" />\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "examples/todomvc/src/main/res/menu/main_manu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <item android:id=\"@+id/menu_clear_completed_todo\"\n        android:title=\"@string/menu_clear_completed_todo\"\n        app:showAsAction=\"never\" />\n</menu>"
  },
  {
    "path": "examples/todomvc/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "examples/todomvc/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    <dimen name=\"fab_margin\">16dp</dimen>\n\n</resources>\n"
  },
  {
    "path": "examples/todomvc/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">TodoMVC</string>\n    <string name=\"title_activity_main\">TodoMVC</string>\n\n    <string name=\"btn_add_todo\">Add</string>\n    <string name=\"edit_new_todo_hint\">new task</string>\n\n    <string name=\"dialog_delete_todo_title\">Delete todo</string>\n    <string name=\"dialog_delete_todo_message\">Are you sure you want to delete \"%s\"?</string>\n    <string name=\"dialog_delete_todo_btn_positive\">OK</string>\n    <string name=\"dialog_delete_todo_btn_neutral\">Cancel</string>\n\n    <string name=\"toast_add_todo\">Added new task !</string>\n    <string name=\"toast_delete_todo\">Deleted task $d !</string>\n\n    <string name=\"menu_clear_completed_todo\">Clear completed tasks</string>\n</resources>\n"
  },
  {
    "path": "examples/todomvc/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        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n    <style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\" />\n    <style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\" />\n\n</resources>\n"
  },
  {
    "path": "examples/todomvc/src/main/res/values-v21/styles.xml",
    "content": "<resources>>\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "examples/todomvc/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": "examples/todos-with-dagger/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "examples/todos-with-dagger/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion project.compileSdkVersion\n    buildToolsVersion project.buildToolsVersion\n\n    defaultConfig {\n        applicationId \"info.izumin.android.droidux.example.todoswithdagger\"\n        minSdkVersion project.minSdkVersion\n        targetSdkVersion project.targetSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    packagingOptions {\n        exclude 'META-INF/services/javax.annotation.processing.Processor'\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    dataBinding {\n        enabled = true\n    }\n}\n\nconfigurations.all {\n    resolutionStrategy.force 'com.android.support:support-annotations:23.1.0'\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    testCompile 'junit:junit:4.12'\n    compile \"io.reactivex.rxjava2:rxjava:${project.rxJava2Version}\"\n    compile \"io.reactivex.rxjava2:rxandroid:${project.rxAndroid2Version}\"\n    compile project(':droidux')\n    annotationProcessor project(':droidux-processor')\n    compile \"com.android.support:appcompat-v7:${project.supportLibrariesVersion}\"\n    compile \"com.android.support:design:${project.supportLibrariesVersion}\"\n    compile 'com.google.code.gson:gson:2.4'\n    compile 'com.google.dagger:dagger:2.0'\n    annotationProcessor 'com.google.dagger:dagger-compiler:2.0'\n\n    androidTestCompile 'com.android.support.test:runner:0.4.1'\n    androidTestCompile 'com.android.support.test:rules:0.4.1'\n    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/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 /usr/local/opt/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"
  },
  {
    "path": "examples/todos-with-dagger/src/androidTest/java/info/izumin/android/droidux/example/todoswithdagger/ApplicationTest.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"http://d.android.com/tools/testing/testing_android.html\">Testing Fundamentals</a>\n */\npublic class ApplicationTest extends ApplicationTestCase<Application> {\n    public ApplicationTest() {\n        super(Application.class);\n    }\n}"
  },
  {
    "path": "examples/todos-with-dagger/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=\"info.izumin.android.droidux.example.todoswithdagger\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\"\n        android:name=\".App\">\n        <activity android:name=\".module.main.MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/App.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger;\n\nimport android.app.Application;\n\nimport info.izumin.android.droidux.example.todoswithdagger.entity.TodoList;\nimport info.izumin.android.droidux.example.todoswithdagger.reducer.TodoListReducer;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class App extends Application {\n    public static final String TAG = App.class.getSimpleName();\n\n    private RootStore store;\n    private AppComponent component;\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        setupStore();\n        setupGraph();\n    }\n\n    public RootStore getStore() {\n        return store;\n    }\n\n    public AppComponent getComponent() {\n        return component;\n    }\n\n    private void setupStore() {\n        store = DroiduxRootStore.builder()\n                .setReducer(new TodoListReducer(), new TodoList())\n                .build();\n    }\n\n    private void setupGraph() {\n        component = DaggerAppComponent.builder()\n                .appModule(new AppModule(this))\n                .build();\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/AppComponent.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger;\n\nimport javax.inject.Singleton;\n\nimport dagger.Component;\nimport info.izumin.android.droidux.example.todoswithdagger.module.main.MainComponent;\nimport info.izumin.android.droidux.example.todoswithdagger.module.main.MainModule;\n\n/**\n * Created by izumin on 11/29/15.\n */\n@Singleton\n@Component(\n        modules = AppModule.class\n)\npublic interface AppComponent {\n    MainComponent createMainActivityComponent(MainModule module);\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/AppModule.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger;\n\nimport javax.inject.Singleton;\n\nimport dagger.Module;\nimport dagger.Provides;\n\n/**\n * Created by izumin on 11/29/15.\n */\n@Module\npublic class AppModule {\n\n    private final App app;\n\n    public AppModule(App app) {\n        this.app = app;\n    }\n\n    @Provides\n    @Singleton\n    RootStore provideRootStore() {\n        return app.getStore();\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/RootStore.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger;\n\nimport info.izumin.android.droidux.BaseStore;\nimport info.izumin.android.droidux.annotation.Store;\nimport info.izumin.android.droidux.example.todoswithdagger.entity.TodoList;\nimport info.izumin.android.droidux.example.todoswithdagger.reducer.TodoListReducer;\nimport io.reactivex.Flowable;\n\n/**\n * Created by izumin on 11/29/15.\n */\n@Store(TodoListReducer.class)\npublic interface RootStore extends BaseStore {\n    TodoList todoList();\n    Flowable<TodoList> observeTodoList();\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/action/AddTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.action;\n\nimport com.google.gson.Gson;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class AddTodoAction implements Action {\n    public static final String TAG = AddTodoAction.class.getSimpleName();\n\n    private final String text;\n\n    public AddTodoAction(String text) {\n        this.text = text;\n    }\n\n    public String getText() {\n        return text;\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/action/ClearCompletedTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class ClearCompletedTodoAction implements Action {\n    public static final String TAG = ClearCompletedTodoAction.class.getSimpleName();\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/action/ClearNewTodoTextAction.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 12/5/15.\n */\npublic class ClearNewTodoTextAction implements Action {\n    public static final String TAG = ClearNewTodoTextAction.class.getSimpleName();\n\n    public ClearNewTodoTextAction() {\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/action/DeleteTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.action;\n\nimport com.google.gson.Gson;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class DeleteTodoAction implements Action {\n    public static final String TAG = DeleteTodoAction.class.getSimpleName();\n\n    private final long id;\n\n    public DeleteTodoAction(long id) {\n        this.id = id;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/action/ToggleCompletedTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.action;\n\nimport com.google.gson.Gson;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class ToggleCompletedTodoAction implements Action {\n    public static final String TAG = ToggleCompletedTodoAction.class.getSimpleName();\n\n    private final int id;\n\n    public ToggleCompletedTodoAction(int id) {\n        this.id = id;\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/action/UpdateNewTodoTextAction.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 12/5/15.\n */\npublic class UpdateNewTodoTextAction implements Action {\n    public static final String TAG = UpdateNewTodoTextAction.class.getSimpleName();\n\n    private final String text;\n\n    public UpdateNewTodoTextAction(String text) {\n        this.text = text;\n    }\n\n    public String getText() {\n        return text;\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/adapter/TodoListAdapter.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.adapter;\n\nimport android.content.Context;\nimport android.databinding.DataBindingUtil;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\n\nimport info.izumin.android.droidux.example.todoswithdagger.App;\nimport info.izumin.android.droidux.example.todoswithdagger.R;\nimport info.izumin.android.droidux.example.todoswithdagger.RootStore;\nimport info.izumin.android.droidux.example.todoswithdagger.databinding.ListItemTodoBinding;\nimport info.izumin.android.droidux.example.todoswithdagger.entity.TodoList;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class TodoListAdapter extends BaseAdapter {\n    public static final String TAG = TodoListAdapter.class.getSimpleName();\n\n    private static final int LAYOUT_RES_ID = R.layout.list_item_todo;\n\n    private final LayoutInflater inflater;\n    private final RootStore store;\n\n    public TodoListAdapter(Context context) {\n        super();\n        this.inflater = LayoutInflater.from(context);\n        this.store = ((App) context.getApplicationContext()).getStore();\n        this.store.observeTodoList().subscribe(todoList -> notifyDataSetChanged());\n    }\n\n    @Override\n    public int getCount() {\n        return store.todoList().size();\n    }\n\n    @Override\n    public TodoList.Todo getItem(int position) {\n        return store.todoList().get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return getItem(position).getId();\n    }\n\n    @Override\n    public View getView(int position, View convertView, ViewGroup parent) {\n        ListItemTodoBinding binding;\n        if (convertView == null) {\n            binding = DataBindingUtil.inflate(inflater, LAYOUT_RES_ID, parent, false);\n            convertView = binding.getRoot();\n            convertView.setTag(binding);\n        } else {\n            binding = (ListItemTodoBinding) convertView.getTag();\n        }\n\n        binding.setTodo(getItem(position));\n\n        return convertView;\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/entity/TodoList.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.entity;\n\nimport com.google.gson.Gson;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport info.izumin.android.droidux.UndoableState;\nimport io.reactivex.Observable;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class TodoList extends ArrayList<TodoList.Todo> implements UndoableState<TodoList> {\n    public static final String TAG = TodoList.class.getSimpleName();\n\n    public TodoList() {\n    }\n\n    public TodoList(List<Todo> list) {\n        super(list);\n    }\n\n    public Todo getTodoById(int id) {\n        return Observable.fromIterable(this)\n                .filter(todo -> id == todo.getId()).blockingFirst();\n    }\n\n    @Override\n    public TodoList clone() {\n        return (TodoList) super.clone();\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n\n    public static class Todo {\n        private final int id;\n        private final boolean completed;\n        private final String text;\n\n        public Todo(int id, String text) {\n            this.id = id;\n            this.text = text;\n            this.completed = false;\n        }\n\n        public Todo(int id, String text, boolean isCompleted) {\n            this.id = id;\n            this.text = text;\n            this.completed = isCompleted;\n        }\n\n        public int getId() {\n            return id;\n        }\n\n        public boolean isCompleted() {\n            return completed;\n        }\n\n        public String getText() {\n            return text;\n        }\n\n        @Override\n        public String toString() {\n            return new Gson().toJson(this);\n        }\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/module/main/MainActivity.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.module.main;\n\nimport android.databinding.DataBindingUtil;\nimport android.os.Bundle;\nimport android.support.annotation.StringRes;\nimport android.support.v7.app.AlertDialog;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.Toast;\n\nimport javax.inject.Inject;\n\nimport info.izumin.android.droidux.example.todoswithdagger.App;\nimport info.izumin.android.droidux.example.todoswithdagger.R;\nimport info.izumin.android.droidux.example.todoswithdagger.RootStore;\nimport info.izumin.android.droidux.example.todoswithdagger.adapter.TodoListAdapter;\nimport info.izumin.android.droidux.example.todoswithdagger.databinding.ActivityMainBinding;\n\npublic class MainActivity extends AppCompatActivity implements MainView, MainEventHandlers {\n\n    @Inject MainPresenter presenter;\n    @Inject RootStore store;\n\n    private ActivityMainBinding binding;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);\n        setupComponent();\n        binding.setHandlers(this);\n        binding.setTodoAdapter(new TodoListAdapter(this));\n        binding.setStore(store);\n    }\n\n    @Override\n    protected void onStart() {\n        super.onStart();\n        presenter.onStart();\n    }\n\n    @Override\n    protected void onStop() {\n        presenter.onStop();\n        super.onStop();\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        getMenuInflater().inflate(R.menu.main_manu, menu);\n        return true;\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case R.id.menu_clear_completed_todo:\n                presenter.clearCompletedTodo();\n                return true;\n            default:\n                return super.onOptionsItemSelected(item);\n        }\n    }\n\n    @Override\n    public void showToast(@StringRes int resId, Object... args) {\n        Toast.makeText(this, getString(resId, args), Toast.LENGTH_LONG).show();\n    }\n\n    @Override\n    public void showConfirmDeleteDialog(long id) {\n        new AlertDialog.Builder(this)\n                .setTitle(R.string.dialog_delete_todo_title)\n                .setMessage(getString(R.string.dialog_delete_todo_message,\n                        store.todoList().getTodoById((int) id).getText()))\n                .setPositiveButton(R.string.dialog_delete_todo_btn_positive, (dialog, which) -> {\n                    presenter.onLongClickListItem(id);\n                })\n                .setNeutralButton(R.string.dialog_delete_todo_btn_neutral, (dialog, which) -> {\n                    dialog.dismiss();\n                })\n                .show();\n    }\n\n    @Override\n    public void clearNewTodoText() {\n        binding.editNewTodo.setText(\"\");\n    }\n\n    @Override\n    public void onClickAddTodo(View view) {\n        presenter.onClickBtnAddTodo(binding.editNewTodo.getText().toString());\n    }\n\n    @Override\n    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n        presenter.onClickListItem(id);\n    }\n\n    @Override\n    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {\n        showConfirmDeleteDialog(id);\n        return true;\n    }\n\n    protected MainModule getModule() {\n        return new MainModule(this);\n    }\n\n    private void setupComponent() {\n        ((App) getApplication()).getComponent()\n                .createMainActivityComponent(getModule())\n                .inject(this);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/module/main/MainComponent.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.module.main;\n\nimport dagger.Subcomponent;\n\n/**\n * Created by izumin on 11/29/15.\n */\n@Subcomponent(\n        modules = MainModule.class\n)\npublic interface MainComponent {\n    void inject(MainActivity activity);\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/module/main/MainEventHandlers.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.module.main;\n\nimport android.view.View;\nimport android.widget.AdapterView;\n\n/**\n * Created by izumin on 12/5/15.\n */\npublic interface MainEventHandlers {\n    void onClickAddTodo(View view);\n    void onItemClick(AdapterView<?> parent, View view, int position, long id);\n    boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id);\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/module/main/MainModule.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.module.main;\n\nimport dagger.Module;\nimport dagger.Provides;\nimport info.izumin.android.droidux.example.todoswithdagger.RootStore;\n\n/**\n * Created by izumin on 11/29/15.\n */\n@Module\npublic class MainModule {\n    public static final String TAG = MainModule.class.getSimpleName();\n\n    private final MainActivity activity;\n\n    public MainModule(MainActivity activity) {\n        this.activity = activity;\n    }\n\n    @Provides\n    MainPresenter provideMainPresenter(RootStore store) {\n        return new MainPresenter(activity, store);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/module/main/MainPresenter.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.module.main;\n\nimport info.izumin.android.droidux.example.todoswithdagger.R;\nimport info.izumin.android.droidux.example.todoswithdagger.RootStore;\nimport info.izumin.android.droidux.example.todoswithdagger.action.AddTodoAction;\nimport info.izumin.android.droidux.example.todoswithdagger.action.ClearCompletedTodoAction;\nimport info.izumin.android.droidux.example.todoswithdagger.action.ClearNewTodoTextAction;\nimport info.izumin.android.droidux.example.todoswithdagger.action.DeleteTodoAction;\nimport info.izumin.android.droidux.example.todoswithdagger.action.ToggleCompletedTodoAction;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.disposables.CompositeDisposable;\nimport io.reactivex.subjects.PublishSubject;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class MainPresenter {\n    public static final String TAG = MainPresenter.class.getSimpleName();\n\n    private final MainView view;\n    private final RootStore store;\n\n    private final PublishSubject<String> clickAddTodoSubject = PublishSubject.create();\n    private final PublishSubject<Long> clickItemSubject = PublishSubject.create();\n    private final PublishSubject<Long> longClickItemSubject = PublishSubject.create();\n\n    private CompositeDisposable compositeDisposable;\n\n    public MainPresenter(MainView view, RootStore store) {\n        this.view = view;\n        this.store = store;\n    }\n\n    void onStart() {\n        compositeDisposable = new CompositeDisposable();\n\n        compositeDisposable.add(clickAddTodoSubject\n                .filter(s -> !s.isEmpty())\n                .flatMap(s -> store.dispatch(new AddTodoAction(s)).toObservable())\n                .subscribeOn(AndroidSchedulers.mainThread())\n                .flatMap(_a -> store.dispatch(new ClearNewTodoTextAction()).toObservable())\n                .subscribe(_a -> {\n                    view.clearNewTodoText();\n                    view.showToast(R.string.toast_add_todo);\n                }));\n\n        compositeDisposable.add(clickItemSubject\n                .flatMap(id -> store.dispatch(new ToggleCompletedTodoAction(id.intValue())).toObservable())\n                .subscribe());\n\n        compositeDisposable.add(longClickItemSubject\n                .flatMap(id -> store.dispatch(new DeleteTodoAction(id)).toObservable())\n                .subscribeOn(AndroidSchedulers.mainThread())\n                .subscribe(action -> view.showToast(R.string.toast_delete_todo)));\n    }\n\n    void onStop() {\n        compositeDisposable.clear();\n    }\n\n    void onClickBtnAddTodo(String text) {\n        clickAddTodoSubject.onNext(text);\n    }\n\n    void onClickListItem(long id) {\n        clickItemSubject.onNext(id);\n    }\n\n    void onLongClickListItem(long id) {\n        longClickItemSubject.onNext(id);\n    }\n\n    void clearCompletedTodo() {\n        store.dispatch(new ClearCompletedTodoAction()).subscribe();\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/module/main/MainView.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.module.main;\n\nimport android.support.annotation.StringRes;\n\n/**\n * Created by izumin on 12/2/15.\n */\npublic interface MainView {\n    void showToast(@StringRes int resId, Object... args);\n    void showConfirmDeleteDialog(long id);\n    void clearNewTodoText();\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/reducer/TodoListReducer.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.reducer;\n\nimport info.izumin.android.droidux.annotation.Dispatchable;\nimport info.izumin.android.droidux.annotation.Reducer;\nimport info.izumin.android.droidux.example.todoswithdagger.action.AddTodoAction;\nimport info.izumin.android.droidux.example.todoswithdagger.action.ClearCompletedTodoAction;\nimport info.izumin.android.droidux.example.todoswithdagger.action.DeleteTodoAction;\nimport info.izumin.android.droidux.example.todoswithdagger.action.ToggleCompletedTodoAction;\nimport info.izumin.android.droidux.example.todoswithdagger.entity.TodoList;\nimport io.reactivex.Observable;\n\n/**\n * Created by izumin on 11/4/15.\n */\n@Reducer(TodoList.class)\npublic class TodoListReducer {\n    public static final String TAG = TodoListReducer.class.getSimpleName();\n\n    @Dispatchable(AddTodoAction.class)\n    public TodoList add(TodoList state, AddTodoAction action) {\n        if (state.isEmpty()) {\n            TodoList newState = new TodoList(state);\n            newState.add(new TodoList.Todo(0, action.getText()));\n            return newState;\n        }\n        int id = Observable.fromIterable(state)\n                .reduce((todo, todo2) -> (todo.getId() < todo2.getId()) ? todo2 : todo)\n                .onErrorReturn(throwable -> new TodoList.Todo(0, \"\"))\n                .blockingGet()\n                .getId();\n        TodoList newState = new TodoList(state);\n        newState.add(new TodoList.Todo(id + 1, action.getText()));\n        return newState;\n    }\n\n    @Dispatchable(ToggleCompletedTodoAction.class)\n    public TodoList complete(TodoList state, ToggleCompletedTodoAction action) {\n        return new TodoList(Observable.fromIterable(state)\n                .map(todo -> {\n                    if (todo.getId() == action.getId()) {\n                        return new TodoList.Todo(todo.getId(), todo.getText(), !todo.isCompleted());\n                    }\n                    return todo;\n                })\n                .toList().blockingGet()\n        );\n    }\n\n    @Dispatchable(ClearCompletedTodoAction.class)\n    public TodoList clear(TodoList state) {\n        return new TodoList(Observable.fromIterable(state)\n                .filter(todo -> !todo.isCompleted()).toList().blockingGet()\n        );\n    }\n\n    @Dispatchable(DeleteTodoAction.class)\n    public TodoList delete(TodoList state, DeleteTodoAction action) {\n        return new TodoList(Observable.fromIterable(state)\n                .filter(todo -> todo.getId() != action.getId()).toList().blockingGet()\n        );\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/java/info/izumin/android/droidux/example/todoswithdagger/util/ViewBindingUtils.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger.util;\n\nimport android.databinding.BindingAdapter;\nimport android.widget.ListView;\n\nimport info.izumin.android.droidux.example.todoswithdagger.adapter.TodoListAdapter;\n\n/**\n * Created by izumin on 12/5/15.\n */\npublic final class ViewBindingUtils {\n    private ViewBindingUtils() {\n        throw new AssertionError(\"constructor of the utility class should not be called\");\n    }\n\n    @BindingAdapter(\"todoAdapter\")\n    public static void setTodoAdapter(ListView listView, TodoListAdapter adapter) {\n        listView.setAdapter(adapter);\n    }\n}"
  },
  {
    "path": "examples/todos-with-dagger/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <data>\n        <variable name=\"handlers\" type=\"info.izumin.android.droidux.example.todoswithdagger.module.main.MainEventHandlers\" />\n        <variable name=\"todoAdapter\" type=\"info.izumin.android.droidux.example.todoswithdagger.adapter.TodoListAdapter\" />\n        <variable name=\"store\" type=\"info.izumin.android.droidux.example.todoswithdagger.RootStore\" />\n    </data>\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n        android:paddingRight=\"@dimen/activity_horizontal_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\"\n        android:paddingBottom=\"@dimen/activity_vertical_margin\"\n        tools:context=\".module.main.MainActivity\" >\n\n        <ListView\n            android:id=\"@+id/list_todo\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_above=\"@+id/btn_add_todo\"\n            android:onItemClick=\"@{handlers.onItemClick}\"\n            android:onItemLongClick=\"@{handlers.onItemLongClick}\"\n            app:todoAdapter=\"@{todoAdapter}\" />\n\n        <EditText\n            android:id=\"@+id/edit_new_todo\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_toLeftOf=\"@+id/btn_add_todo\"\n            android:hint=\"@string/edit_new_todo_hint\" />\n\n        <Button\n            android:id=\"@+id/btn_add_todo\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_alignParentBottom=\"true\"\n            android:onClick=\"@{handlers.onClickAddTodo}\"\n            android:text=\"@string/btn_add_todo\" />\n    </RelativeLayout>\n</layout>\n\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/res/layout/list_item_todo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\" >\n    <data>\n        <import type=\"info.izumin.android.droidux.example.todoswithdagger.entity.TodoList.Todo\" />\n        <variable name=\"todo\" type=\"Todo\" />\n    </data>\n    <LinearLayout\n        android:orientation=\"horizontal\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n        android:paddingRight=\"@dimen/activity_horizontal_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\"\n        android:paddingBottom=\"@dimen/activity_vertical_margin\" >\n\n        <CheckBox android:id=\"@+id/checkbox_todo\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:focusable=\"false\"\n            android:checked=\"@{todo.isCompleted()}\"/>\n\n        <TextView android:id=\"@+id/text_todo\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:focusable=\"false\"\n            android:text=\"@{todo.getText()}\"\n            tools:text=\"sample text\" />\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "examples/todos-with-dagger/src/main/res/menu/main_manu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <item android:id=\"@+id/menu_clear_completed_todo\"\n        android:title=\"@string/menu_clear_completed_todo\"\n        app:showAsAction=\"never\" />\n</menu>"
  },
  {
    "path": "examples/todos-with-dagger/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "examples/todos-with-dagger/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": "examples/todos-with-dagger/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Todos with Dagger</string>\n    <string name=\"title_activity_main\">Todos with Dagger</string>\n\n    <string name=\"btn_add_todo\">Add</string>\n    <string name=\"edit_new_todo_hint\">new task</string>\n\n    <string name=\"dialog_delete_todo_title\">Delete todo</string>\n    <string name=\"dialog_delete_todo_message\">Are you sure you want to delete \"%s\"?</string>\n    <string name=\"dialog_delete_todo_btn_positive\">OK</string>\n    <string name=\"dialog_delete_todo_btn_neutral\">Cancel</string>\n\n    <string name=\"toast_add_todo\">Added new task !</string>\n    <string name=\"toast_delete_todo\">Deleted task $d !</string>\n\n    <string name=\"menu_clear_completed_todo\">Clear completed tasks</string>\n    <string name=\"menu_undo_todo\">Undo</string>\n    <string name=\"menu_redo_todo\">Redo</string>\n</resources>\n"
  },
  {
    "path": "examples/todos-with-dagger/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        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "examples/todos-with-dagger/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": "examples/todos-with-dagger/src/test/java/info/izumin/android/droidux/example/todoswithdagger/ExampleUnitTest.java",
    "content": "package info.izumin.android.droidux.example.todoswithdagger;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work on unit tests, switch the Test Artifact in the Build Variants view.\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "examples/todos-with-undo/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "examples/todos-with-undo/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion project.compileSdkVersion\n    buildToolsVersion project.buildToolsVersion\n\n    defaultConfig {\n        applicationId \"info.izumin.android.droidux.example.todoswithundo\"\n        minSdkVersion project.minSdkVersion\n        targetSdkVersion project.targetSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n    packagingOptions {\n        exclude 'META-INF/services/javax.annotation.processing.Processor'\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    dataBinding {\n        enabled = true\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    testCompile 'junit:junit:4.12'\n    compile \"io.reactivex.rxjava2:rxjava:${project.rxJava2Version}\"\n    compile \"io.reactivex.rxjava2:rxandroid:${project.rxAndroid2Version}\"\n    compile project(':droidux')\n    annotationProcessor project(':droidux-processor')\n    compile \"com.android.support:appcompat-v7:${project.supportLibrariesVersion}\"\n    compile \"com.android.support:design:${project.supportLibrariesVersion}\"\n    compile 'com.google.code.gson:gson:2.4'\n}\n\n"
  },
  {
    "path": "examples/todos-with-undo/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 /usr/local/opt/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"
  },
  {
    "path": "examples/todos-with-undo/src/androidTest/java/info/izumin/android/droidux/example/todoswithundo/ApplicationTest.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"http://d.android.com/tools/testing/testing_android.html\">Testing Fundamentals</a>\n */\npublic class ApplicationTest extends ApplicationTestCase<Application> {\n    public ApplicationTest() {\n        super(Application.class);\n    }\n}"
  },
  {
    "path": "examples/todos-with-undo/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=\"info.izumin.android.droidux.example.todoswithundo\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\"\n        android:name=\".App\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/App.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo;\n\nimport android.app.Application;\n\nimport info.izumin.android.droidux.example.todoswithundo.entity.TodoList;\nimport info.izumin.android.droidux.example.todoswithundo.middleware.Logger;\nimport info.izumin.android.droidux.example.todoswithundo.reducer.TodoListReducer;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class App extends Application {\n    public static final String TAG = App.class.getSimpleName();\n\n    private RootStore store;\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        store = DroiduxRootStore.builder()\n                .addMiddleware(new Logger())\n                .setReducer(new TodoListReducer(), new TodoList())\n                .build();\n    }\n\n    public RootStore getStore() {\n        return store;\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/MainActivity.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo;\n\nimport android.databinding.DataBindingUtil;\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.view.Menu;\nimport android.view.MenuItem;\n\npublic class MainActivity extends AppCompatActivity {\n    public static final String TAG = MainActivity.class.getSimpleName();\n\n    private RootStore store;\n    private MainActivityHelper helper;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        DataBindingUtil.setContentView(this, R.layout.activity_main);\n        store = ((App) getApplication()).getStore();\n        helper = new MainActivityHelper(this);\n        helper.onCreate();\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        getMenuInflater().inflate(R.menu.main_manu, menu);\n        return true;\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        return helper.onOptionItemSelected(item) || super.onOptionsItemSelected(item);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/MainActivityHelper.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo;\n\nimport android.support.v7.app.AlertDialog;\nimport android.view.MenuItem;\nimport android.widget.Button;\nimport android.widget.EditText;\nimport android.widget.ListView;\nimport android.widget.Toast;\n\nimport info.izumin.android.droidux.action.RedoAction;\nimport info.izumin.android.droidux.action.UndoAction;\nimport info.izumin.android.droidux.example.todoswithundo.action.AddTodoAction;\nimport info.izumin.android.droidux.example.todoswithundo.action.ClearCompletedTodoAction;\nimport info.izumin.android.droidux.example.todoswithundo.action.DeleteTodoAction;\nimport info.izumin.android.droidux.example.todoswithundo.action.ToggleCompletedTodoAction;\nimport info.izumin.android.droidux.example.todoswithundo.reducer.TodoListReducer;\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.Flowable;\nimport io.reactivex.Observable;\nimport io.reactivex.Single;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.subjects.PublishSubject;\nimport io.reactivex.subjects.SingleSubject;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class MainActivityHelper {\n    public static final String TAG = MainActivityHelper.class.getSimpleName();\n\n    private MainActivity activity;\n    private RootStore store;\n\n    private EditText editNewTodo;\n    private Button btnAddTodo;\n    private ListView listTodo;\n\n    public MainActivityHelper(MainActivity activity) {\n        this.activity = activity;\n    }\n\n    public void onCreate() {\n        store = ((App) activity.getApplication()).getStore();\n\n        editNewTodo = (EditText) activity.findViewById(R.id.edit_new_todo);\n        btnAddTodo = (Button) activity.findViewById(R.id.btn_add_todo);\n        listTodo = (ListView) activity.findViewById(R.id.list_todo);\n\n        observeOnClickBtnAddTodo()\n                .filter(s -> !s.isEmpty())\n                .flatMap(s -> store.dispatch(new AddTodoAction(s)))\n                .subscribeOn(AndroidSchedulers.mainThread())\n                .subscribe(action -> {\n                    editNewTodo.setText(\"\");\n                    Toast.makeText(activity, R.string.toast_add_todo, Toast.LENGTH_SHORT).show();\n                });\n\n        observeOnClickListItem()\n                .flatMap(id -> store.dispatch(new ToggleCompletedTodoAction(id.intValue())))\n                .subscribe();\n\n        observeOnLongClickListItem()\n                .flatMap(id -> store.dispatch(new DeleteTodoAction(id)))\n                .subscribeOn(AndroidSchedulers.mainThread())\n                .subscribe(action -> {\n                    Toast.makeText(activity, R.string.toast_delete_todo, Toast.LENGTH_SHORT).show();\n                });\n\n        listTodo.setAdapter(new TodoListAdapter(activity));\n    }\n\n    public boolean onOptionItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case R.id.menu_clear_completed_todo:\n                store.dispatch(new ClearCompletedTodoAction()).subscribe();\n                return true;\n            case R.id.menu_undo_todo:\n                store.dispatch(new UndoAction(TodoListReducer.class)).subscribe();\n                return true;\n            case R.id.menu_redo_todo:\n                store.dispatch(new RedoAction(TodoListReducer.class)).subscribe();\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    private Flowable<String> observeOnClickBtnAddTodo() {\n        PublishSubject<String> subject = PublishSubject.create();\n        btnAddTodo.setOnClickListener(v -> subject.onNext(editNewTodo.getText().toString()));\n        return subject.toFlowable(BackpressureStrategy.DROP);\n    }\n\n    private Flowable<Long> observeOnClickListItem() {\n        PublishSubject<Long> subject = PublishSubject.create();\n        listTodo.setOnItemClickListener((parent, view, position, id) -> subject.onNext(id));\n        return subject.toFlowable(BackpressureStrategy.DROP);\n    }\n\n    private Flowable<Long> observeOnLongClickListItem() {\n        PublishSubject<Long> subject = PublishSubject.create();\n        listTodo.setOnItemLongClickListener((parent, view, position, id) -> {\n            new AlertDialog.Builder(activity)\n                    .setTitle(R.string.dialog_delete_todo_title)\n                    .setMessage(activity.getString(R.string.dialog_delete_todo_message,\n                            store.todoList().getTodoById((int) id).getText()))\n                    .setPositiveButton(R.string.dialog_delete_todo_btn_positive, (dialog, which) -> {\n                        subject.onNext(id);\n                    })\n                    .setNeutralButton(R.string.dialog_delete_todo_btn_neutral, (dialog, which) -> {\n                        dialog.dismiss();\n                    })\n                    .show();\n            return true;\n        });\n        return subject.toFlowable(BackpressureStrategy.DROP);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/RootStore.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo;\n\nimport info.izumin.android.droidux.BaseStore;\nimport info.izumin.android.droidux.annotation.Store;\nimport info.izumin.android.droidux.example.todoswithundo.entity.TodoList;\nimport info.izumin.android.droidux.example.todoswithundo.reducer.TodoListReducer;\nimport io.reactivex.Flowable;\n\n/**\n * Created by izumin on 11/29/15.\n */\n@Store(TodoListReducer.class)\npublic interface RootStore extends BaseStore {\n    TodoList todoList();\n    Flowable<TodoList> observeTodoList();\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/TodoListAdapter.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo;\n\nimport android.content.Context;\nimport android.databinding.DataBindingUtil;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\n\nimport info.izumin.android.droidux.example.todoswithundo.databinding.ListItemTodoBinding;\nimport info.izumin.android.droidux.example.todoswithundo.entity.TodoList;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class TodoListAdapter extends BaseAdapter {\n    public static final String TAG = TodoListAdapter.class.getSimpleName();\n\n    private static final int LAYOUT_RES_ID = R.layout.list_item_todo;\n\n    private final LayoutInflater inflater;\n    private final RootStore store;\n\n    public TodoListAdapter(Context context) {\n        super();\n        this.inflater = LayoutInflater.from(context);\n        this.store = ((App) context.getApplicationContext()).getStore();\n        this.store.observeTodoList().subscribe(todoList -> notifyDataSetChanged());\n    }\n\n    @Override\n    public int getCount() {\n        return store.todoList().size();\n    }\n\n    @Override\n    public TodoList.Todo getItem(int position) {\n        return store.todoList().get(position);\n    }\n\n    @Override\n    public long getItemId(int position) {\n        return getItem(position).getId();\n    }\n\n    @Override\n    public View getView(int position, View convertView, ViewGroup parent) {\n        ListItemTodoBinding binding;\n        if (convertView == null) {\n            binding = DataBindingUtil.inflate(inflater, LAYOUT_RES_ID, parent, false);\n            convertView = binding.getRoot();\n            convertView.setTag(binding);\n        } else {\n            binding = (ListItemTodoBinding) convertView.getTag();\n        }\n\n        binding.setTodo(getItem(position));\n\n        return convertView;\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/action/AddTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo.action;\n\nimport com.google.gson.Gson;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class AddTodoAction implements Action {\n    public static final String TAG = AddTodoAction.class.getSimpleName();\n\n    private final String text;\n\n    public AddTodoAction(String text) {\n        this.text = text;\n    }\n\n    public String getText() {\n        return text;\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/action/ClearCompletedTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo.action;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class ClearCompletedTodoAction implements Action {\n    public static final String TAG = ClearCompletedTodoAction.class.getSimpleName();\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/action/DeleteTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo.action;\n\nimport com.google.gson.Gson;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class DeleteTodoAction implements Action {\n    public static final String TAG = DeleteTodoAction.class.getSimpleName();\n\n    private final long id;\n\n    public DeleteTodoAction(long id) {\n        this.id = id;\n    }\n\n    public long getId() {\n        return id;\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/action/ToggleCompletedTodoAction.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo.action;\n\nimport com.google.gson.Gson;\n\nimport info.izumin.android.droidux.Action;\n\n/**\n * Created by izumin on 11/5/15.\n */\npublic class ToggleCompletedTodoAction implements Action {\n    public static final String TAG = ToggleCompletedTodoAction.class.getSimpleName();\n\n    private final int id;\n\n    public ToggleCompletedTodoAction(int id) {\n        this.id = id;\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/entity/TodoList.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo.entity;\n\nimport com.google.gson.Gson;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport info.izumin.android.droidux.UndoableState;\nimport io.reactivex.Observable;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class TodoList extends ArrayList<TodoList.Todo> implements UndoableState<TodoList> {\n    public static final String TAG = TodoList.class.getSimpleName();\n\n    public TodoList() {\n    }\n\n    public TodoList(List<Todo> list) {\n        super(list);\n    }\n\n    public Todo getTodoById(int id) {\n        return Observable.fromIterable(this)\n                .filter(todo -> id == todo.getId()).blockingFirst();\n    }\n\n    @Override\n    public TodoList clone() {\n        return (TodoList) super.clone();\n    }\n\n    @Override\n    public String toString() {\n        return new Gson().toJson(this);\n    }\n\n    public static class Todo {\n        private final int id;\n        private final boolean completed;\n        private final String text;\n\n        public Todo(int id, String text) {\n            this.id = id;\n            this.text = text;\n            this.completed = false;\n        }\n\n        public Todo(int id, String text, boolean isCompleted) {\n            this.id = id;\n            this.text = text;\n            this.completed = isCompleted;\n        }\n\n        public int getId() {\n            return id;\n        }\n\n        public boolean isCompleted() {\n            return completed;\n        }\n\n        public String getText() {\n            return text;\n        }\n\n        @Override\n        public String toString() {\n            return new Gson().toJson(this);\n        }\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/middleware/Logger.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo.middleware;\n\nimport android.util.Log;\n\nimport info.izumin.android.droidux.Action;\nimport info.izumin.android.droidux.Middleware;\nimport info.izumin.android.droidux.example.todoswithundo.RootStore;\nimport io.reactivex.Flowable;\nimport io.reactivex.Single;\n\n/**\n * Created by izumin on 11/4/15.\n */\npublic class Logger extends Middleware<RootStore> {\n    public static final String TAG = Logger.class.getSimpleName();\n\n\n    @Override\n    public Flowable<Action> beforeDispatch(Action action) {\n        Log.d(\"[prev todo]\", getStore().todoList().toString());\n        Log.d(\"[\" + action.getClass().getSimpleName() + \"]\", action.toString());\n        return Flowable.just(action);\n    }\n\n    @Override\n    public Flowable<Action> afterDispatch(Action action) {\n        Log.d(\"[next todo]\", getStore().todoList().toString());\n        return Flowable.just(action);\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/java/info/izumin/android/droidux/example/todoswithundo/reducer/TodoListReducer.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo.reducer;\n\nimport info.izumin.android.droidux.annotation.Dispatchable;\nimport info.izumin.android.droidux.annotation.Reducer;\nimport info.izumin.android.droidux.annotation.Undoable;\nimport info.izumin.android.droidux.example.todoswithundo.action.AddTodoAction;\nimport info.izumin.android.droidux.example.todoswithundo.action.ClearCompletedTodoAction;\nimport info.izumin.android.droidux.example.todoswithundo.action.DeleteTodoAction;\nimport info.izumin.android.droidux.example.todoswithundo.action.ToggleCompletedTodoAction;\nimport info.izumin.android.droidux.example.todoswithundo.entity.TodoList;\nimport io.reactivex.Observable;\n\n/**\n * Created by izumin on 11/4/15.\n */\n@Undoable\n@Reducer(TodoList.class)\npublic class TodoListReducer {\n    public static final String TAG = TodoListReducer.class.getSimpleName();\n\n    @Dispatchable(AddTodoAction.class)\n    public TodoList onAddedTodo(TodoList state, AddTodoAction action) {\n        if (state.isEmpty()) {\n            TodoList newState = new TodoList(state);\n            newState.add(new TodoList.Todo(0, action.getText()));\n            return newState;\n        }\n        int id = Observable.fromIterable(state)\n                .reduce((todo, todo2) -> (todo.getId() < todo2.getId()) ? todo2 : todo)\n                .onErrorReturn(throwable -> new TodoList.Todo(0, \"\"))\n                .toObservable()\n                .blockingLast()\n                .getId();\n        TodoList newState = new TodoList(state);\n        newState.add(new TodoList.Todo(id + 1, action.getText()));\n        return newState;\n    }\n\n    @Dispatchable(ToggleCompletedTodoAction.class)\n    public TodoList onCompletedTodo(TodoList state, ToggleCompletedTodoAction action) {\n        return new TodoList(Observable.fromIterable(state)\n                .map(todo -> {\n                    if (todo.getId() == action.getId()) {\n                        return new TodoList.Todo(todo.getId(), todo.getText(), !todo.isCompleted());\n                    }\n                    return todo;\n                })\n                .toList().blockingGet()\n        );\n    }\n\n    @Dispatchable(ClearCompletedTodoAction.class)\n    public TodoList onClearCompletedTodo(TodoList state, ClearCompletedTodoAction action) {\n        return new TodoList(Observable.fromIterable(state)\n                .filter(todo -> !todo.isCompleted()).toList().blockingGet()\n        );\n    }\n\n    @Dispatchable(DeleteTodoAction.class)\n    public TodoList onDeletedTodo(TodoList state, DeleteTodoAction action) {\n        return new TodoList(Observable.fromIterable(state)\n                .filter(todo -> todo.getId() != action.getId()).toList().blockingGet()\n        );\n    }\n}\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <data>\n    </data>\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n        android:paddingRight=\"@dimen/activity_horizontal_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\"\n        android:paddingBottom=\"@dimen/activity_vertical_margin\"\n        tools:context=\".MainActivity\" >\n\n        <ListView\n            android:id=\"@+id/list_todo\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_above=\"@+id/btn_add_todo\" />\n\n        <EditText\n            android:id=\"@+id/edit_new_todo\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_toLeftOf=\"@+id/btn_add_todo\"\n            android:hint=\"@string/edit_new_todo_hint\" />\n\n        <Button\n            android:id=\"@+id/btn_add_todo\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_alignParentBottom=\"true\"\n            android:text=\"@string/btn_add_todo\" />\n    </RelativeLayout>\n</layout>\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/res/layout/list_item_todo.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\" >\n    <data>\n        <import type=\"info.izumin.android.droidux.example.todoswithundo.entity.TodoList.Todo\" />\n        <variable name=\"todo\" type=\"Todo\" />\n    </data>\n    <LinearLayout\n        android:orientation=\"horizontal\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n        android:paddingRight=\"@dimen/activity_horizontal_margin\"\n        android:paddingTop=\"@dimen/activity_vertical_margin\"\n        android:paddingBottom=\"@dimen/activity_vertical_margin\" >\n\n        <CheckBox android:id=\"@+id/checkbox_todo\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:focusable=\"false\"\n            android:checked=\"@{todo.isCompleted()}\"/>\n\n        <TextView android:id=\"@+id/text_todo\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:focusable=\"false\"\n            android:text=\"@{todo.getText()}\"\n            tools:text=\"sample text\" />\n    </LinearLayout>\n</layout>\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/res/menu/main_manu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <item android:id=\"@+id/menu_clear_completed_todo\"\n        android:title=\"@string/menu_clear_completed_todo\"\n        app:showAsAction=\"never\" />\n    <item android:id=\"@+id/menu_undo_todo\"\n        android:title=\"@string/menu_undo_todo\"\n        app:showAsAction=\"never\" />\n    <item android:id=\"@+id/menu_redo_todo\"\n        android:title=\"@string/menu_redo_todo\"\n        app:showAsAction=\"never\" />\n</menu>"
  },
  {
    "path": "examples/todos-with-undo/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "examples/todos-with-undo/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    <dimen name=\"fab_margin\">16dp</dimen>\n\n</resources>\n"
  },
  {
    "path": "examples/todos-with-undo/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Todos with undo</string>\n    <string name=\"title_activity_main\">Todos with undo</string>\n\n    <string name=\"btn_add_todo\">Add</string>\n    <string name=\"edit_new_todo_hint\">new task</string>\n\n    <string name=\"dialog_delete_todo_title\">Delete todo</string>\n    <string name=\"dialog_delete_todo_message\">Are you sure you want to delete \"%s\"?</string>\n    <string name=\"dialog_delete_todo_btn_positive\">OK</string>\n    <string name=\"dialog_delete_todo_btn_neutral\">Cancel</string>\n\n    <string name=\"toast_add_todo\">Added new task !</string>\n    <string name=\"toast_delete_todo\">Deleted task $d !</string>\n\n    <string name=\"menu_clear_completed_todo\">Clear completed tasks</string>\n    <string name=\"menu_undo_todo\">Undo</string>\n    <string name=\"menu_redo_todo\">Redo</string>\n</resources>\n"
  },
  {
    "path": "examples/todos-with-undo/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        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n    <style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\" />\n    <style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\" />\n\n</resources>\n"
  },
  {
    "path": "examples/todos-with-undo/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": "examples/todos-with-undo/src/test/java/info/izumin/android/droidux/example/todoswithundo/ExampleUnitTest.java",
    "content": "package info.izumin.android.droidux.example.todoswithundo;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work on unit tests, switch the Test Artifact in the Build Variants view.\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Mon Jan 01 18:04:23 JST 2018\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-4.1-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\n\nproject_group = info.izumin.android\nproject_url = https://github.com/izumin5210/Droidux\nproject_bintray_org = izumin5210\n"
  },
  {
    "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\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\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%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "middlewares/droidux-thunk/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "middlewares/droidux-thunk/build.gradle",
    "content": "apply plugin: 'java'\napply plugin: 'groovy'\napply plugin: 'com.novoda.bintray-release'\n\ntargetCompatibility = JavaVersion.VERSION_1_7\nsourceCompatibility = JavaVersion.VERSION_1_7\n\ndependencies {\n    compile project(':droidux')\n\n    testCompile \"org.spockframework:spock-core:${spockCoreVersion}\"\n    testCompile \"cglib:cglib-nodep:${project.cglibVersion}\"\n}\n\npublish {\n    userOrg = project_bintray_org\n    groupId = project_group\n    artifactId = 'droidux-thunk'\n    version = '0.3.0'\n    description = 'Thunk middleware for Droidux.'\n    website = project_url\n}\n"
  },
  {
    "path": "middlewares/droidux-thunk/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 /usr/local/opt/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"
  },
  {
    "path": "middlewares/droidux-thunk/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"info.izumin.android.droidux.thunk\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\">\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "middlewares/droidux-thunk/src/main/java/info/izumin/android/droidux/thunk/AsyncAction.java",
    "content": "package info.izumin.android.droidux.thunk;\n\nimport info.izumin.android.droidux.Action;\nimport info.izumin.android.droidux.Dispatcher;\nimport io.reactivex.Flowable;\n\n/**\n * Created by izumin on 11/29/15.\n */\npublic interface AsyncAction extends Action {\n    Flowable<Action> call(Dispatcher dispatcher);\n}\n"
  },
  {
    "path": "middlewares/droidux-thunk/src/main/java/info/izumin/android/droidux/thunk/ThunkMiddleware.java",
    "content": "package info.izumin.android.droidux.thunk;\n\nimport info.izumin.android.droidux.Action;\nimport info.izumin.android.droidux.Middleware;\nimport io.reactivex.Flowable;\nimport io.reactivex.functions.Function;\n\n/**\n * Created by izumin on 11/29/15.\n */\npublic class ThunkMiddleware extends Middleware {\n    public static final String TAG = ThunkMiddleware.class.getSimpleName();\n\n    @Override\n    public Flowable<Action> beforeDispatch(final Action action) {\n        if (action instanceof AsyncAction) {\n            return ((AsyncAction) action).call(getDispatcher())\n                    .flatMap(new Function<Action, Flowable<? extends Action>>() {\n                        @Override\n                        public Flowable<Action> apply(Action next) throws Exception {\n                            return getDispatcher().dispatch(next);\n                        }\n                    })\n                    .flatMap(new Function<Action, Flowable<? extends Action>>() {\n                        @Override\n                        public Flowable<Action> apply(Action _next) throws Exception {\n                            return Flowable.just(action);\n                        }\n                    });\n        }\n        return Flowable.just(action);\n    }\n\n    @Override\n    public Flowable<Action> afterDispatch(Action action) {\n        return Flowable.just(action);\n    }\n}\n"
  },
  {
    "path": "middlewares/droidux-thunk/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">DroiduxThunk</string>\n</resources>\n"
  },
  {
    "path": "middlewares/droidux-thunk/src/test/groovy/info/izumin/android/droidux/thunk/ThunkMiddlewareTest.groovy",
    "content": "package info.izumin.android.droidux.thunk\n\nimport info.izumin.android.droidux.Action\nimport info.izumin.android.droidux.Dispatcher\nimport info.izumin.android.droidux.Middleware\nimport info.izumin.android.droidux.StoreImpl\nimport io.reactivex.Flowable\nimport spock.lang.Specification\n\n/**\n * Created by izumin on 11/29/15.\n */\nclass ThunkMiddlewareTest extends Specification {\n\n    def store1\n    def store2\n    def thunkMiddleware\n    def middleware1\n    def middleware2\n    def preAction\n    def action\n    def asyncAction\n    def dispatcher\n\n    def setup() {\n        store1 = Mock(StoreImpl.class, constructorArgs: [null, null])\n        store2 = Mock(StoreImpl.class, constructorArgs: [null, null])\n        thunkMiddleware = new ThunkMiddleware()\n        middleware1 = Mock(Middleware.class)\n        middleware2 = Mock(Middleware.class)\n        preAction = Mock(Action.class)\n        action = Mock(Action.class)\n        asyncAction = new AsyncAction() {\n            @Override\n            Flowable<Action> call(Dispatcher d) {\n                d.dispatch(preAction).flatMap({_a -> Flowable.just(action) }) as Flowable<Action>\n            }\n        }\n\n        def middlewares = new ArrayList<Middleware>()\n        middlewares.add(middleware1)\n        middlewares.add(thunkMiddleware)\n        middlewares.add(middleware2)\n\n        dispatcher = new Dispatcher(middlewares, store1, store2)\n        thunkMiddleware.onAttach(null, dispatcher)\n    }\n\n    def \"dispatch AsyncAction\"() {\n        when:\n        dispatcher.dispatch(asyncAction).subscribe()\n\n        then:\n        1 * middleware1.beforeDispatch(asyncAction) >> Flowable.just(asyncAction)\n\n        then:\n        1 * middleware1.beforeDispatch(preAction) >> Flowable.just(preAction)\n\n        then:\n        1 * middleware2.beforeDispatch(preAction) >> Flowable.just(preAction)\n\n        then:\n        1 * store1.dispatch(preAction)\n\n        then:\n        1 * store2.dispatch(preAction)\n\n        then:\n        1 * middleware2.afterDispatch(preAction) >> Flowable.just(preAction)\n\n        then:\n        1 * middleware1.afterDispatch(preAction) >> Flowable.just(preAction)\n\n        then:\n        1 * middleware1.beforeDispatch(action) >> Flowable.just(action)\n\n        then:\n        1 * middleware2.beforeDispatch(action) >> Flowable.just(action)\n\n        then:\n        1 * store1.dispatch(action)\n\n        then:\n        1 * store2.dispatch(action)\n\n        then:\n        1 * middleware2.afterDispatch(action) >> Flowable.just(action)\n\n        then:\n        1 * middleware1.afterDispatch(action) >> Flowable.just(action)\n\n        then:\n        1 * middleware2.beforeDispatch(asyncAction) >> Flowable.just(asyncAction)\n\n        then:\n        1 * store1.dispatch(asyncAction)\n\n        then:\n        1 * store2.dispatch(asyncAction)\n\n        then:\n        1 * middleware2.afterDispatch(asyncAction) >> Flowable.just(asyncAction)\n\n        then:\n        1 * middleware1.afterDispatch(asyncAction) >> Flowable.just(asyncAction)\n    }\n}\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':droidux', ':droidux-processor', ':middlewares:droidux-thunk'\ninclude ':examples:counter', ':examples:todomvc', ':examples:todos-with-undo', ':examples:todos-with-dagger'\n"
  }
]