├── .gitignore ├── .travis.yml ├── CHANGELOG.txt ├── README.md ├── build.gradle ├── dev.txt ├── frodo2-api ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── fernandocejas │ └── frodo2 │ ├── annotation │ ├── RxLogCompletable.java │ ├── RxLogFlowable.java │ ├── RxLogMaybe.java │ ├── RxLogObservable.java │ └── RxLogSingle.java │ └── logging │ └── Logger.java ├── frodo2-logger ├── build.gradle └── src │ ├── main │ └── java │ │ └── com │ │ └── fernandocejas │ │ └── frodo2 │ │ └── logger │ │ ├── completable │ │ ├── CompletableWeaver.java │ │ └── FrodoForCompletable.java │ │ ├── flowable │ │ ├── FlowableWeaver.java │ │ └── FrodoForFlowable.java │ │ ├── joinpoint │ │ ├── FrodoJoinPoint.java │ │ ├── FrodoProceedingJoinPoint.java │ │ ├── RxComponent.java │ │ └── RxComponentInfo.java │ │ ├── logging │ │ ├── Counter.java │ │ ├── MessageBuilder.java │ │ ├── MessageManager.java │ │ └── StopWatch.java │ │ ├── maybe │ │ ├── FrodoForMaybe.java │ │ └── MaybeWeaver.java │ │ ├── observable │ │ ├── FrodoForObservable.java │ │ └── ObservableWeaver.java │ │ └── single │ │ ├── FrodoForSingle.java │ │ └── SingleWeaver.java │ └── test │ └── java │ └── com │ └── fernandocejas │ └── frodo2 │ ├── logger │ ├── completable │ │ ├── CompletableRule.java │ │ ├── CompletableWeaverTest.java │ │ └── FrodoForCompletableTest.java │ ├── flowable │ │ ├── FlowableRule.java │ │ ├── FlowableWeaverTest.java │ │ └── FrodoForFlowableTest.java │ ├── joinpoint │ │ ├── FrodoJoinPointTest.java │ │ ├── FrodoProceedingJoinPointTest.java │ │ ├── RxComponentInfoTest.java │ │ └── RxComponentTest.java │ ├── logging │ │ ├── CounterTest.java │ │ └── StopWatchTest.java │ ├── maybe │ │ ├── FrodoForMaybeTest.java │ │ ├── MaybeRule.java │ │ └── MaybeWeaverTest.java │ ├── observable │ │ ├── FrodoForObservableTest.java │ │ ├── ObservableRule.java │ │ └── ObservableWeaverTest.java │ └── single │ │ ├── FrodoForSingleTest.java │ │ ├── SingleRule.java │ │ └── SingleWeaverTest.java │ └── test │ ├── TestJoinPoint.java │ ├── TestProceedingJoinPoint.java │ └── UnitTest.java ├── frodo2-plugin ├── build.gradle └── src │ └── main │ ├── groovy │ └── com │ │ └── fernandocejas │ │ └── frodo2 │ │ └── plugin │ │ ├── FrodoEnablerExtension.groovy │ │ ├── FrodoPlugin.groovy │ │ ├── aspect │ │ └── AspectCompiler.groovy │ │ └── config │ │ ├── AndroidBuild.groovy │ │ ├── Build.groovy │ │ ├── BuildFactory.groovy │ │ └── JavaBuild.groovy │ └── resources │ └── META-INF │ └── gradle-plugins │ └── com.fernandocejas.frodo2.properties ├── frodo2-runtime-android ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── fernandocejas │ └── frodo2 │ └── android │ ├── AndroidLog.java │ ├── LogCompletable.java │ ├── LogFlowable.java │ ├── LogMaybe.java │ ├── LogObservable.java │ └── LogSingle.java ├── frodo2-runtime-java ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── fernandocejas │ └── frodo2 │ └── java │ ├── JavaLog.java │ ├── LogCompletable.java │ ├── LogFlowable.java │ ├── LogMaybe.java │ ├── LogObservable.java │ └── LogSingle.java ├── frodo2-sample-android ├── build.gradle ├── debug.keystore ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── fernandocejas │ │ └── example │ │ └── frodo2 │ │ ├── MainActivity.java │ │ ├── SamplesActivity.java │ │ └── sample │ │ ├── AndroidSamples.java │ │ ├── CompletableSamples.java │ │ ├── FlowableSamples.java │ │ ├── MaybeSamples.java │ │ ├── MyObserver.java │ │ ├── MySubscriber.java │ │ ├── ObservableSamples.java │ │ └── SingleSamples.java │ └── res │ ├── drawable-hdpi │ ├── ic_launcher.png │ └── logo.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── layout │ ├── activity_main.xml │ └── activity_samples.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── frodo2-sample-java ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── fernandocejas │ └── example │ └── frodo2 │ ├── CompletableSamples.java │ ├── FlowableSamples.java │ ├── JavaSamples.java │ ├── Main.java │ ├── MaybeSamples.java │ ├── MyObserver.java │ ├── MySubscriber.java │ ├── ObservableSamples.java │ └── SingleSamples.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── install_frodo2.sh ├── run_frodo2_android.sh ├── run_frodo2_java.sh └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows thumbnail db 2 | Thumbs.db 3 | 4 | # OSX files 5 | .DS_Store 6 | 7 | # built application files 8 | *.apk 9 | *.ap_ 10 | 11 | # files for the dex VM 12 | *.dex 13 | 14 | # Java class files 15 | *.class 16 | 17 | # generated files 18 | bin/ 19 | gen/ 20 | build/ 21 | 22 | # Local configuration file (sdk path, etc) 23 | local.properties 24 | 25 | # Eclipse project files 26 | .classpath 27 | .project 28 | 29 | # Android Studio 30 | .idea 31 | .gradle 32 | .gradletasknamecache 33 | /*/local.properties 34 | /*/out 35 | /*/*/build 36 | build 37 | /*/*/production 38 | *.iml 39 | *.iws 40 | *.ipr 41 | *~ 42 | *.swp -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | jdk: oraclejdk8 3 | sudo: false 4 | os: linux 5 | 6 | before_install: 7 | - yes | sdkmanager "platforms;android-26" 8 | - yes | sdkmanager "platforms;android-27" 9 | 10 | install: ./install_frodo2.sh 11 | 12 | android: 13 | components: 14 | - tools 15 | - platform-tools 16 | - build-tools-27.0.3 17 | - android-27 18 | - extra-google-m2repository 19 | - extra-android-m2repository 20 | - extra-android-support 21 | 22 | # Specify at least one system image, 23 | # if you need to run emulator(s) during your tests 24 | - sys-img-armeabi-v7a-android-16 25 | - sys-img-armeabi-v7a-android-21 26 | - sys-img-armeabi-v7a-android-22 27 | - sys-img-armeabi-v7a-android-25 28 | 29 | licenses: 30 | - 'android-sdk-license-.+' 31 | - 'google-gdk-license-.+' 32 | - 'android-sdk-preview-license-.+' 33 | 34 | script: 35 | ./gradlew runUnitTests 36 | 37 | -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------- 2 | VERSION 0.9.0 3 | ---------------------------------------------------------- 4 | FEATURE: @RxLogFlowable Logging Scope. 5 | FEATURE: @RxLogObservable Logging Scope. 6 | FEATURE: @RxLogSingle Logging Scope. 7 | FEATURE: @RxLogMaybe Logging Scope. 8 | FEATURE: @RxLogCompletable Logging Scope. 9 | FEATURE: Disable frodo via Gradle configuration. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Frodo 2 [![Build Status](https://travis-ci.org/android10/frodo2.svg?branch=master)](https://travis-ci.org/android10/frodo2) 4 | ========================= 5 | 6 | [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0) 7 | [![Platform](https://img.shields.io/badge/platform-kotlin-blue.svg)](https://kotlinlang.org/) 8 | [![Platform](https://img.shields.io/badge/platform-android-green.svg)](http://developer.android.com/index.html) 9 | [![Platform](https://img.shields.io/badge/platform-java-orange.svg)](https://docs.oracle.com/javase/8/docs/) 10 | 11 | ```Frodo 2``` is the second version of [Frodo](https://github.com/android10/frodo/), mainly used to make easier debugging projects where [RxJava 2](https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0) is used. 12 | Just annotated your code and voilá! 13 | 14 | - **On Android projects (both Kotlin and Java):** It is safe to persist any ```Frodo 2``` annotation in the codebase since the code generator will **ONLY** work on ```debug``` versions of the application where the plugin is applied. 15 | 16 | - **On pure Kotlin/Java projects: EXPERIMENTAL,** you can keep the annotation in the source code but you have to manually enable/disable the code generation (check **Enabling Frodo 2** section). 17 | 18 | RxJava 2 building blocks supported: 19 | * `Flowable` 20 | * `Observable` 21 | * `Single` 22 | * `Maybe` 23 | * `Completable` 24 | 25 | Check **Main Features** Section below for more details. 26 | 27 | ![frodo_hug](https://cloud.githubusercontent.com/assets/1360604/10925718/e7ea4318-8290-11e5-91b4-f2bfbde65319.gif) 28 | 29 | 30 | Main Features 31 | ========================= 32 | 33 | - **@RxLogFlowable:** Annotated functions which return ```io.reactivex.Flowable``` will print the following information on the log output: 34 | 35 | ```java 36 | @RxLogFlowable 37 | Flowable numbers() { 38 | return Flowable.just(1, 2, 3, 4); 39 | } 40 | ``` 41 | ``` 42 | Frodo2 => [@Flowable :: @InClass -> FlowableSamples :: @Method -> numbers()] 43 | Frodo2 => [@Flowable#numbers -> onSubscribe()] 44 | Frodo2 => [@Flowable#numbers -> onRequest() -> 9223372036854775807] 45 | Frodo2 => [@Flowable#numbers -> onNext() -> 1] 46 | Frodo2 => [@Flowable#numbers -> onNext() -> 2] 47 | Frodo2 => [@Flowable#numbers -> onNext() -> 3] 48 | Frodo2 => [@Flowable#numbers -> onNext() -> 4] 49 | Frodo2 => [@Flowable#numbers -> onComplete()] 50 | Frodo2 => [@Flowable#numbers -> onTerminate()] 51 | Frodo2 => [@Flowable#numbers -> @Emitted -> 4 elements :: @Time -> 1 ms] 52 | Frodo2 => [@Flowable#numbers -> @ObserveOn -> RxNewThreadScheduler-3] 53 | ``` 54 | 55 | - **@RxLogObservable:** Annotated functions which return ```io.reactivex.Observable``` will print the following information on the log output: 56 | 57 | ```java 58 | @RxLogObservable 59 | Observable strings() { 60 | return Observable.just("Hello", "My", "Name", "Is", "Fernando"); 61 | } 62 | ``` 63 | ``` 64 | Frodo2 => [@Observable :: @InClass -> ObservableSamples :: @Method -> strings()] 65 | Frodo2 => [@Observable#strings -> onSubscribe()] 66 | Frodo2 => [@Observable#strings -> onNext() -> Hello] 67 | Frodo2 => [@Observable#strings -> onNext() -> My] 68 | Frodo2 => [@Observable#strings -> onNext() -> Name] 69 | Frodo2 => [@Observable#strings -> onNext() -> Is] 70 | Frodo2 => [@Observable#strings -> onNext() -> Fernando] 71 | Frodo2 => [@Observable#strings -> onComplete()] 72 | Frodo2 => [@Observable#strings -> onTerminate()] 73 | Frodo2 => [@Observable#strings -> @Emitted -> 5 elements :: @Time -> 9 ms] 74 | Frodo2 => [@Observable#strings -> @ObserveOn -> RxCachedThreadScheduler-1] 75 | ``` 76 | 77 | - **@RxLogSingle:** Annotated functions which return ```io.reactivex.Single``` will print the following information on the log output: 78 | 79 | ```java 80 | @RxLogSingle 81 | Single string() { 82 | return Single.just("My Value"); 83 | } 84 | ``` 85 | ``` 86 | Frodo2 => [@Single :: @InClass -> SingleSamples :: @Method -> string()] 87 | Frodo2 => [@Single#string -> onSubscribe()] 88 | Frodo2 => [@Single#string -> onSuccess() -> My Value] 89 | Frodo2 => [@Single#string -> @Emitted -> 1 element :: @Time -> 0 ms] 90 | Frodo2 => [@Single#string -> @ObserveOn -> RxCachedThreadScheduler-1] 91 | ``` 92 | 93 | - **@RxLogMaybe:** Annotated functions which return ```io.reactivex.Maybe``` will print the following information on the log output: 94 | 95 | ```java 96 | @RxLogMaybe 97 | Maybe number() { 98 | return Maybe.just(1); 99 | } 100 | ``` 101 | ``` 102 | Frodo2 => [@Maybe :: @InClass -> MaybeSamples :: @Method -> number()] 103 | Frodo2 => [@Maybe#number -> onSubscribe()] 104 | Frodo2 => [@Maybe#number -> onSuccess() -> 1] 105 | Frodo2 => [@Maybe#number -> @Emitted -> 1 element :: @Time -> 0 ms] 106 | Frodo2 => [@Maybe#number -> @ObserveOn -> RxNewThreadScheduler-1] 107 | ``` 108 | 109 | - **@RxLogCompletable:** Annotated functions which return ```io.reactivex.Completable``` will print the following information on the log output: 110 | 111 | ```java 112 | @RxLogCompletable 113 | Completable doSomething() { 114 | return Completable.fromAction(new Action() { 115 | @Override public void run() throws Exception { 116 | Thread.sleep(1000); 117 | } 118 | }); 119 | } 120 | ``` 121 | ``` 122 | Frodo2 => [@Completable :: @InClass -> CompletableSamples :: @Method -> doSomething()] 123 | Frodo2 => [@Completable#doSomething -> onSubscribe()] 124 | Frodo2 => [@Completable#doSomething -> onComplete()] 125 | Frodo2 => [@Completable#doSomething -> @Emitted -> 0 elements :: @Time -> 1003 ms] 126 | ``` 127 | 128 | Enabling Frodo 2 129 | ========================= 130 | 131 | To enable Frodo, a gradle plugin must be applied in your ```build.gradle```: 132 | 133 | ```java 134 | buildscript { 135 | repositories { 136 | jcenter() 137 | } 138 | dependencies { 139 | classpath "com.fernandocejas.frodo2:frodo2-plugin:$project.version" 140 | } 141 | } 142 | 143 | apply plugin: 'com.fernandocejas.frodo2' 144 | 145 | //By default frodo2 is ON, although 146 | //we can enable-disable it with this configuration. 147 | frodo2 { 148 | enabled = true 149 | } 150 | ``` 151 | 152 | Experimental 153 | ========================= 154 | 155 | - Frodo 2 works only on **Android, Java and Kotlin*** projects using **Gradle** as Build System. 156 | 157 | - In **pure Java/Kotlin projects** all the debug information will be display using `System.out` (**NOT** the case of **Android** which displays on the **logcat**). The idea for future versions is to be able to use different Loggers like **Log4J** or any other alternative for example. 158 | 159 | - Contributions are more than welcome. 160 | 161 | Architecture Overview 162 | ========================= 163 | 164 | It generates and weaves code based on annotations at compile time. This code is injected using [Aspect Oriented Programming](https://fernandocejas.com/2014/08/03/aspect-oriented-programming-in-android/) with [AspectJ](https://www.eclipse.org/aspectj/). 165 | 166 | For more details please check these articles where there is a deeper explanation with implementation details: 167 | 168 | - [Debugging RxJava on Android](https://fernandocejas.com/2015/11/05/debugging-rxjava-on-android/) 169 | 170 | - [Aspect Oriented Programming in Android](https://fernandocejas.com/2014/08/03/aspect-oriented-programming-in-android/) 171 | 172 | ![aspectweaving](https://user-images.githubusercontent.com/1360604/40504693-4adf5a5e-5f92-11e8-89b3-e45c04b78745.png) 173 | 174 | 175 | Known issues 176 | ========================= 177 | 178 | 1 - **Limitation**: Frodo 1 has the ability to detect ```@SubscribeOn``` thread but RxJava 2 does not offer any way to grab this information so only ```@ObserveOn``` thread information is displayed at the moment. 179 | 180 | 2 - **On Android**: Multi module setup (application + android library) will not log annotated methods/classes from Android Library Module but will do it on Android Application Module. The reason behind this, is that the Android Gradle Plugin will build all Android Libraries as release versions, for instance, Frodo is not able to weave any code on the annotated methods/classes (Remember that only weaves in debug versions). There is a workaround for forcing debug versions of your Android Libraries (just be careful in case this is forgotten and you end up shipping a version of your app with RxJava Logging enabled) by adding this line in your ```build.gradle``` file: 181 | 182 | ```java 183 | android { 184 | defaultPublishConfig "debug" 185 | } 186 | ``` 187 | 188 | Local Development 189 | ========================= 190 | 191 | Clone the repo and use the scripts listed below in order to to run/install/execute frodo 2 locally: 192 | 193 | * `./install_frodo2.sh` - One time execution command for installing frodo library and dependencies. 194 | * `./run_frodo2_android.sh` - Compiles frodo2 and run the android sample application. 195 | * `./run_frodo2_java` - Compiles frodo2 and run the java sample application. 196 | * `./gradlew runUnitTests` - Execute all unit tests in the project. 197 | 198 | Contribution 199 | ========================= 200 | 201 | Here you can download and install the java codestyle. 202 | https://github.com/android10/java-code-styles 203 | 204 | License 205 | ========================= 206 | 207 | Copyright 2018 Fernando Cejas 208 | 209 | Licensed under the Apache License, Version 2.0 (the "License"); 210 | you may not use this file except in compliance with the License. 211 | You may obtain a copy of the License at 212 | 213 | http://www.apache.org/licenses/LICENSE-2.0 214 | 215 | Unless required by applicable law or agreed to in writing, software 216 | distributed under the License is distributed on an "AS IS" BASIS, 217 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 218 | See the License for the specific language governing permissions and 219 | limitations under the License. 220 | 221 | 222 | ![http://www.fernandocejas.com](https://github.com/android10/Sample-Data/blob/master/android10/android10_logo_big.png) 223 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenLocal() 4 | google() 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath "com.android.tools.build:gradle:$project.androidBuildToolsVersion" 9 | classpath "org.aspectj:aspectjtools:$project.aspectjVersion" 10 | classpath "com.github.dcendents:android-maven-gradle-plugin:$project.androidMavenVersion" 11 | } 12 | } 13 | 14 | subprojects { 15 | repositories { 16 | maven { 17 | url "http://dl.bintray.com/android10/maven" 18 | } 19 | mavenLocal() 20 | jcenter() 21 | google() 22 | } 23 | } 24 | 25 | if (JavaVersion.current().isJava8Compatible()) { 26 | allprojects { 27 | tasks.withType(Javadoc) { 28 | options.addStringOption('Xdoclint:none', '-quiet') 29 | } 30 | } 31 | } 32 | 33 | task wrapper(type: Wrapper) { 34 | gradleVersion = project.gradleVersion 35 | } 36 | 37 | task runUnitTests(dependsOn: [':frodo2-logger:test']) { 38 | description = 'Run unit tests for frodo 2 logger.' 39 | } 40 | -------------------------------------------------------------------------------- /dev.txt: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------- 2 | New Frodo version (TODO: automate these tasks) 3 | ---------------------------------------------------------- 4 | 1. Publish through gradle task: 5 | - ./gradlew publishFrodo2 6 | 7 | 2. Upload pom.xml manually (there is an issue with the publishing plugin) and publish on bintray: 8 | - https://github.com/novoda/bintray-release 9 | - https://github.com/novoda/bintray-release/issues/19 10 | 11 | 3. Generate and upload javadoc and sources manually on bintray for frodo2-runtime-android: 12 | - ./gradlew -p frodo2-runtime-android/ androidJavadocsJar 13 | - ./gradlew -p frodo2-runtime-android/ androidSourcesJar 14 | - https://bintray.com/android10/maven 15 | 16 | 3. Delete any local frodo repository and try the plugin with a new clean android project. 17 | - cd ~/.m2/repository/com/fernandocejas 18 | - rm -rf frodo2/ 19 | 20 | 4. Create a tag on github: 21 | - git tag 22 | - git tag -a v0.9.0 -m "Release version 0.9.0" 23 | - git tag 24 | - git show v0.9.0 25 | - git push origin v0.9.0 26 | 27 | 5. Release Notes: and description in both Github and Bintray. 28 | - Frodo wiki on github: https://github.com/android10/frodo2/wiki 29 | - Bintray description: https://bintray.com/android10/maven 30 | 31 | 6. Prepare for the next development version: 32 | - gradle.properties 'version' property 33 | - Build class in gradle plugin needs frodo version update (changes are no pick up automatically) 34 | - add new version CHANGELOG.txt file 35 | 36 | 7. Install new version by running either of these tasks: 37 | - ./install_frodo2.sh 38 | - ./run_frodo2_android.sh 39 | - ./run_frodo2_android.sh 40 | 41 | 8. Promote new version released 42 | ---------------------------------------------------------- 43 | 44 | ---------------------------------------------------------- 45 | POSSIBLE ISSUE #1 46 | ---------------------------------------------------------- 47 | - Installing frodo through './install_frodo2.sh' can trigger this exception: 48 | 49 | FAILURE: Build failed with an exception. 50 | 51 | * What went wrong: 52 | Execution failed for task ':frodo2-runtime-android:install'. 53 | > A problem occurred starting process 'command 'mvn'' 54 | 55 | - Solution: Stop Gradle by executing: './gradlew --stop' 56 | ---------------------------------------------------------- 57 | -------------------------------------------------------------------------------- /frodo2-api/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'maven' 3 | 4 | targetCompatibility = JavaVersion.VERSION_1_8 5 | sourceCompatibility = JavaVersion.VERSION_1_8 6 | 7 | //noinspection GroovyAssignabilityCheck 8 | task sourcesJar(type: Jar, dependsOn: classes) { 9 | classifier = 'sources' 10 | from sourceSets.main.allSource 11 | } 12 | 13 | //noinspection GroovyAssignabilityCheck 14 | task javadocJar(type: Jar, dependsOn: ['javadoc']) { 15 | classifier = 'javadoc' 16 | from 'build/docs/javadoc' 17 | } 18 | 19 | artifacts { 20 | archives jar 21 | archives sourcesJar 22 | } 23 | -------------------------------------------------------------------------------- /frodo2-api/src/main/java/com/fernandocejas/frodo2/annotation/RxLogCompletable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | 6 | import static java.lang.annotation.ElementType.METHOD; 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | @Retention(RUNTIME) 10 | @Target({ METHOD }) 11 | public @interface RxLogCompletable {} 12 | -------------------------------------------------------------------------------- /frodo2-api/src/main/java/com/fernandocejas/frodo2/annotation/RxLogFlowable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.annotation; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | @Retention(RUNTIME) 10 | @Target({ METHOD }) 11 | public @interface RxLogFlowable {} 12 | -------------------------------------------------------------------------------- /frodo2-api/src/main/java/com/fernandocejas/frodo2/annotation/RxLogMaybe.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.Target; 5 | 6 | import static java.lang.annotation.ElementType.METHOD; 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | @Retention(RUNTIME) 10 | @Target({ METHOD }) 11 | public @interface RxLogMaybe {} 12 | -------------------------------------------------------------------------------- /frodo2-api/src/main/java/com/fernandocejas/frodo2/annotation/RxLogObservable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.annotation; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | @Retention(RUNTIME) 10 | @Target({ METHOD }) 11 | public @interface RxLogObservable {} 12 | -------------------------------------------------------------------------------- /frodo2-api/src/main/java/com/fernandocejas/frodo2/annotation/RxLogSingle.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.annotation; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | @Retention(RUNTIME) 10 | @Target({ METHOD }) 11 | public @interface RxLogSingle {} 12 | -------------------------------------------------------------------------------- /frodo2-api/src/main/java/com/fernandocejas/frodo2/logging/Logger.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logging; 2 | 3 | /** 4 | * Copyright (C) 2017 android10.org Open Source Project 5 | *

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

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | public interface Logger { 19 | /** 20 | * Send a debug log message 21 | * 22 | * @param tag Source of a log message. It usually identifies the class or activity where the log 23 | * call occurs. 24 | * @param message The message you would like logged. 25 | */ 26 | void log(String tag, String message); 27 | } 28 | -------------------------------------------------------------------------------- /frodo2-logger/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'maven' 3 | 4 | targetCompatibility = JavaVersion.VERSION_1_7 5 | sourceCompatibility = JavaVersion.VERSION_1_7 6 | 7 | dependencies { 8 | implementation "org.jetbrains:annotations:$project.annotationsVersion" 9 | implementation "org.aspectj:aspectjrt:$project.aspectjVersion" 10 | implementation "io.reactivex.rxjava2:rxjava:$project.rxJavaVersion" 11 | implementation project(':frodo2-api') 12 | 13 | testImplementation "junit:junit:$project.junitVersion" 14 | testImplementation "org.assertj:assertj-core:$project.assertJVersion" 15 | testImplementation "org.mockito:mockito-core:$project.mockitoVersion" 16 | } 17 | 18 | //noinspection GroovyAssignabilityCheck 19 | task javadocJar(type: Jar, dependsOn: ['javadoc']) { 20 | classifier = 'javadoc' 21 | from 'build/docs/javadoc' 22 | } 23 | 24 | artifacts { 25 | archives jar 26 | } 27 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/completable/CompletableWeaver.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.completable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.logging.MessageBuilder; 5 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 6 | import com.fernandocejas.frodo2.logging.Logger; 7 | 8 | import org.aspectj.lang.ProceedingJoinPoint; 9 | import org.aspectj.lang.reflect.MethodSignature; 10 | 11 | import io.reactivex.Completable; 12 | 13 | /** 14 | * Copyright (C) 2017 android10.org Open Source Project 15 | *

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

20 | * http://www.apache.org/licenses/LICENSE-2.0 21 | *

22 | * Unless required by applicable law or agreed to in writing, software 23 | * distributed under the License is distributed on an "AS IS" BASIS, 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25 | * See the License for the specific language governing permissions and 26 | * limitations under the License. 27 | */ 28 | public class CompletableWeaver { 29 | 30 | public static final String POINTCUT = 31 | "execution(@com.fernandocejas.frodo2.annotation.RxLogCompletable * *(..)) && if()"; 32 | public static final String ADVICE = "methodAnnotatedWithRxLogCompletable(joinPoint)"; 33 | 34 | public static boolean methodAnnotatedWithRxLogCompletable(ProceedingJoinPoint joinPoint) { 35 | return ((MethodSignature) joinPoint.getSignature()).getReturnType() == Completable.class; 36 | } 37 | 38 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint, Logger logger) 39 | throws Throwable { 40 | final FrodoProceedingJoinPoint proceedingJoinPoint = new FrodoProceedingJoinPoint(joinPoint); 41 | final MessageManager messageManager = new MessageManager(new MessageBuilder(), logger); 42 | return new FrodoForCompletable(proceedingJoinPoint, messageManager).completable(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/completable/FrodoForCompletable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.completable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponent; 5 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 6 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 7 | import com.fernandocejas.frodo2.logger.logging.StopWatch; 8 | 9 | import io.reactivex.Completable; 10 | import io.reactivex.disposables.Disposable; 11 | import io.reactivex.functions.Action; 12 | import io.reactivex.functions.Consumer; 13 | 14 | @SuppressWarnings({"unchecked", "Convert2Lambda"}) 15 | class FrodoForCompletable { 16 | 17 | private final FrodoProceedingJoinPoint joinPoint; 18 | private final MessageManager messageManager; 19 | private final RxComponentInfo rxComponentInfo; 20 | 21 | FrodoForCompletable(FrodoProceedingJoinPoint joinPoint, MessageManager messageManager) { 22 | this.joinPoint = joinPoint; 23 | this.messageManager = messageManager; 24 | this.rxComponentInfo = new RxComponentInfo(RxComponent.COMPLETABLE, joinPoint); 25 | } 26 | 27 | Completable completable() throws Throwable { 28 | messageManager.printRxComponentInfo(rxComponentInfo); 29 | return loggableCompletable(); 30 | } 31 | 32 | private Completable loggableCompletable() throws Throwable { 33 | final StopWatch stopWatch = new StopWatch(); 34 | return ((Completable) joinPoint.proceed()) 35 | .doOnSubscribe(new Consumer() { 36 | @Override 37 | public void accept(Disposable disposable) throws Exception { 38 | stopWatch.start(); 39 | messageManager.printOnSubscribe(rxComponentInfo); 40 | } 41 | }) 42 | .doOnEvent(new Consumer() { 43 | @Override public void accept(Throwable throwable) throws Exception { 44 | //do nothing here yet 45 | } 46 | }) 47 | .doOnComplete(new Action() { 48 | @Override 49 | public void run() throws Exception { 50 | messageManager.printOnComplete(rxComponentInfo); 51 | } 52 | }) 53 | .doOnError(new Consumer() { 54 | @Override 55 | public void accept(Throwable throwable) throws Exception { 56 | messageManager.printOnError(rxComponentInfo, throwable); 57 | } 58 | }) 59 | .doOnDispose(new Action() { 60 | @Override 61 | public void run() throws Exception { 62 | messageManager.printOnDispose(rxComponentInfo); 63 | } 64 | }) 65 | .doFinally(new Action() { 66 | @Override 67 | public void run() throws Exception { 68 | stopWatch.stop(); 69 | rxComponentInfo.setTotalExecutionTime(stopWatch.getTotalTimeMillis()); 70 | rxComponentInfo.setTotalEmittedItems(0); 71 | messageManager.printItemTimeInfo(rxComponentInfo); 72 | messageManager.printThreadInfo(rxComponentInfo); 73 | } 74 | }); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/flowable/FlowableWeaver.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.flowable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.logging.MessageBuilder; 5 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 6 | import com.fernandocejas.frodo2.logging.Logger; 7 | import io.reactivex.Flowable; 8 | import org.aspectj.lang.ProceedingJoinPoint; 9 | import org.aspectj.lang.reflect.MethodSignature; 10 | 11 | /** 12 | * Copyright (C) 2017 android10.org Open Source Project 13 | *

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

18 | * http://www.apache.org/licenses/LICENSE-2.0 19 | *

20 | * Unless required by applicable law or agreed to in writing, software 21 | * distributed under the License is distributed on an "AS IS" BASIS, 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | * See the License for the specific language governing permissions and 24 | * limitations under the License. 25 | */ 26 | public class FlowableWeaver { 27 | 28 | public static final String POINTCUT = 29 | "execution(@com.fernandocejas.frodo2.annotation.RxLogFlowable * *(..)) && if()"; 30 | public static final String ADVICE = "methodAnnotatedWithRxLogFlowable(joinPoint)"; 31 | 32 | public static boolean methodAnnotatedWithRxLogFlowable(ProceedingJoinPoint joinPoint) { 33 | return ((MethodSignature) joinPoint.getSignature()).getReturnType() == Flowable.class; 34 | } 35 | 36 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint, Logger logger) 37 | throws Throwable { 38 | final FrodoProceedingJoinPoint proceedingJoinPoint = new FrodoProceedingJoinPoint(joinPoint); 39 | final MessageManager messageManager = new MessageManager(new MessageBuilder(), logger); 40 | return new FrodoForFlowable(proceedingJoinPoint, messageManager).flowable(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/flowable/FrodoForFlowable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.flowable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponent; 5 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 6 | import com.fernandocejas.frodo2.logger.logging.Counter; 7 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 8 | import com.fernandocejas.frodo2.logger.logging.StopWatch; 9 | 10 | import org.reactivestreams.Subscription; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.functions.Action; 14 | import io.reactivex.functions.Consumer; 15 | import io.reactivex.functions.LongConsumer; 16 | 17 | @SuppressWarnings({"unchecked", "Convert2Lambda"}) 18 | class FrodoForFlowable { 19 | 20 | private final FrodoProceedingJoinPoint joinPoint; 21 | private final MessageManager messageManager; 22 | private final RxComponentInfo rxComponentInfo; 23 | 24 | FrodoForFlowable(FrodoProceedingJoinPoint joinPoint, MessageManager messageManager) { 25 | this.joinPoint = joinPoint; 26 | this.messageManager = messageManager; 27 | this.rxComponentInfo = new RxComponentInfo(RxComponent.FLOWABLE, joinPoint); 28 | } 29 | 30 | Flowable flowable() throws Throwable { 31 | messageManager.printRxComponentInfo(rxComponentInfo); 32 | final Class flowableType = joinPoint.getGenericReturnTypes().get(0); 33 | return loggableFlowable(flowableType); 34 | } 35 | 36 | private Flowable loggableFlowable(T type) throws Throwable { 37 | final StopWatch stopWatch = new StopWatch(); 38 | final Counter emittedItems = new Counter(joinPoint.getMethodName()); 39 | return ((Flowable) joinPoint.proceed()) 40 | .doOnSubscribe(new Consumer() { 41 | @Override 42 | public void accept(Subscription subscription) throws Exception { 43 | stopWatch.start(); 44 | messageManager.printOnSubscribe(rxComponentInfo); 45 | } 46 | }) 47 | .doOnNext(new Consumer() { 48 | @Override 49 | public void accept(T value) throws Exception { 50 | if (rxComponentInfo.observeOnThread() == null) { 51 | rxComponentInfo.setObserveOnThread(Thread.currentThread().getName()); 52 | } 53 | emittedItems.increment(); 54 | messageManager.printOnNextWithValue(rxComponentInfo, value); 55 | } 56 | }) 57 | .doOnError(new Consumer() { 58 | @Override 59 | public void accept(Throwable throwable) throws Exception { 60 | messageManager.printOnError(rxComponentInfo, throwable); 61 | } 62 | }) 63 | .doOnComplete(new Action() { 64 | @Override 65 | public void run() throws Exception { 66 | messageManager.printOnComplete(rxComponentInfo); 67 | } 68 | }) 69 | .doOnTerminate(new Action() { 70 | @Override 71 | public void run() throws Exception { 72 | messageManager.printOnTerminate(rxComponentInfo); 73 | } 74 | }) 75 | .doOnRequest(new LongConsumer() { 76 | @Override 77 | public void accept(long count) throws Exception { 78 | messageManager.printOnRequestWithCount(rxComponentInfo, count); 79 | } 80 | }) 81 | .doOnCancel(new Action() { 82 | @Override 83 | public void run() throws Exception { 84 | messageManager.printOnCancel(rxComponentInfo); 85 | } 86 | }) 87 | .doFinally(new Action() { 88 | @Override 89 | public void run() throws Exception { 90 | stopWatch.stop(); 91 | rxComponentInfo.setTotalExecutionTime(stopWatch.getTotalTimeMillis()); 92 | rxComponentInfo.setTotalEmittedItems(emittedItems.tally()); 93 | messageManager.printItemTimeInfo(rxComponentInfo); 94 | messageManager.printThreadInfo(rxComponentInfo); 95 | } 96 | }); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/joinpoint/FrodoJoinPoint.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.joinpoint; 2 | 3 | import org.aspectj.lang.JoinPoint; 4 | import org.aspectj.lang.Signature; 5 | import org.aspectj.lang.reflect.MethodSignature; 6 | 7 | import java.lang.annotation.Annotation; 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.ParameterizedType; 10 | import java.lang.reflect.Type; 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | /** 17 | * Wrapper around {@link org.aspectj.lang.JoinPoint} to make easy retrieve data from a certain 18 | * {@link org.aspectj.lang.JoinPoint} passed as a parameter in the constructor. 19 | */ 20 | public class FrodoJoinPoint { 21 | 22 | private final JoinPoint joinPoint; 23 | private final MethodSignature methodSignature; 24 | private final String classCanonicalName; 25 | private final String classSimpleName; 26 | private final String methodName; 27 | private final List methodParamTypesList; 28 | private final List methodParamNamesList; 29 | private final List methodParamValuesList; 30 | private final String executionThreadName; 31 | private final String joinPointUniqueName; 32 | 33 | /** 34 | * Constructor of the class 35 | * 36 | * @param joinPoint object to wrap around. 37 | */ 38 | public FrodoJoinPoint(JoinPoint joinPoint) { 39 | if (joinPoint == null) { 40 | throw new IllegalArgumentException("Constructor parameters cannot be null!!!"); 41 | } 42 | 43 | this.joinPoint = joinPoint; 44 | this.methodSignature = (MethodSignature) this.joinPoint.getSignature(); 45 | this.classCanonicalName = this.methodSignature.getDeclaringType().getCanonicalName(); 46 | this.classSimpleName = this.methodSignature.getDeclaringType().getSimpleName(); 47 | this.methodName = this.methodSignature.getName(); 48 | this.executionThreadName = Thread.currentThread().getName(); 49 | final Class[] parameterTypes = this.methodSignature.getParameterTypes(); 50 | final String[] parameterNames = this.methodSignature.getParameterNames(); 51 | final Object[] args = this.joinPoint.getArgs(); 52 | this.methodParamTypesList = parameterTypes != null ? 53 | Arrays.asList(parameterTypes) : Collections.emptyList(); 54 | this.methodParamNamesList = parameterNames != null ? 55 | Arrays.asList(parameterNames) : Collections.emptyList(); 56 | this.methodParamValuesList = args != null ? Arrays.asList(args) : Collections.emptyList(); 57 | this.joinPointUniqueName = this.generateJoinPointUniqueName(); 58 | } 59 | 60 | public String getClassSimpleName() { 61 | return classSimpleName; 62 | } 63 | 64 | public String getMethodName() { 65 | return methodName; 66 | } 67 | 68 | public List getMethodParamTypesList() { 69 | return methodParamTypesList; 70 | } 71 | 72 | public List getMethodParamNamesList() { 73 | return methodParamNamesList; 74 | } 75 | 76 | public List getMethodParamValuesList() { 77 | return methodParamValuesList; 78 | } 79 | 80 | public String getExecutionThreadName() { 81 | return executionThreadName; 82 | } 83 | 84 | /** 85 | * Gets an annotation from a method, will return null in case it does not exist. 86 | * It is important to have a retention policy of 87 | * {@link java.lang.annotation.RetentionPolicy#RUNTIME} to avoid null values when reading them. 88 | * 89 | * @param annotation The {@link Annotation} to get. 90 | * @return The annotation if exists, otherwise null. 91 | */ 92 | public Annotation getAnnotation(Class annotation) { 93 | return methodSignature.getMethod().getAnnotation(annotation); 94 | } 95 | 96 | /** 97 | * Check if the {@link JoinPoint} has a return type. 98 | * 99 | * @param joinPoint the {@link JoinPoint} to check. 100 | * @return true if there is a return type, false if it is void. 101 | */ 102 | public boolean hasReturnType(JoinPoint joinPoint) { 103 | Signature signature = joinPoint.getSignature(); 104 | 105 | return (signature instanceof MethodSignature 106 | && ((MethodSignature) signature).getReturnType() != void.class); 107 | } 108 | 109 | /** 110 | * {@link MethodSignature#getReturnType()}. 111 | */ 112 | public Class getReturnType() { 113 | return methodSignature.getReturnType(); 114 | } 115 | 116 | /** 117 | * {@link Method#getGenericReturnType()}. 118 | */ 119 | public List getGenericReturnTypes() { 120 | final Type returnType = methodSignature.getMethod().getGenericReturnType(); 121 | if (returnType instanceof ParameterizedType) { 122 | final Type[] typeArguments = ((ParameterizedType) returnType).getActualTypeArguments(); 123 | final List genericReturnTypes = new ArrayList<>(typeArguments.length); 124 | for (Type typeArgument : typeArguments) { 125 | genericReturnTypes.add(typeArgument.getClass()); 126 | } 127 | return genericReturnTypes; 128 | } 129 | final Class clazz = (Class) returnType; 130 | return Collections.singletonList(clazz); 131 | } 132 | 133 | /** 134 | * {@link JoinPoint#getTarget()}. 135 | */ 136 | public Object getTarget() { 137 | return joinPoint.getTarget(); 138 | } 139 | 140 | /** 141 | * Get wrapped {@link JoinPoint}. 142 | */ 143 | public JoinPoint getJoinPoint() { 144 | return joinPoint; 145 | } 146 | 147 | @Override 148 | public boolean equals(Object object) { 149 | if (object == this) { 150 | return true; 151 | } 152 | 153 | if ((object == null) || (object.getClass() != this.getClass())) { 154 | return false; 155 | } 156 | 157 | FrodoJoinPoint joinPoint = (FrodoJoinPoint) object; 158 | return this.joinPointUniqueName.equals(joinPoint.joinPointUniqueName); 159 | } 160 | 161 | @Override 162 | public int hashCode() { 163 | return this.joinPointUniqueName.hashCode(); 164 | } 165 | 166 | private String generateJoinPointUniqueName() { 167 | StringBuilder stringBuilder = new StringBuilder(256); 168 | stringBuilder.append(this.classCanonicalName); 169 | stringBuilder.append("."); 170 | stringBuilder.append(this.methodName); 171 | stringBuilder.append("("); 172 | if (!this.methodParamNamesList.isEmpty()) { 173 | for (int i = 0; i < this.methodParamNamesList.size(); i++) { 174 | stringBuilder.append(this.methodParamTypesList.get(i).getSimpleName()); 175 | stringBuilder.append(" "); 176 | stringBuilder.append(this.methodParamNamesList.get(i)); 177 | if ((i != this.methodParamNamesList.size() - 1)) { 178 | stringBuilder.append(", "); 179 | } 180 | } 181 | } 182 | stringBuilder.append(")"); 183 | 184 | return stringBuilder.toString(); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/joinpoint/FrodoProceedingJoinPoint.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.joinpoint; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | 5 | public class FrodoProceedingJoinPoint extends FrodoJoinPoint { 6 | 7 | private final ProceedingJoinPoint proceedingJoinPoint; 8 | 9 | public FrodoProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint) { 10 | super(proceedingJoinPoint); 11 | this.proceedingJoinPoint = proceedingJoinPoint; 12 | } 13 | 14 | /** 15 | * {@link ProceedingJoinPoint#proceed()} 16 | */ 17 | public Object proceed() throws Throwable { 18 | return proceedingJoinPoint.proceed(); 19 | } 20 | 21 | /** 22 | * {@link ProceedingJoinPoint#proceed(Object[])} 23 | */ 24 | public Object proceed(Object[] args) throws Throwable { 25 | return proceedingJoinPoint.proceed(args); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/joinpoint/RxComponent.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.joinpoint; 2 | 3 | public enum RxComponent { 4 | FLOWABLE, 5 | OBSERVABLE, 6 | SINGLE, 7 | MAYBE, 8 | COMPLETABLE; 9 | 10 | @Override public String toString() { 11 | return capitalize(name()); 12 | } 13 | 14 | private String capitalize(String string) { 15 | String lowerCase = string.toLowerCase(); 16 | return lowerCase.substring(0, 1).toUpperCase() + lowerCase.substring(1); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/joinpoint/RxComponentInfo.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.joinpoint; 2 | 3 | public class RxComponentInfo { 4 | private final RxComponent rxComponent; 5 | private final FrodoJoinPoint joinPoint; 6 | 7 | private String subscribeOnThread; 8 | private String observeOnThread; 9 | private long totalExecutionTime; 10 | private int totalEmittedItems; 11 | 12 | public RxComponentInfo(RxComponent rxComponent, FrodoJoinPoint joinPoint) { 13 | this.rxComponent = rxComponent; 14 | this.joinPoint = joinPoint; 15 | } 16 | 17 | public String rxComponentName() { 18 | return rxComponent.toString(); 19 | } 20 | 21 | public String classSimpleName() { 22 | return joinPoint.getClassSimpleName(); 23 | } 24 | 25 | public String methodName() { 26 | return joinPoint.getMethodName(); 27 | } 28 | 29 | public FrodoJoinPoint joinPoint() { 30 | return joinPoint; 31 | } 32 | 33 | public String subscribeOnThread() { 34 | return subscribeOnThread; 35 | } 36 | 37 | public String observeOnThread() { 38 | return observeOnThread; 39 | } 40 | 41 | public long totalExecutionTime() { 42 | return totalExecutionTime; 43 | } 44 | 45 | public int totalEmittedItems() { 46 | return totalEmittedItems; 47 | } 48 | 49 | public void setSubscribeOnThread(String subscribeOnThread) { 50 | this.subscribeOnThread = subscribeOnThread; 51 | } 52 | 53 | public void setObserveOnThread(String observeOnThread) { 54 | this.observeOnThread = observeOnThread; 55 | } 56 | 57 | public void setTotalExecutionTime(long totalExecutionTime) { 58 | this.totalExecutionTime = totalExecutionTime; 59 | } 60 | 61 | public void setTotalEmittedItems(int totalEmittedItems) { 62 | this.totalEmittedItems = totalEmittedItems; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/logging/Counter.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.logging; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public class Counter implements Comparable { 7 | 8 | private final String name; 9 | private final AtomicInteger count; 10 | 11 | public Counter() { 12 | this(Counter.class.getSimpleName()); 13 | } 14 | 15 | public Counter(String name) { 16 | this.name = name; 17 | this.count = new AtomicInteger(0); 18 | } 19 | 20 | public void increment() { 21 | count.incrementAndGet(); 22 | } 23 | 24 | public void decrement() { 25 | count.decrementAndGet(); 26 | } 27 | 28 | public int tally() { 29 | return count.intValue(); 30 | } 31 | 32 | public void clear() { 33 | count.set(0); 34 | } 35 | 36 | @Override 37 | public int compareTo(@NotNull Counter that) { 38 | final int thisValue = count.intValue(); 39 | final int thatValue = that.count.intValue(); 40 | 41 | if (thisValue < thatValue) { return -1; } else if (thisValue > thatValue) { return +1; } else { 42 | return 0; 43 | } 44 | } 45 | 46 | public String toString() { 47 | return getClass().getSimpleName() + " name: " + name + " value: " + count.intValue(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/logging/MessageManager.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.logging; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 4 | import com.fernandocejas.frodo2.logging.Logger; 5 | 6 | public class MessageManager { 7 | 8 | private final MessageBuilder messageBuilder; 9 | private final Logger logger; 10 | 11 | public MessageManager(MessageBuilder messageBuilder, Logger logger) { 12 | this.messageBuilder = messageBuilder; 13 | this.logger = logger; 14 | } 15 | 16 | private void printMessage(String tag, String message) { 17 | logger.log(tag, message); 18 | } 19 | 20 | public void printRxComponentInfo(RxComponentInfo rxComponentInfo) { 21 | final String message = messageBuilder.buildRxComponentInfoMessage(rxComponentInfo); 22 | this.printMessage(rxComponentInfo.classSimpleName(), message); 23 | } 24 | 25 | public void printOnSubscribe(RxComponentInfo rxComponentInfo) { 26 | final String message = messageBuilder.buildOnSubscribeMessage(rxComponentInfo); 27 | this.printMessage(rxComponentInfo.classSimpleName(), message); 28 | } 29 | 30 | public void printOnNextWithValue(RxComponentInfo rxComponentInfo, T value) { 31 | final String message = messageBuilder.buildOnNextWithValueMessage(rxComponentInfo, value); 32 | this.printMessage(rxComponentInfo.classSimpleName(), message); 33 | } 34 | 35 | public void printOnSuccessWithValue(RxComponentInfo rxComponentInfo, T value) { 36 | final String message = messageBuilder.buildOnSuccessWithValueMessage(rxComponentInfo, value); 37 | this.printMessage(rxComponentInfo.classSimpleName(), message); 38 | } 39 | 40 | public void printOnError(RxComponentInfo rxComponentInfo, 41 | Throwable throwable) { 42 | final String message = messageBuilder.buildOnErrorMessage(rxComponentInfo, throwable.getMessage()); 43 | this.printMessage(rxComponentInfo.classSimpleName(), message); 44 | } 45 | 46 | public void printOnComplete(RxComponentInfo rxComponentInfo) { 47 | final String message = messageBuilder.buildOnCompleteMessage(rxComponentInfo); 48 | this.printMessage(rxComponentInfo.classSimpleName(), message); 49 | } 50 | 51 | public void printOnTerminate(RxComponentInfo rxComponentInfo) { 52 | final String message = messageBuilder.buildOnTerminateMessage(rxComponentInfo); 53 | this.printMessage(rxComponentInfo.classSimpleName(), message); 54 | } 55 | 56 | public void printOnDispose(RxComponentInfo rxComponentInfo) { 57 | final String message = messageBuilder.buildOnDisposeMessage(rxComponentInfo); 58 | this.printMessage(rxComponentInfo.classSimpleName(), message); 59 | } 60 | 61 | public void printOnRequestWithCount(RxComponentInfo rxComponentInfo, long count) { 62 | final String message = messageBuilder.buildOnRequestWithCountMessage(rxComponentInfo, count); 63 | this.printMessage(rxComponentInfo.classSimpleName(), message); 64 | } 65 | 66 | public void printOnCancel(RxComponentInfo rxComponentInfo) { 67 | final String message = messageBuilder.buildOnCancelMessage(rxComponentInfo); 68 | this.printMessage(rxComponentInfo.classSimpleName(), message); 69 | } 70 | 71 | public void printItemTimeInfo(RxComponentInfo rxComponentInfo) { 72 | final String message = messageBuilder.buildItemTimeInfoMessage(rxComponentInfo); 73 | this.printMessage(rxComponentInfo.classSimpleName(), message); 74 | } 75 | 76 | public void printThreadInfo(RxComponentInfo rxComponentInfo) { 77 | if (rxComponentInfo.subscribeOnThread() != null || 78 | rxComponentInfo.observeOnThread() != null) { 79 | final String message = messageBuilder.buildThreadInfoMessage(rxComponentInfo); 80 | this.printMessage(rxComponentInfo.classSimpleName(), message); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/logging/StopWatch.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.logging; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * Class representing a StopWatch for measuring time. 7 | */ 8 | public class StopWatch { 9 | private long startTime; 10 | private long endTime; 11 | private long elapsedTime; 12 | 13 | public StopWatch() { 14 | //empty 15 | } 16 | 17 | void reset() { 18 | startTime = 0; 19 | endTime = 0; 20 | elapsedTime = 0; 21 | } 22 | 23 | public void start() { 24 | reset(); 25 | startTime = System.nanoTime(); 26 | } 27 | 28 | public void stop() { 29 | if (startTime != 0) { 30 | endTime = System.nanoTime(); 31 | elapsedTime = endTime - startTime; 32 | } else { 33 | reset(); 34 | } 35 | } 36 | 37 | public long getTotalTimeMillis() { 38 | return (elapsedTime != 0) ? TimeUnit.NANOSECONDS.toMillis(endTime - startTime) : 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/maybe/FrodoForMaybe.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.maybe; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponent; 5 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 6 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 7 | import com.fernandocejas.frodo2.logger.logging.StopWatch; 8 | 9 | import io.reactivex.Maybe; 10 | import io.reactivex.disposables.Disposable; 11 | import io.reactivex.functions.Action; 12 | import io.reactivex.functions.BiConsumer; 13 | import io.reactivex.functions.Consumer; 14 | 15 | @SuppressWarnings({"unchecked", "Convert2Lambda"}) 16 | class FrodoForMaybe { 17 | 18 | private final FrodoProceedingJoinPoint joinPoint; 19 | private final MessageManager messageManager; 20 | private final RxComponentInfo rxComponentInfo; 21 | 22 | FrodoForMaybe(FrodoProceedingJoinPoint joinPoint, MessageManager messageManager) { 23 | this.joinPoint = joinPoint; 24 | this.messageManager = messageManager; 25 | this.rxComponentInfo = new RxComponentInfo(RxComponent.MAYBE, joinPoint); 26 | } 27 | 28 | Maybe maybe() throws Throwable { 29 | messageManager.printRxComponentInfo(rxComponentInfo); 30 | final Class singleType = joinPoint.getGenericReturnTypes().get(0); 31 | return loggableMaybe(singleType); 32 | } 33 | 34 | private Maybe loggableMaybe(T type) throws Throwable { 35 | final StopWatch stopWatch = new StopWatch(); 36 | return ((Maybe) joinPoint.proceed()) 37 | .doOnSubscribe(new Consumer() { 38 | @Override 39 | public void accept(Disposable disposable) throws Exception { 40 | stopWatch.start(); 41 | messageManager.printOnSubscribe(rxComponentInfo); 42 | } 43 | }) 44 | .doOnSuccess(new Consumer() { 45 | @Override 46 | public void accept(T value) throws Exception { 47 | //nothing for now 48 | } 49 | }) 50 | .doOnError(new Consumer() { 51 | @Override 52 | public void accept(Throwable throwable) throws Exception { 53 | //nothing for now 54 | } 55 | }) 56 | .doOnComplete(new Action() { 57 | @Override 58 | public void run() throws Exception { 59 | //nothing for now 60 | } 61 | }) 62 | .doOnEvent(new BiConsumer() { 63 | @Override 64 | public void accept(T value, Throwable throwable) throws Exception { 65 | if (rxComponentInfo.observeOnThread() == null) { 66 | rxComponentInfo.setObserveOnThread(Thread.currentThread().getName()); 67 | } 68 | 69 | if (value != null) { // Success 70 | messageManager.printOnSuccessWithValue(rxComponentInfo, value); 71 | rxComponentInfo.setTotalEmittedItems(1); 72 | } else if (throwable != null) { // Error 73 | messageManager.printOnError(rxComponentInfo, throwable); 74 | } else { // Complete without item 75 | messageManager.printOnComplete(rxComponentInfo); 76 | } 77 | } 78 | }) 79 | .doOnDispose(new Action() { 80 | @Override 81 | public void run() throws Exception { 82 | messageManager.printOnDispose(rxComponentInfo); 83 | } 84 | }) 85 | .doFinally(new Action() { 86 | @Override 87 | public void run() throws Exception { 88 | stopWatch.stop(); 89 | rxComponentInfo.setTotalExecutionTime(stopWatch.getTotalTimeMillis()); 90 | messageManager.printItemTimeInfo(rxComponentInfo); 91 | messageManager.printThreadInfo(rxComponentInfo); 92 | } 93 | }); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/maybe/MaybeWeaver.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.maybe; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.logging.MessageBuilder; 5 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 6 | import com.fernandocejas.frodo2.logging.Logger; 7 | 8 | import org.aspectj.lang.ProceedingJoinPoint; 9 | import org.aspectj.lang.reflect.MethodSignature; 10 | 11 | import io.reactivex.Maybe; 12 | 13 | /** 14 | * Copyright (C) 2017 android10.org Open Source Project 15 | *

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

20 | * http://www.apache.org/licenses/LICENSE-2.0 21 | *

22 | * Unless required by applicable law or agreed to in writing, software 23 | * distributed under the License is distributed on an "AS IS" BASIS, 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25 | * See the License for the specific language governing permissions and 26 | * limitations under the License. 27 | */ 28 | public class MaybeWeaver { 29 | 30 | public static final String POINTCUT = 31 | "execution(@com.fernandocejas.frodo2.annotation.RxLogMaybe * *(..)) && if()"; 32 | public static final String ADVICE = "methodAnnotatedWithRxLogMaybe(joinPoint)"; 33 | 34 | public static boolean methodAnnotatedWithRxLogMaybe(ProceedingJoinPoint joinPoint) { 35 | return ((MethodSignature) joinPoint.getSignature()).getReturnType() == Maybe.class; 36 | } 37 | 38 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint, Logger logger) 39 | throws Throwable { 40 | final FrodoProceedingJoinPoint proceedingJoinPoint = new FrodoProceedingJoinPoint(joinPoint); 41 | final MessageManager messageManager = new MessageManager(new MessageBuilder(), logger); 42 | return new FrodoForMaybe(proceedingJoinPoint, messageManager).maybe(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/observable/FrodoForObservable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.observable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponent; 5 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 6 | import com.fernandocejas.frodo2.logger.logging.Counter; 7 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 8 | import com.fernandocejas.frodo2.logger.logging.StopWatch; 9 | 10 | import io.reactivex.Observable; 11 | import io.reactivex.disposables.Disposable; 12 | import io.reactivex.functions.Action; 13 | import io.reactivex.functions.Consumer; 14 | 15 | @SuppressWarnings({"unchecked", "Convert2Lambda"}) 16 | class FrodoForObservable { 17 | 18 | private final FrodoProceedingJoinPoint joinPoint; 19 | private final MessageManager messageManager; 20 | private final RxComponentInfo rxComponentInfo; 21 | 22 | FrodoForObservable(FrodoProceedingJoinPoint joinPoint, MessageManager messageManager) { 23 | this.joinPoint = joinPoint; 24 | this.messageManager = messageManager; 25 | this.rxComponentInfo = new RxComponentInfo(RxComponent.OBSERVABLE, joinPoint); 26 | } 27 | 28 | Observable observable() throws Throwable { 29 | messageManager.printRxComponentInfo(rxComponentInfo); 30 | final Class observableType = joinPoint.getGenericReturnTypes().get(0); 31 | return loggableObservable(observableType); 32 | } 33 | 34 | private Observable loggableObservable(T type) throws Throwable { 35 | final StopWatch stopWatch = new StopWatch(); 36 | final Counter emittedItems = new Counter(joinPoint.getMethodName()); 37 | return ((Observable) joinPoint.proceed()) 38 | .doOnSubscribe(new Consumer() { 39 | @Override 40 | public void accept(Disposable disposable) throws Exception { 41 | stopWatch.start(); 42 | messageManager.printOnSubscribe(rxComponentInfo); 43 | } 44 | }) 45 | .doOnNext(new Consumer() { 46 | @Override 47 | public void accept(T value) throws Exception { 48 | if (rxComponentInfo.observeOnThread() == null) { 49 | rxComponentInfo.setObserveOnThread(Thread.currentThread().getName()); 50 | } 51 | emittedItems.increment(); 52 | messageManager.printOnNextWithValue(rxComponentInfo, value); 53 | } 54 | }) 55 | .doOnError(new Consumer() { 56 | @Override 57 | public void accept(Throwable throwable) throws Exception { 58 | messageManager.printOnError(rxComponentInfo, throwable); 59 | } 60 | }) 61 | .doOnComplete(new Action() { 62 | @Override 63 | public void run() throws Exception { 64 | messageManager.printOnComplete(rxComponentInfo); 65 | } 66 | }) 67 | .doOnTerminate(new Action() { 68 | @Override 69 | public void run() throws Exception { 70 | messageManager.printOnTerminate(rxComponentInfo); 71 | } 72 | }) 73 | .doOnDispose(new Action() { 74 | @Override 75 | public void run() throws Exception { 76 | messageManager.printOnDispose(rxComponentInfo); 77 | } 78 | }) 79 | .doFinally(new Action() { 80 | @Override 81 | public void run() throws Exception { 82 | stopWatch.stop(); 83 | rxComponentInfo.setTotalExecutionTime(stopWatch.getTotalTimeMillis()); 84 | rxComponentInfo.setTotalEmittedItems(emittedItems.tally()); 85 | messageManager.printItemTimeInfo(rxComponentInfo); 86 | messageManager.printThreadInfo(rxComponentInfo); 87 | } 88 | }); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/observable/ObservableWeaver.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.observable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logging.Logger; 5 | import com.fernandocejas.frodo2.logger.logging.MessageBuilder; 6 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 7 | import io.reactivex.Observable; 8 | import org.aspectj.lang.ProceedingJoinPoint; 9 | import org.aspectj.lang.reflect.MethodSignature; 10 | 11 | /** 12 | * Copyright (C) 2017 android10.org Open Source Project 13 | *

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

18 | * http://www.apache.org/licenses/LICENSE-2.0 19 | *

20 | * Unless required by applicable law or agreed to in writing, software 21 | * distributed under the License is distributed on an "AS IS" BASIS, 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | * See the License for the specific language governing permissions and 24 | * limitations under the License. 25 | */ 26 | public class ObservableWeaver { 27 | 28 | public static final String POINTCUT = 29 | "execution(@com.fernandocejas.frodo2.annotation.RxLogObservable * *(..)) && if()"; 30 | public static final String ADVICE = "methodAnnotatedWithRxLogObservable(joinPoint)"; 31 | 32 | public static boolean methodAnnotatedWithRxLogObservable(ProceedingJoinPoint joinPoint) { 33 | return ((MethodSignature) joinPoint.getSignature()).getReturnType() == Observable.class; 34 | } 35 | 36 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint, Logger logger) 37 | throws Throwable { 38 | final FrodoProceedingJoinPoint proceedingJoinPoint = new FrodoProceedingJoinPoint(joinPoint); 39 | final MessageManager messageManager = new MessageManager(new MessageBuilder(), logger); 40 | return new FrodoForObservable(proceedingJoinPoint, messageManager).observable(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/single/FrodoForSingle.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.single; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponent; 5 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 6 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 7 | import com.fernandocejas.frodo2.logger.logging.StopWatch; 8 | 9 | import io.reactivex.Single; 10 | import io.reactivex.disposables.Disposable; 11 | import io.reactivex.functions.Action; 12 | import io.reactivex.functions.BiConsumer; 13 | import io.reactivex.functions.Consumer; 14 | 15 | @SuppressWarnings({"unchecked", "Convert2Lambda"}) 16 | class FrodoForSingle { 17 | 18 | private final FrodoProceedingJoinPoint joinPoint; 19 | private final MessageManager messageManager; 20 | private final RxComponentInfo rxComponentInfo; 21 | 22 | FrodoForSingle(FrodoProceedingJoinPoint joinPoint, MessageManager messageManager) { 23 | this.joinPoint = joinPoint; 24 | this.messageManager = messageManager; 25 | this.rxComponentInfo = new RxComponentInfo(RxComponent.SINGLE, joinPoint); 26 | } 27 | 28 | Single single() throws Throwable { 29 | messageManager.printRxComponentInfo(rxComponentInfo); 30 | final Class singleType = joinPoint.getGenericReturnTypes().get(0); 31 | return loggableSingle(singleType); 32 | } 33 | 34 | private Single loggableSingle(T type) throws Throwable { 35 | final StopWatch stopWatch = new StopWatch(); 36 | return ((Single) joinPoint.proceed()) 37 | .doOnSubscribe(new Consumer() { 38 | @Override 39 | public void accept(Disposable disposable) throws Exception { 40 | stopWatch.start(); 41 | messageManager.printOnSubscribe(rxComponentInfo); 42 | } 43 | }) 44 | .doOnEvent(new BiConsumer() { 45 | @Override 46 | public void accept(T value, Throwable throwable) throws Exception { 47 | if (rxComponentInfo.observeOnThread() == null) { 48 | rxComponentInfo.setObserveOnThread(Thread.currentThread().getName()); 49 | } 50 | 51 | if (value != null) { // success 52 | messageManager.printOnSuccessWithValue(rxComponentInfo, value); 53 | rxComponentInfo.setTotalEmittedItems(1); 54 | } else { // error 55 | messageManager.printOnError(rxComponentInfo, throwable); 56 | } 57 | } 58 | }) 59 | .doOnDispose(new Action() { 60 | @Override 61 | public void run() throws Exception { 62 | messageManager.printOnDispose(rxComponentInfo); 63 | } 64 | }) 65 | .doFinally(new Action() { 66 | @Override 67 | public void run() throws Exception { 68 | stopWatch.stop(); 69 | rxComponentInfo.setTotalExecutionTime(stopWatch.getTotalTimeMillis()); 70 | messageManager.printItemTimeInfo(rxComponentInfo); 71 | messageManager.printThreadInfo(rxComponentInfo); 72 | } 73 | }); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /frodo2-logger/src/main/java/com/fernandocejas/frodo2/logger/single/SingleWeaver.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.single; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.logging.MessageBuilder; 5 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 6 | import com.fernandocejas.frodo2.logging.Logger; 7 | import io.reactivex.Single; 8 | import org.aspectj.lang.ProceedingJoinPoint; 9 | import org.aspectj.lang.reflect.MethodSignature; 10 | 11 | /** 12 | * Copyright (C) 2017 android10.org Open Source Project 13 | *

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

18 | * http://www.apache.org/licenses/LICENSE-2.0 19 | *

20 | * Unless required by applicable law or agreed to in writing, software 21 | * distributed under the License is distributed on an "AS IS" BASIS, 22 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | * See the License for the specific language governing permissions and 24 | * limitations under the License. 25 | */ 26 | public class SingleWeaver { 27 | 28 | public static final String POINTCUT = 29 | "execution(@com.fernandocejas.frodo2.annotation.RxLogSingle * *(..)) && if()"; 30 | public static final String ADVICE = "methodAnnotatedWithRxLogSingle(joinPoint)"; 31 | 32 | public static boolean methodAnnotatedWithRxLogSingle(ProceedingJoinPoint joinPoint) { 33 | return ((MethodSignature) joinPoint.getSignature()).getReturnType() == Single.class; 34 | } 35 | 36 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint, Logger logger) 37 | throws Throwable { 38 | final FrodoProceedingJoinPoint proceedingJoinPoint = new FrodoProceedingJoinPoint(joinPoint); 39 | final MessageManager messageManager = new MessageManager(new MessageBuilder(), logger); 40 | return new FrodoForSingle(proceedingJoinPoint, messageManager).single(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/completable/CompletableRule.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.completable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponent; 5 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 6 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 7 | import com.fernandocejas.frodo2.test.TestJoinPoint; 8 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 9 | 10 | import org.junit.rules.TestRule; 11 | import org.junit.runner.Description; 12 | import org.junit.runners.model.Statement; 13 | import org.mockito.Mock; 14 | import org.mockito.MockitoAnnotations; 15 | 16 | import io.reactivex.Completable; 17 | 18 | class CompletableRule implements TestRule { 19 | 20 | static final String OBSERVABLE_STREAM_VALUE = "fernando"; 21 | 22 | private final Class declaringType; 23 | 24 | private FrodoProceedingJoinPoint frodoProceedingJoinPoint; 25 | private RxComponentInfo rxComponentInfo; 26 | 27 | @Mock private MessageManager messageManager; 28 | 29 | CompletableRule(Class declaringType) { 30 | MockitoAnnotations.initMocks(this); 31 | this.declaringType = declaringType; 32 | } 33 | 34 | @Override public Statement apply(Statement statement, Description description) { 35 | final TestJoinPoint testJoinPoint = 36 | new TestJoinPoint.Builder(declaringType) 37 | .withReturnType(Completable.class) 38 | .withReturnValue(OBSERVABLE_STREAM_VALUE) 39 | .build(); 40 | 41 | final TestProceedingJoinPoint testProceedingJoinPoint = 42 | new TestProceedingJoinPoint(testJoinPoint); 43 | 44 | frodoProceedingJoinPoint = new FrodoProceedingJoinPoint(testProceedingJoinPoint); 45 | rxComponentInfo = new RxComponentInfo(RxComponent.COMPLETABLE, frodoProceedingJoinPoint); 46 | 47 | return statement; 48 | } 49 | 50 | FrodoProceedingJoinPoint joinPoint() { 51 | return frodoProceedingJoinPoint; 52 | } 53 | 54 | MessageManager messageManager() { 55 | return messageManager; 56 | } 57 | 58 | RxComponentInfo info() { 59 | return rxComponentInfo; 60 | } 61 | 62 | String stringType() { 63 | return ""; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/completable/CompletableWeaverTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.completable; 2 | 3 | import com.fernandocejas.frodo2.logging.Logger; 4 | import com.fernandocejas.frodo2.test.TestJoinPoint; 5 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 6 | import com.fernandocejas.frodo2.test.UnitTest; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Completable; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | import static org.mockito.Mockito.mock; 15 | 16 | public class CompletableWeaverTest extends UnitTest { 17 | 18 | private CompletableWeaver completableWeaver; 19 | 20 | private TestProceedingJoinPoint proceedingJoinPoint; 21 | 22 | @Before 23 | public void setUp() { 24 | completableWeaver = new CompletableWeaver(); 25 | TestJoinPoint testJoinPoint = new TestJoinPoint.Builder(this.getClass()).withReturnType(Completable.class).build(); 26 | proceedingJoinPoint = new TestProceedingJoinPoint(testJoinPoint); 27 | } 28 | 29 | @Test 30 | @SuppressWarnings("AccessStaticViaInstance") 31 | public void shouldGetCorrectReturnType() { 32 | final boolean result = completableWeaver.methodAnnotatedWithRxLogCompletable(proceedingJoinPoint); 33 | assertThat(result).isTrue(); 34 | } 35 | 36 | @Test 37 | public void shouldWeaveAroundJoinPointAndReturnCorrectObject() throws Throwable { 38 | final Object object = completableWeaver.weaveAroundJoinPoint(proceedingJoinPoint, mock(Logger.class)); 39 | assertThat(object).isInstanceOf(Completable.class); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/completable/FrodoForCompletableTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.completable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 4 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 5 | import com.fernandocejas.frodo2.test.UnitTest; 6 | 7 | import org.junit.Before; 8 | import org.junit.Rule; 9 | import org.junit.Test; 10 | import org.mockito.Mock; 11 | 12 | import io.reactivex.observers.TestObserver; 13 | 14 | import static org.mockito.Matchers.any; 15 | import static org.mockito.Mockito.verify; 16 | 17 | @SuppressWarnings("unchecked") 18 | public class FrodoForCompletableTest extends UnitTest { 19 | 20 | @Rule public CompletableRule completableRule = new CompletableRule(this.getClass()); 21 | 22 | private FrodoForCompletable frodoForCompletable; 23 | private TestObserver observer; 24 | 25 | @Mock private MessageManager messageManager; 26 | 27 | @Before 28 | public void setUp() { 29 | frodoForCompletable = new FrodoForCompletable(completableRule.joinPoint(), messageManager); 30 | observer = new TestObserver(); 31 | } 32 | 33 | @Test 34 | public void shouldBuild() throws Throwable { 35 | frodoForCompletable.completable().subscribe(observer); 36 | 37 | observer.assertNoValues(); 38 | observer.assertNoErrors(); 39 | observer.assertComplete(); 40 | } 41 | 42 | @Test 43 | public void shouldPrintInfo() throws Throwable { 44 | frodoForCompletable.completable(); 45 | 46 | verify(messageManager).printRxComponentInfo(any(RxComponentInfo.class)); 47 | } 48 | 49 | @Test 50 | public void shouldLogInformation() throws Throwable { 51 | frodoForCompletable.completable().subscribe(observer); 52 | observer.dispose(); 53 | 54 | verify(messageManager).printRxComponentInfo(any(RxComponentInfo.class)); 55 | verify(messageManager).printOnSubscribe(any(RxComponentInfo.class)); 56 | verify(messageManager).printOnComplete(any(RxComponentInfo.class)); 57 | verify(messageManager).printItemTimeInfo(any(RxComponentInfo.class)); 58 | verify(messageManager).printThreadInfo(any(RxComponentInfo.class)); 59 | verify(messageManager).printOnDispose(any(RxComponentInfo.class)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/flowable/FlowableRule.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.flowable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponent; 5 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 6 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 7 | import com.fernandocejas.frodo2.test.TestJoinPoint; 8 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 9 | 10 | import org.junit.rules.TestRule; 11 | import org.junit.runner.Description; 12 | import org.junit.runners.model.Statement; 13 | import org.mockito.Mock; 14 | import org.mockito.MockitoAnnotations; 15 | 16 | import io.reactivex.Flowable; 17 | 18 | class FlowableRule implements TestRule { 19 | 20 | static final String OBSERVABLE_STREAM_VALUE = "fernando"; 21 | 22 | private final Class declaringType; 23 | 24 | private FrodoProceedingJoinPoint frodoProceedingJoinPoint; 25 | private RxComponentInfo rxComponentInfo; 26 | 27 | @Mock private MessageManager messageManager; 28 | 29 | FlowableRule(Class declaringType) { 30 | MockitoAnnotations.initMocks(this); 31 | this.declaringType = declaringType; 32 | } 33 | 34 | @Override public Statement apply(Statement statement, Description description) { 35 | final TestJoinPoint testJoinPoint = 36 | new TestJoinPoint.Builder(declaringType) 37 | .withReturnType(Flowable.class) 38 | .withReturnValue(OBSERVABLE_STREAM_VALUE) 39 | .build(); 40 | 41 | final TestProceedingJoinPoint testProceedingJoinPoint = 42 | new TestProceedingJoinPoint(testJoinPoint); 43 | 44 | frodoProceedingJoinPoint = new FrodoProceedingJoinPoint(testProceedingJoinPoint); 45 | rxComponentInfo = new RxComponentInfo(RxComponent.FLOWABLE, frodoProceedingJoinPoint); 46 | 47 | return statement; 48 | } 49 | 50 | FrodoProceedingJoinPoint joinPoint() { 51 | return frodoProceedingJoinPoint; 52 | } 53 | 54 | MessageManager messageManager() { 55 | return messageManager; 56 | } 57 | 58 | RxComponentInfo info() { 59 | return rxComponentInfo; 60 | } 61 | 62 | String stringType() { 63 | return ""; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/flowable/FlowableWeaverTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.flowable; 2 | 3 | import com.fernandocejas.frodo2.logging.Logger; 4 | import com.fernandocejas.frodo2.test.TestJoinPoint; 5 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 6 | import com.fernandocejas.frodo2.test.UnitTest; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Flowable; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | import static org.mockito.Mockito.mock; 15 | 16 | public class FlowableWeaverTest extends UnitTest { 17 | 18 | private FlowableWeaver flowableWeaver; 19 | 20 | private TestProceedingJoinPoint proceedingJoinPoint; 21 | 22 | @Before 23 | public void setUp() { 24 | flowableWeaver = new FlowableWeaver(); 25 | TestJoinPoint testJoinPoint = new TestJoinPoint.Builder(this.getClass()).withReturnType(Flowable.class).build(); 26 | proceedingJoinPoint = new TestProceedingJoinPoint(testJoinPoint); 27 | } 28 | 29 | @Test 30 | @SuppressWarnings("AccessStaticViaInstance") 31 | public void shouldGetCorrectReturnType() { 32 | final boolean result = flowableWeaver.methodAnnotatedWithRxLogFlowable(proceedingJoinPoint); 33 | assertThat(result).isTrue(); 34 | } 35 | 36 | @Test 37 | public void shouldWeaveAroundJoinPointAndReturnCorrectObject() throws Throwable { 38 | final Object object = flowableWeaver.weaveAroundJoinPoint(proceedingJoinPoint, mock(Logger.class)); 39 | assertThat(object).isInstanceOf(Flowable.class); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/flowable/FrodoForFlowableTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.flowable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 4 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 5 | import com.fernandocejas.frodo2.test.UnitTest; 6 | 7 | import org.junit.Before; 8 | import org.junit.Rule; 9 | import org.junit.Test; 10 | import org.mockito.Mock; 11 | 12 | import io.reactivex.subscribers.TestSubscriber; 13 | 14 | import static org.mockito.Matchers.any; 15 | import static org.mockito.Mockito.verify; 16 | 17 | @SuppressWarnings("unchecked") 18 | public class FrodoForFlowableTest extends UnitTest { 19 | 20 | @Rule public FlowableRule flowableRule = new FlowableRule(this.getClass()); 21 | 22 | private FrodoForFlowable frodoFlowable; 23 | private TestSubscriber subscriber; 24 | 25 | @Mock private MessageManager messageManager; 26 | 27 | @Before 28 | public void setUp() { 29 | frodoFlowable = new FrodoForFlowable(flowableRule.joinPoint(), messageManager); 30 | subscriber = new TestSubscriber(); 31 | } 32 | 33 | @Test 34 | public void shouldBuild() throws Throwable { 35 | frodoFlowable.flowable().subscribe(subscriber); 36 | 37 | subscriber.assertValue(FlowableRule.OBSERVABLE_STREAM_VALUE); 38 | subscriber.assertNoErrors(); 39 | subscriber.assertComplete(); 40 | } 41 | 42 | @Test 43 | public void shouldPrintInfo() throws Throwable { 44 | frodoFlowable.flowable(); 45 | 46 | verify(messageManager).printRxComponentInfo(any(RxComponentInfo.class)); 47 | } 48 | 49 | @Test 50 | public void shouldLogInformation() throws Throwable { 51 | frodoFlowable.flowable().subscribe(subscriber); 52 | subscriber.dispose(); 53 | 54 | verify(messageManager).printRxComponentInfo(any(RxComponentInfo.class)); 55 | verify(messageManager).printOnSubscribe(any(RxComponentInfo.class)); 56 | verify(messageManager).printOnNextWithValue(any(RxComponentInfo.class), any()); 57 | verify(messageManager).printOnComplete(any(RxComponentInfo.class)); 58 | verify(messageManager).printOnTerminate(any(RxComponentInfo.class)); 59 | verify(messageManager).printItemTimeInfo(any(RxComponentInfo.class)); 60 | verify(messageManager).printThreadInfo(any(RxComponentInfo.class)); 61 | verify(messageManager).printOnCancel(any(RxComponentInfo.class)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/joinpoint/FrodoJoinPointTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.joinpoint; 2 | 3 | import com.fernandocejas.frodo2.test.TestJoinPoint; 4 | import com.fernandocejas.frodo2.test.UnitTest; 5 | import io.reactivex.Observable; 6 | import java.util.Arrays; 7 | import java.util.Collections; 8 | import java.util.List; 9 | import org.junit.Test; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | public class FrodoJoinPointTest extends UnitTest { 14 | 15 | @Test 16 | public void shouldReturnCorrectParametersList() { 17 | final Class[] paramTypes = { String.class, String.class }; 18 | final String[] paramNames = { "paramOne", "paramTwo" }; 19 | final Object[] paramValues = { "ValueOne", "ValueTwo" }; 20 | 21 | final TestJoinPoint testJoinPoint = new TestJoinPoint.Builder(this.getClass()) 22 | .withParamTypes(paramTypes) 23 | .withParamNames(paramNames) 24 | .withParamValues(paramValues) 25 | .build(); 26 | final FrodoJoinPoint frodoJoinPoint = new FrodoJoinPoint(testJoinPoint); 27 | 28 | final List paramTypeList = frodoJoinPoint.getMethodParamTypesList(); 29 | final List paramNamesList = frodoJoinPoint.getMethodParamNamesList(); 30 | final List paramValuesList = frodoJoinPoint.getMethodParamValuesList(); 31 | 32 | assertThat(paramTypeList).isEqualTo(Arrays.asList(paramTypes)); 33 | assertThat(paramNamesList).isEqualTo(Arrays.asList(paramNames)); 34 | assertThat(paramValuesList).isEqualTo(Arrays.asList(paramValues)); 35 | } 36 | 37 | @Test 38 | public void shouldHaveReturnType() { 39 | final TestJoinPoint testJoinPoint = new TestJoinPoint.Builder(this.getClass()) 40 | .withReturnType(Observable.class) 41 | .build(); 42 | final FrodoJoinPoint frodoJoinPoint = new FrodoJoinPoint(testJoinPoint); 43 | 44 | assertThat(frodoJoinPoint.hasReturnType(testJoinPoint)).isTrue(); 45 | assertThat(frodoJoinPoint.getReturnType()).isEqualTo(Observable.class); 46 | } 47 | 48 | @Test 49 | public void shouldNotHaveReturnType() { 50 | final TestJoinPoint testJoinPoint = new TestJoinPoint.Builder(this.getClass()) 51 | .withReturnType(void.class) 52 | .build(); 53 | final FrodoJoinPoint frodoJoinPoint = new FrodoJoinPoint(testJoinPoint); 54 | 55 | assertThat(frodoJoinPoint.hasReturnType(testJoinPoint)).isFalse(); 56 | assertThat(frodoJoinPoint.getReturnType()).isEqualTo(void.class); 57 | } 58 | 59 | @Test 60 | public void shouldReturnCorrectGenericReturnType() { 61 | final TestJoinPoint testJoinPoint = 62 | new TestJoinPoint.Builder(MyDummyClass.class, "buildDummyObservable") 63 | .withReturnType(Observable.class) 64 | .build(); 65 | final FrodoJoinPoint frodoJoinPoint = new FrodoJoinPoint(testJoinPoint); 66 | 67 | assertThat(frodoJoinPoint.getGenericReturnTypes()).isEqualTo( 68 | Collections.singletonList(Observable.class)); 69 | } 70 | 71 | @Test 72 | public void shouldReturnCorrectGenericParameterizedReturnType() { 73 | final TestJoinPoint testJoinPoint = new TestJoinPoint.Builder(MyDummyClass.class, "toString") 74 | .withReturnType(Observable.class) 75 | .build(); 76 | final FrodoJoinPoint frodoJoinPoint = new FrodoJoinPoint(testJoinPoint); 77 | 78 | assertThat(frodoJoinPoint.getGenericReturnTypes()).isEqualTo( 79 | Collections.singletonList(String.class)); 80 | } 81 | 82 | @Test 83 | public void mustGenerateJoinPointUniqueNameForEqualityComparison() { 84 | final Class[] paramTypes = { String.class, String.class }; 85 | final String[] paramNames = { "paramOne", "paramTwo" }; 86 | final Object[] paramValues = { "ValueOne", "ValueTwo" }; 87 | 88 | final TestJoinPoint testJoinPointOne = new TestJoinPoint.Builder(this.getClass()) 89 | .withParamTypes(paramTypes) 90 | .withParamNames(paramNames) 91 | .withParamValues(paramValues) 92 | .build(); 93 | 94 | final TestJoinPoint testJoinPointTwo = new TestJoinPoint.Builder(this.getClass()).build(); 95 | 96 | final FrodoJoinPoint frodoJoinPointOne = new FrodoJoinPoint(testJoinPointOne); 97 | final FrodoJoinPoint frodoJoinPointTwo = new FrodoJoinPoint(testJoinPointTwo); 98 | 99 | assertThat(frodoJoinPointOne).isNotEqualTo(frodoJoinPointTwo); 100 | assertThat(frodoJoinPointOne.hashCode()).isNotEqualTo(frodoJoinPointTwo.hashCode()); 101 | } 102 | 103 | private static class MyDummyClass { 104 | MyDummyClass() {} 105 | 106 | public Observable buildDummyObservable() { 107 | return Observable.empty(); 108 | } 109 | 110 | @Override public String toString() { 111 | return this.getClass().getSimpleName(); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/joinpoint/FrodoProceedingJoinPointTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.joinpoint; 2 | 3 | import com.fernandocejas.frodo2.test.TestJoinPoint; 4 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 5 | import java.util.Observable; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | public class FrodoProceedingJoinPointTest { 10 | 11 | private FrodoProceedingJoinPoint frodoJoinPoint; 12 | 13 | private TestJoinPoint joinPoint; 14 | private TestProceedingJoinPoint proceedingJoinPoint; 15 | 16 | @Before 17 | public void setUp() throws Exception { 18 | joinPoint = new TestJoinPoint.Builder(this.getClass()).withReturnType(Observable.class).build(); 19 | proceedingJoinPoint = new TestProceedingJoinPoint(joinPoint); 20 | frodoJoinPoint = new FrodoProceedingJoinPoint(proceedingJoinPoint); 21 | } 22 | 23 | @Test 24 | public void shouldDelegateProceedMethod() throws Throwable { 25 | frodoJoinPoint.proceed(); 26 | 27 | proceedingJoinPoint.assertProceedMethodCalled(); 28 | } 29 | 30 | @Test 31 | public void shouldDelegateProceedMethodWithArgs() throws Throwable { 32 | Object[] args = new Object[] { 1, 2, 3 }; 33 | 34 | frodoJoinPoint.proceed(args); 35 | 36 | proceedingJoinPoint.assertProceedMethodCalledWithArgs(args); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/joinpoint/RxComponentInfoTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.joinpoint; 2 | 3 | import com.fernandocejas.frodo2.test.UnitTest; 4 | 5 | import org.junit.Test; 6 | import org.mockito.Mock; 7 | 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | 10 | public class RxComponentInfoTest extends UnitTest { 11 | private RxComponentInfo rxComponentInfo; 12 | 13 | @Mock 14 | private FrodoJoinPoint frodoJoinPoint; 15 | 16 | @Test 17 | public void shouldReturnFlowableStringLiteral() { 18 | rxComponentInfo = new RxComponentInfo(RxComponent.FLOWABLE, frodoJoinPoint); 19 | assertThat(rxComponentInfo.rxComponentName()).isEqualTo("Flowable"); 20 | } 21 | 22 | @Test 23 | public void shouldReturnObservableStringLiteral() { 24 | rxComponentInfo = new RxComponentInfo(RxComponent.OBSERVABLE, frodoJoinPoint); 25 | assertThat(rxComponentInfo.rxComponentName()).isEqualTo("Observable"); 26 | } 27 | 28 | @Test 29 | public void shouldReturnSingleStringLiteral() { 30 | rxComponentInfo = new RxComponentInfo(RxComponent.SINGLE, frodoJoinPoint); 31 | assertThat(rxComponentInfo.rxComponentName()).isEqualTo("Single"); 32 | } 33 | 34 | @Test 35 | public void shouldReturnMaybeStringLiteral() { 36 | rxComponentInfo = new RxComponentInfo(RxComponent.MAYBE, frodoJoinPoint); 37 | assertThat(rxComponentInfo.rxComponentName()).isEqualTo("Maybe"); 38 | } 39 | 40 | @Test 41 | public void shouldReturnCompletableStringLiteral() { 42 | rxComponentInfo = new RxComponentInfo(RxComponent.COMPLETABLE, frodoJoinPoint); 43 | assertThat(rxComponentInfo.rxComponentName()).isEqualTo("Completable"); 44 | } 45 | } -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/joinpoint/RxComponentTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.joinpoint; 2 | 3 | import com.fernandocejas.frodo2.test.UnitTest; 4 | import org.junit.Test; 5 | 6 | import static org.assertj.core.api.Assertions.assertThat; 7 | 8 | public class RxComponentTest extends UnitTest { 9 | private static final int NUMBER_RX_COMPONENTS_SUPPORTED = 5; 10 | 11 | @Test 12 | public void shouldReturnNumberRxComponentsSupported() { 13 | assertThat(RxComponent.values().length).isEqualTo(NUMBER_RX_COMPONENTS_SUPPORTED); 14 | } 15 | 16 | @Test 17 | public void shouldReturnFlowableStringLiteral() { 18 | final String flowableName = RxComponent.FLOWABLE.toString(); 19 | assertThat(flowableName).isEqualTo("Flowable"); 20 | } 21 | 22 | @Test 23 | public void shouldReturnObservableStringLiteral() { 24 | final String observableName = RxComponent.OBSERVABLE.toString(); 25 | assertThat(observableName).isEqualTo("Observable"); 26 | } 27 | 28 | @Test 29 | public void shouldReturnSingleStringLiteral() { 30 | final String singleName = RxComponent.SINGLE.toString(); 31 | assertThat(singleName).isEqualTo("Single"); 32 | } 33 | 34 | @Test 35 | public void shouldReturnMaybeStringLiteral() { 36 | final String singleName = RxComponent.MAYBE.toString(); 37 | assertThat(singleName).isEqualTo("Maybe"); 38 | } 39 | 40 | @Test 41 | public void shouldReturnCompletableStringLiteral() { 42 | final String singleName = RxComponent.COMPLETABLE.toString(); 43 | assertThat(singleName).isEqualTo("Completable"); 44 | } 45 | } -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/logging/CounterTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.logging; 2 | 3 | import com.fernandocejas.frodo2.test.UnitTest; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | public class CounterTest extends UnitTest { 10 | 11 | private static final String COUNTER_NAME = "android10"; 12 | 13 | private Counter counter; 14 | 15 | @Before 16 | public void setUp() { 17 | counter = new Counter(COUNTER_NAME); 18 | } 19 | 20 | @Test 21 | public void incrementsCounter() { 22 | counter.increment(); 23 | counter.increment(); 24 | counter.increment(); 25 | 26 | assertThat(counter.tally()).isEqualTo(3); 27 | } 28 | 29 | @Test 30 | public void clearsCounter() { 31 | counter.increment(); 32 | counter.increment(); 33 | assertThat(counter.tally()).isEqualTo(2); 34 | 35 | counter.clear(); 36 | assertThat(counter.tally()).isZero(); 37 | } 38 | 39 | @Test 40 | public void decrementsCounter() { 41 | counter.increment(); 42 | counter.increment(); 43 | counter.increment(); 44 | counter.decrement(); 45 | counter.decrement(); 46 | 47 | assertThat(counter.tally()).isEqualTo(1); 48 | } 49 | 50 | @Test 51 | public void comparesCounterValues() { 52 | final Counter anotherCounter = new Counter("myCounter"); 53 | 54 | counter.increment(); 55 | counter.increment(); 56 | assertThat(counter.compareTo(anotherCounter)).isEqualTo(1); 57 | 58 | anotherCounter.increment(); 59 | anotherCounter.increment(); 60 | assertThat(counter.compareTo(anotherCounter)).isZero(); 61 | 62 | counter.decrement(); 63 | assertThat(counter.compareTo(anotherCounter)).isEqualTo(-1); 64 | } 65 | 66 | @Test 67 | public void countsNegatives() { 68 | counter.decrement(); 69 | counter.decrement(); 70 | 71 | assertThat(counter.tally()).isEqualTo(-2); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/logging/StopWatchTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.logging; 2 | 3 | import com.fernandocejas.frodo2.test.UnitTest; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import static org.assertj.core.api.Assertions.assertThat; 8 | 9 | public class StopWatchTest extends UnitTest { 10 | 11 | private StopWatch stopWatch; 12 | 13 | @Before 14 | public void setUp() { 15 | stopWatch = new StopWatch(); 16 | } 17 | 18 | @Test 19 | public void mustResetStopWatch() { 20 | stopWatch.reset(); 21 | 22 | assertThat(stopWatch.getTotalTimeMillis()).isZero(); 23 | } 24 | 25 | @Test 26 | public void mustStartStopWatch() throws InterruptedException { 27 | stopWatch.start(); 28 | Thread.sleep(10); 29 | stopWatch.stop(); 30 | 31 | assertThat(stopWatch.getTotalTimeMillis()).isGreaterThan(0L); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/maybe/FrodoForMaybeTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.maybe; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 4 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 5 | import com.fernandocejas.frodo2.test.UnitTest; 6 | 7 | import org.junit.Before; 8 | import org.junit.Rule; 9 | import org.junit.Test; 10 | import org.mockito.Mock; 11 | 12 | import io.reactivex.observers.TestObserver; 13 | 14 | import static org.mockito.Matchers.any; 15 | import static org.mockito.Mockito.verify; 16 | 17 | @SuppressWarnings("unchecked") 18 | public class FrodoForMaybeTest extends UnitTest { 19 | 20 | @Rule public MaybeRule maybeRule = new MaybeRule(this.getClass()); 21 | 22 | private FrodoForMaybe frodoForMaybe; 23 | private TestObserver observer; 24 | 25 | @Mock private MessageManager messageManager; 26 | 27 | @Before 28 | public void setUp() { 29 | frodoForMaybe = new FrodoForMaybe(maybeRule.joinPoint(), messageManager); 30 | observer = new TestObserver(); 31 | } 32 | 33 | @Test 34 | public void shouldBuild() throws Throwable { 35 | frodoForMaybe.maybe().subscribe(observer); 36 | 37 | observer.assertResult(MaybeRule.OBSERVABLE_STREAM_VALUE); 38 | observer.assertNoErrors(); 39 | observer.assertComplete(); 40 | } 41 | 42 | @Test 43 | public void shouldPrintInfo() throws Throwable { 44 | frodoForMaybe.maybe(); 45 | 46 | verify(messageManager).printRxComponentInfo(any(RxComponentInfo.class)); 47 | } 48 | 49 | @Test 50 | public void shouldLogInformation() throws Throwable { 51 | frodoForMaybe.maybe().subscribe(observer); 52 | observer.dispose(); 53 | 54 | verify(messageManager).printRxComponentInfo(any(RxComponentInfo.class)); 55 | verify(messageManager).printOnSubscribe(any(RxComponentInfo.class)); 56 | verify(messageManager).printOnSuccessWithValue(any(RxComponentInfo.class), any()); 57 | verify(messageManager).printItemTimeInfo(any(RxComponentInfo.class)); 58 | verify(messageManager).printThreadInfo(any(RxComponentInfo.class)); 59 | verify(messageManager).printOnDispose(any(RxComponentInfo.class)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/maybe/MaybeRule.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.maybe; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponent; 5 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 6 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 7 | import com.fernandocejas.frodo2.test.TestJoinPoint; 8 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 9 | 10 | import org.junit.rules.TestRule; 11 | import org.junit.runner.Description; 12 | import org.junit.runners.model.Statement; 13 | import org.mockito.Mock; 14 | import org.mockito.MockitoAnnotations; 15 | 16 | import io.reactivex.Maybe; 17 | 18 | class MaybeRule implements TestRule { 19 | 20 | static final String OBSERVABLE_STREAM_VALUE = "fernando"; 21 | 22 | private final Class declaringType; 23 | 24 | private FrodoProceedingJoinPoint frodoProceedingJoinPoint; 25 | private RxComponentInfo rxComponentInfo; 26 | 27 | @Mock private MessageManager messageManager; 28 | 29 | MaybeRule(Class declaringType) { 30 | MockitoAnnotations.initMocks(this); 31 | this.declaringType = declaringType; 32 | } 33 | 34 | @Override public Statement apply(Statement statement, Description description) { 35 | final TestJoinPoint testJoinPoint = 36 | new TestJoinPoint.Builder(declaringType) 37 | .withReturnType(Maybe.class) 38 | .withReturnValue(OBSERVABLE_STREAM_VALUE) 39 | .build(); 40 | 41 | final TestProceedingJoinPoint testProceedingJoinPoint = 42 | new TestProceedingJoinPoint(testJoinPoint); 43 | 44 | frodoProceedingJoinPoint = new FrodoProceedingJoinPoint(testProceedingJoinPoint); 45 | rxComponentInfo = new RxComponentInfo(RxComponent.MAYBE, frodoProceedingJoinPoint); 46 | 47 | return statement; 48 | } 49 | 50 | FrodoProceedingJoinPoint joinPoint() { 51 | return frodoProceedingJoinPoint; 52 | } 53 | 54 | MessageManager messageManager() { 55 | return messageManager; 56 | } 57 | 58 | RxComponentInfo info() { 59 | return rxComponentInfo; 60 | } 61 | 62 | String stringType() { 63 | return ""; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/maybe/MaybeWeaverTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.maybe; 2 | 3 | import com.fernandocejas.frodo2.logging.Logger; 4 | import com.fernandocejas.frodo2.test.TestJoinPoint; 5 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 6 | import com.fernandocejas.frodo2.test.UnitTest; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Maybe; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | import static org.mockito.Mockito.mock; 15 | 16 | public class MaybeWeaverTest extends UnitTest { 17 | 18 | private MaybeWeaver maybeWeaver; 19 | 20 | private TestProceedingJoinPoint proceedingJoinPoint; 21 | 22 | @Before 23 | public void setUp() { 24 | maybeWeaver = new MaybeWeaver(); 25 | TestJoinPoint testJoinPoint = 26 | new TestJoinPoint.Builder(this.getClass()).withReturnType(Maybe.class).build(); 27 | proceedingJoinPoint = new TestProceedingJoinPoint(testJoinPoint); 28 | } 29 | 30 | @Test 31 | @SuppressWarnings("AccessStaticViaInstance") 32 | public void shouldGetCorrectReturnType() { 33 | final boolean result = maybeWeaver.methodAnnotatedWithRxLogMaybe(proceedingJoinPoint); 34 | assertThat(result).isTrue(); 35 | } 36 | 37 | @Test 38 | public void shouldWeaveAroundJoinPointAndReturnCorrectObject() throws Throwable { 39 | final Object object = maybeWeaver.weaveAroundJoinPoint(proceedingJoinPoint, mock(Logger.class)); 40 | assertThat(object).isInstanceOf(Maybe.class); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/observable/FrodoForObservableTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.observable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 4 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 5 | import com.fernandocejas.frodo2.test.UnitTest; 6 | 7 | import org.junit.Before; 8 | import org.junit.Rule; 9 | import org.junit.Test; 10 | import org.mockito.Mock; 11 | 12 | import io.reactivex.observers.TestObserver; 13 | 14 | import static org.mockito.Matchers.any; 15 | import static org.mockito.Mockito.verify; 16 | 17 | @SuppressWarnings("unchecked") 18 | public class FrodoForObservableTest extends UnitTest { 19 | 20 | @Rule public ObservableRule observableRule = new ObservableRule(this.getClass()); 21 | 22 | private FrodoForObservable frodoObservable; 23 | private TestObserver observer; 24 | 25 | @Mock private MessageManager messageManager; 26 | 27 | @Before 28 | public void setUp() { 29 | frodoObservable = new FrodoForObservable(observableRule.joinPoint(), messageManager); 30 | observer = new TestObserver(); 31 | } 32 | 33 | @Test 34 | public void shouldBuild() throws Throwable { 35 | frodoObservable.observable().subscribe(observer); 36 | 37 | observer.assertResult(ObservableRule.OBSERVABLE_STREAM_VALUE); 38 | observer.assertNoErrors(); 39 | observer.assertComplete(); 40 | } 41 | 42 | @Test 43 | public void shouldPrintInfo() throws Throwable { 44 | frodoObservable.observable(); 45 | 46 | verify(messageManager).printRxComponentInfo(any(RxComponentInfo.class)); 47 | } 48 | 49 | @Test 50 | public void shouldLogInformation() throws Throwable { 51 | frodoObservable.observable().subscribe(observer); 52 | observer.dispose(); 53 | 54 | verify(messageManager).printRxComponentInfo(any(RxComponentInfo.class)); 55 | verify(messageManager).printOnSubscribe(any(RxComponentInfo.class)); 56 | verify(messageManager).printOnNextWithValue(any(RxComponentInfo.class), any()); 57 | verify(messageManager).printOnComplete(any(RxComponentInfo.class)); 58 | verify(messageManager).printOnTerminate(any(RxComponentInfo.class)); 59 | verify(messageManager).printItemTimeInfo(any(RxComponentInfo.class)); 60 | verify(messageManager).printThreadInfo(any(RxComponentInfo.class)); 61 | verify(messageManager).printOnDispose(any(RxComponentInfo.class)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/observable/ObservableRule.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.observable; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponent; 5 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 6 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 7 | import com.fernandocejas.frodo2.test.TestJoinPoint; 8 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 9 | import io.reactivex.Observable; 10 | import org.junit.rules.TestRule; 11 | import org.junit.runner.Description; 12 | import org.junit.runners.model.Statement; 13 | import org.mockito.Mock; 14 | import org.mockito.MockitoAnnotations; 15 | 16 | class ObservableRule implements TestRule { 17 | 18 | static final String OBSERVABLE_STREAM_VALUE = "fernando"; 19 | 20 | private final Class declaringType; 21 | 22 | private FrodoProceedingJoinPoint frodoProceedingJoinPoint; 23 | private RxComponentInfo rxComponentInfo; 24 | 25 | @Mock private MessageManager messageManager; 26 | 27 | ObservableRule(Class declaringType) { 28 | MockitoAnnotations.initMocks(this); 29 | this.declaringType = declaringType; 30 | } 31 | 32 | @Override public Statement apply(Statement statement, Description description) { 33 | final TestJoinPoint testJoinPoint = 34 | new TestJoinPoint.Builder(declaringType) 35 | .withReturnType(Observable.class) 36 | .withReturnValue(OBSERVABLE_STREAM_VALUE) 37 | .build(); 38 | 39 | final TestProceedingJoinPoint testProceedingJoinPoint = 40 | new TestProceedingJoinPoint(testJoinPoint); 41 | 42 | frodoProceedingJoinPoint = new FrodoProceedingJoinPoint(testProceedingJoinPoint); 43 | rxComponentInfo = new RxComponentInfo(RxComponent.OBSERVABLE, frodoProceedingJoinPoint); 44 | 45 | return statement; 46 | } 47 | 48 | FrodoProceedingJoinPoint joinPoint() { 49 | return frodoProceedingJoinPoint; 50 | } 51 | 52 | MessageManager messageManager() { 53 | return messageManager; 54 | } 55 | 56 | RxComponentInfo info() { 57 | return rxComponentInfo; 58 | } 59 | 60 | String stringType() { 61 | return ""; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/observable/ObservableWeaverTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.observable; 2 | 3 | import com.fernandocejas.frodo2.logging.Logger; 4 | import com.fernandocejas.frodo2.test.TestJoinPoint; 5 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 6 | import com.fernandocejas.frodo2.test.UnitTest; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Observable; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | import static org.mockito.Mockito.mock; 15 | 16 | public class ObservableWeaverTest extends UnitTest { 17 | 18 | private ObservableWeaver observableWeaver; 19 | 20 | private TestProceedingJoinPoint proceedingJoinPoint; 21 | 22 | @Before 23 | public void setUp() { 24 | observableWeaver = new ObservableWeaver(); 25 | TestJoinPoint testJoinPoint = new TestJoinPoint.Builder(this.getClass()).withReturnType(Observable.class).build(); 26 | proceedingJoinPoint = new TestProceedingJoinPoint(testJoinPoint); 27 | } 28 | 29 | @Test 30 | @SuppressWarnings("AccessStaticViaInstance") 31 | public void shouldGetCorrectReturnType() { 32 | final boolean result = observableWeaver.methodAnnotatedWithRxLogObservable(proceedingJoinPoint); 33 | assertThat(result).isTrue(); 34 | } 35 | 36 | @Test 37 | public void shouldWeaveAroundJoinPointAndReturnCorrectObject() throws Throwable { 38 | final Object object = observableWeaver.weaveAroundJoinPoint(proceedingJoinPoint, mock(Logger.class)); 39 | assertThat(object).isInstanceOf(Observable.class); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/single/FrodoForSingleTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.single; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 4 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 5 | import com.fernandocejas.frodo2.test.UnitTest; 6 | 7 | import org.junit.Before; 8 | import org.junit.Rule; 9 | import org.junit.Test; 10 | import org.mockito.Mock; 11 | 12 | import io.reactivex.observers.TestObserver; 13 | 14 | import static org.mockito.Matchers.any; 15 | import static org.mockito.Mockito.verify; 16 | 17 | @SuppressWarnings("unchecked") 18 | public class FrodoForSingleTest extends UnitTest { 19 | 20 | @Rule public SingleRule singleRule = new SingleRule(this.getClass()); 21 | 22 | private FrodoForSingle frodoForSingle; 23 | private TestObserver observer; 24 | 25 | @Mock private MessageManager messageManager; 26 | 27 | @Before 28 | public void setUp() { 29 | frodoForSingle = new FrodoForSingle(singleRule.joinPoint(), messageManager); 30 | observer = new TestObserver(); 31 | } 32 | 33 | @Test 34 | public void shouldBuild() throws Throwable { 35 | frodoForSingle.single().subscribe(observer); 36 | 37 | observer.assertValue(SingleRule.OBSERVABLE_STREAM_VALUE); 38 | observer.assertNoErrors(); 39 | observer.assertComplete(); 40 | } 41 | 42 | @Test 43 | public void shouldPrintInfo() throws Throwable { 44 | frodoForSingle.single(); 45 | 46 | verify(messageManager).printRxComponentInfo(any(RxComponentInfo.class)); 47 | } 48 | 49 | @Test 50 | public void shouldLogInformation() throws Throwable { 51 | frodoForSingle.single().subscribe(observer); 52 | observer.dispose(); 53 | 54 | verify(messageManager).printRxComponentInfo(any(RxComponentInfo.class)); 55 | verify(messageManager).printOnSubscribe(any(RxComponentInfo.class)); 56 | verify(messageManager).printOnSuccessWithValue(any(RxComponentInfo.class), any()); 57 | verify(messageManager).printItemTimeInfo(any(RxComponentInfo.class)); 58 | verify(messageManager).printThreadInfo(any(RxComponentInfo.class)); 59 | verify(messageManager).printOnDispose(any(RxComponentInfo.class)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/single/SingleRule.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.single; 2 | 3 | import com.fernandocejas.frodo2.logger.joinpoint.FrodoProceedingJoinPoint; 4 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponent; 5 | import com.fernandocejas.frodo2.logger.joinpoint.RxComponentInfo; 6 | import com.fernandocejas.frodo2.logger.logging.MessageManager; 7 | import com.fernandocejas.frodo2.test.TestJoinPoint; 8 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 9 | 10 | import org.junit.rules.TestRule; 11 | import org.junit.runner.Description; 12 | import org.junit.runners.model.Statement; 13 | import org.mockito.Mock; 14 | import org.mockito.MockitoAnnotations; 15 | 16 | import io.reactivex.Single; 17 | 18 | class SingleRule implements TestRule { 19 | 20 | static final String OBSERVABLE_STREAM_VALUE = "fernando"; 21 | 22 | private final Class declaringType; 23 | 24 | private FrodoProceedingJoinPoint frodoProceedingJoinPoint; 25 | private RxComponentInfo rxComponentInfo; 26 | 27 | @Mock private MessageManager messageManager; 28 | 29 | SingleRule(Class declaringType) { 30 | MockitoAnnotations.initMocks(this); 31 | this.declaringType = declaringType; 32 | } 33 | 34 | @Override public Statement apply(Statement statement, Description description) { 35 | final TestJoinPoint testJoinPoint = 36 | new TestJoinPoint.Builder(declaringType) 37 | .withReturnType(Single.class) 38 | .withReturnValue(OBSERVABLE_STREAM_VALUE) 39 | .build(); 40 | 41 | final TestProceedingJoinPoint testProceedingJoinPoint = 42 | new TestProceedingJoinPoint(testJoinPoint); 43 | 44 | frodoProceedingJoinPoint = new FrodoProceedingJoinPoint(testProceedingJoinPoint); 45 | rxComponentInfo = new RxComponentInfo(RxComponent.SINGLE, frodoProceedingJoinPoint); 46 | 47 | return statement; 48 | } 49 | 50 | FrodoProceedingJoinPoint joinPoint() { 51 | return frodoProceedingJoinPoint; 52 | } 53 | 54 | MessageManager messageManager() { 55 | return messageManager; 56 | } 57 | 58 | RxComponentInfo info() { 59 | return rxComponentInfo; 60 | } 61 | 62 | String stringType() { 63 | return ""; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/logger/single/SingleWeaverTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.logger.single; 2 | 3 | import com.fernandocejas.frodo2.logging.Logger; 4 | import com.fernandocejas.frodo2.test.TestJoinPoint; 5 | import com.fernandocejas.frodo2.test.TestProceedingJoinPoint; 6 | import com.fernandocejas.frodo2.test.UnitTest; 7 | 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Single; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | import static org.mockito.Mockito.mock; 15 | 16 | public class SingleWeaverTest extends UnitTest { 17 | 18 | private SingleWeaver singleWeaver; 19 | 20 | private TestProceedingJoinPoint proceedingJoinPoint; 21 | 22 | @Before 23 | public void setUp() { 24 | singleWeaver = new SingleWeaver(); 25 | TestJoinPoint testJoinPoint = new TestJoinPoint.Builder(this.getClass()).withReturnType(Single.class).build(); 26 | proceedingJoinPoint = new TestProceedingJoinPoint(testJoinPoint); 27 | } 28 | 29 | @Test 30 | @SuppressWarnings("AccessStaticViaInstance") 31 | public void shouldGetCorrectReturnType() { 32 | final boolean result = singleWeaver.methodAnnotatedWithRxLogSingle(proceedingJoinPoint); 33 | assertThat(result).isTrue(); 34 | } 35 | 36 | @Test 37 | public void shouldWeaveAroundJoinPointAndReturnCorrectObject() throws Throwable { 38 | final Object object = singleWeaver.weaveAroundJoinPoint(proceedingJoinPoint, mock(Logger.class)); 39 | assertThat(object).isInstanceOf(Single.class); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/test/TestJoinPoint.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.test; 2 | 3 | import java.util.Observable; 4 | import org.aspectj.lang.JoinPoint; 5 | import org.aspectj.lang.Signature; 6 | import org.aspectj.lang.reflect.MethodSignature; 7 | import org.aspectj.lang.reflect.SourceLocation; 8 | import org.mockito.Mock; 9 | import org.mockito.MockitoAnnotations; 10 | 11 | import static org.mockito.BDDMockito.given; 12 | 13 | @SuppressWarnings("unchecked") 14 | public class TestJoinPoint implements JoinPoint { 15 | 16 | @Mock private MethodSignature methodSignature; 17 | 18 | private final Class declaringType; 19 | private final String methodName; 20 | private final Class methodReturnType; 21 | private final String methodReturnValue; 22 | private final Class[] methodParameterTypes; 23 | private final String[] methodParameterNames; 24 | private final Object[] methodParameterValues; 25 | 26 | private TestJoinPoint(Builder builder) { 27 | this.declaringType = builder.declaringType; 28 | this.methodName = builder.methodName; 29 | this.methodReturnType = builder.methodReturnType; 30 | this.methodReturnValue = builder.methodReturnValue; 31 | this.methodParameterTypes = builder.methodParameterTypes; 32 | this.methodParameterNames = builder.methodParameterNames; 33 | this.methodParameterValues = builder.methodParameterValues; 34 | 35 | MockitoAnnotations.initMocks(this); 36 | 37 | try { 38 | given(methodSignature.getDeclaringType()).willReturn(declaringType); 39 | given(methodSignature.getName()).willReturn(methodName); 40 | given(methodSignature.getParameterTypes()).willReturn(methodParameterTypes); 41 | given(methodSignature.getParameterNames()).willReturn(methodParameterNames); 42 | given(methodSignature.getReturnType()).willReturn(methodReturnType); 43 | given(methodSignature.getMethod()).willReturn(declaringType.getMethod(methodName)); 44 | } catch (NoSuchMethodException e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | 49 | @Override public String toShortString() { 50 | return methodName; 51 | } 52 | 53 | @Override public String toLongString() { 54 | return declaringType.getSimpleName() + "#" + methodName; 55 | } 56 | 57 | @Override public Object getThis() { 58 | return this; 59 | } 60 | 61 | @Override public Object getTarget() { 62 | try { 63 | return declaringType.newInstance(); 64 | } catch (Exception e) { 65 | e.printStackTrace(); 66 | } 67 | return null; 68 | } 69 | 70 | @Override public Object[] getArgs() { 71 | return methodParameterValues; 72 | } 73 | 74 | @Override public Signature getSignature() { 75 | return methodSignature; 76 | } 77 | 78 | @Override public SourceLocation getSourceLocation() { 79 | return null; 80 | } 81 | 82 | @Override public String getKind() { 83 | return null; 84 | } 85 | 86 | @Override public StaticPart getStaticPart() { 87 | return null; 88 | } 89 | 90 | public Class getMethodReturnType() { 91 | return methodReturnType; 92 | } 93 | 94 | public String getMethodReturnValue() { 95 | return methodReturnValue; 96 | } 97 | 98 | public static class Builder { 99 | private final Class declaringType; 100 | private final String methodName; 101 | 102 | private Class methodReturnType = Observable.class; 103 | private String methodReturnValue = "android10"; 104 | private Class[] methodParameterTypes = new Class[] {}; 105 | private String[] methodParameterNames = new String[] {}; 106 | private Object[] methodParameterValues = new Object[] {}; 107 | 108 | public Builder(Class declaringType) { 109 | this(declaringType, "toString"); 110 | } 111 | 112 | public Builder(Class declaringType, String methodName) { 113 | this.declaringType = declaringType; 114 | this.methodName = methodName; 115 | } 116 | 117 | public Builder withReturnType(Class returnType) { 118 | this.methodReturnType = returnType; 119 | return this; 120 | } 121 | 122 | public Builder withReturnValue(String returnValue) { 123 | this.methodReturnValue = returnValue; 124 | return this; 125 | } 126 | 127 | public Builder withParamTypes(Class... paramTypes) { 128 | this.methodParameterTypes = paramTypes; 129 | return this; 130 | } 131 | 132 | public Builder withParamNames(String... paramNames) { 133 | this.methodParameterNames = paramNames; 134 | return this; 135 | } 136 | 137 | public Builder withParamValues(Object... paramValues) { 138 | this.methodParameterValues = paramValues; 139 | return this; 140 | } 141 | 142 | public TestJoinPoint build() { 143 | return new TestJoinPoint(this); 144 | } 145 | } 146 | } 147 | 148 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/test/TestProceedingJoinPoint.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.test; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | import org.aspectj.lang.Signature; 5 | import org.aspectj.lang.reflect.MethodSignature; 6 | import org.aspectj.lang.reflect.SourceLocation; 7 | import org.aspectj.runtime.internal.AroundClosure; 8 | 9 | import io.reactivex.Completable; 10 | import io.reactivex.Flowable; 11 | import io.reactivex.Maybe; 12 | import io.reactivex.Observable; 13 | import io.reactivex.Single; 14 | 15 | import static org.assertj.core.api.Assertions.assertThat; 16 | 17 | public class TestProceedingJoinPoint implements ProceedingJoinPoint { 18 | 19 | private final TestJoinPoint testJoinPoint; 20 | 21 | //Used for assertions 22 | private boolean proceedMethodCalled; 23 | private boolean proceedMethodCalledWithArgs; 24 | private Object[] proceedMethodArgs; 25 | 26 | public TestProceedingJoinPoint(TestJoinPoint testJoinPoint) { 27 | this.testJoinPoint = testJoinPoint; 28 | 29 | proceedMethodCalled = false; 30 | proceedMethodCalledWithArgs = false; 31 | proceedMethodArgs = new Object[]{}; 32 | } 33 | 34 | private Object buildReturnType() throws InstantiationException, IllegalAccessException { 35 | final Class returnType = ((MethodSignature) testJoinPoint.getSignature()).getReturnType(); 36 | if (returnType == Observable.class) { 37 | return Observable.just(testJoinPoint.getMethodReturnValue()); 38 | } else if (returnType == Flowable.class) { 39 | return Flowable.just(testJoinPoint.getMethodReturnValue()); 40 | } else if (returnType == Single.class) { 41 | return Single.just(testJoinPoint.getMethodReturnValue()); 42 | } else if (returnType == Maybe.class) { 43 | return Maybe.just(testJoinPoint.getMethodReturnValue()); 44 | } else if (returnType == Completable.class) { 45 | return Completable.complete(); 46 | } 47 | return returnType.newInstance(); 48 | } 49 | 50 | @Override 51 | public void set$AroundClosure(AroundClosure arc) { 52 | //do nothing 53 | } 54 | 55 | @Override 56 | public Object proceed() throws Throwable { 57 | proceedMethodCalled = true; 58 | return buildReturnType(); 59 | } 60 | 61 | @Override 62 | public Object proceed(Object[] args) throws Throwable { 63 | proceedMethodCalledWithArgs = true; 64 | proceedMethodArgs = args; 65 | return buildReturnType(); 66 | } 67 | 68 | @Override 69 | public String toShortString() { 70 | return testJoinPoint.toShortString(); 71 | } 72 | 73 | @Override 74 | public String toLongString() { 75 | return testJoinPoint.toLongString(); 76 | } 77 | 78 | @Override 79 | public Object getThis() { 80 | return this; 81 | } 82 | 83 | @Override 84 | public Object getTarget() { 85 | return testJoinPoint.getTarget(); 86 | } 87 | 88 | @Override 89 | public Object[] getArgs() { 90 | return testJoinPoint.getArgs(); 91 | } 92 | 93 | @Override 94 | public Signature getSignature() { 95 | return testJoinPoint.getSignature(); 96 | } 97 | 98 | @Override 99 | public SourceLocation getSourceLocation() { 100 | return testJoinPoint.getSourceLocation(); 101 | } 102 | 103 | @Override 104 | public String getKind() { 105 | return testJoinPoint.getKind(); 106 | } 107 | 108 | @Override 109 | public StaticPart getStaticPart() { 110 | return testJoinPoint.getStaticPart(); 111 | } 112 | 113 | public Class getMethodReturnType() { 114 | return testJoinPoint.getMethodReturnType(); 115 | } 116 | 117 | public String getMethodReturnValue() { 118 | return testJoinPoint.getMethodReturnValue(); 119 | } 120 | 121 | public void assertProceedMethodCalled() { 122 | assertThat(proceedMethodCalled).isTrue(); 123 | proceedMethodCalled = false; 124 | } 125 | 126 | public void assertProceedMethodCalledWithArgs(Object[] args) { 127 | assertThat(proceedMethodCalledWithArgs).isTrue(); 128 | assertThat(proceedMethodArgs).isEqualTo(args); 129 | proceedMethodCalledWithArgs = false; 130 | proceedMethodArgs = new Object[]{}; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /frodo2-logger/src/test/java/com/fernandocejas/frodo2/test/UnitTest.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.test; 2 | 3 | import org.junit.Rule; 4 | import org.junit.rules.TestRule; 5 | import org.junit.runner.Description; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.model.Statement; 8 | import org.mockito.MockitoAnnotations; 9 | import org.mockito.runners.MockitoJUnitRunner; 10 | 11 | @RunWith(MockitoJUnitRunner.class) 12 | public abstract class UnitTest { 13 | 14 | @Rule public TestRule injectMocksRule = new TestRule() { 15 | @Override 16 | public Statement apply(Statement base, Description description) { 17 | MockitoAnnotations.initMocks(UnitTest.this); 18 | return base; 19 | } 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /frodo2-plugin/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'groovy' 2 | apply plugin: 'java' 3 | apply plugin: 'maven' 4 | 5 | targetCompatibility = JavaVersion.VERSION_1_8 6 | sourceCompatibility = JavaVersion.VERSION_1_8 7 | 8 | dependencies { 9 | implementation gradleApi() 10 | implementation localGroovy() 11 | 12 | implementation "com.android.tools.build:gradle:${project.androidBuildToolsVersion}" 13 | implementation "org.aspectj:aspectjtools:${project.aspectjVersion}" 14 | implementation "org.aspectj:aspectjrt:${project.aspectjVersion}" 15 | 16 | testImplementation "junit:junit:${project.junitVersion}" 17 | } 18 | 19 | groovydoc { 20 | includePrivate = false 21 | } 22 | 23 | //noinspection GroovyAssignabilityCheck 24 | task javadocJar(type: Jar, dependsOn: ['groovydoc']) { 25 | classifier = 'javadoc' 26 | from 'build/docs/groovydoc' 27 | } 28 | 29 | //noinspection GroovyAssignabilityCheck 30 | task sourcesJar(type: Jar, dependsOn: classes) { 31 | classifier = 'sources' 32 | from sourceSets.main.allSource 33 | } 34 | 35 | artifacts { 36 | archives jar 37 | archives sourcesJar 38 | } 39 | -------------------------------------------------------------------------------- /frodo2-plugin/src/main/groovy/com/fernandocejas/frodo2/plugin/FrodoEnablerExtension.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fernandocejas.frodo2.plugin 17 | 18 | class FrodoEnablerExtension { 19 | boolean enabled = true 20 | } 21 | -------------------------------------------------------------------------------- /frodo2-plugin/src/main/groovy/com/fernandocejas/frodo2/plugin/FrodoPlugin.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fernandocejas.frodo2.plugin 17 | 18 | import com.fernandocejas.frodo2.plugin.config.BuildFactory 19 | import org.gradle.api.Plugin 20 | import org.gradle.api.Project 21 | 22 | class FrodoPlugin implements Plugin { 23 | @Override 24 | void apply(Project project) { 25 | createExtensions project 26 | configureProject project 27 | } 28 | 29 | static def createExtensions(Project project) { 30 | project.extensions.create('frodo2', FrodoEnablerExtension) 31 | } 32 | 33 | static def configureProject(Project project) { 34 | new BuildFactory().create(project).configure() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /frodo2-plugin/src/main/groovy/com/fernandocejas/frodo2/plugin/aspect/AspectCompiler.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fernandocejas.frodo2.plugin.aspect 17 | 18 | import org.aspectj.bridge.IMessage 19 | import org.aspectj.bridge.MessageHandler 20 | import org.aspectj.tools.ajc.Main 21 | 22 | class AspectCompiler { 23 | private def logger 24 | 25 | AspectCompiler(logger) { 26 | this.logger = logger 27 | } 28 | 29 | public void compile(String[] compilerArgs) { 30 | final MessageHandler handler = new MessageHandler(true); 31 | new Main().run(compilerArgs, handler); 32 | for (IMessage message : handler.getMessages(null, true)) { 33 | switch (message.getKind()) { 34 | case IMessage.ABORT: 35 | case IMessage.ERROR: 36 | case IMessage.FAIL: 37 | logger.error message.message, message.thrown 38 | break; 39 | case IMessage.WARNING: 40 | logger.warn message.message, message.thrown 41 | break; 42 | case IMessage.INFO: 43 | logger.info message.message, message.thrown 44 | break; 45 | case IMessage.DEBUG: 46 | logger.debug message.message, message.thrown 47 | break; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /frodo2-plugin/src/main/groovy/com/fernandocejas/frodo2/plugin/config/AndroidBuild.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License.*/ 15 | package com.fernandocejas.frodo2.plugin.config 16 | 17 | import com.android.build.gradle.AppPlugin 18 | import com.fernandocejas.frodo2.plugin.aspect.AspectCompiler 19 | import org.gradle.api.Project 20 | import org.gradle.api.tasks.compile.JavaCompile 21 | 22 | class AndroidBuild extends Build { 23 | 24 | AndroidBuild(Project project) { 25 | super(project) 26 | } 27 | 28 | @Override 29 | void configure() { 30 | project.dependencies { 31 | debugImplementation "org.aspectj:aspectjrt:$ASPECTJ_VERSION" 32 | debugImplementation "com.fernandocejas.frodo2:frodo2-runtime-android:$FRODO_VERSION" 33 | debugImplementation "com.fernandocejas.frodo2:frodo2-logger:$FRODO_VERSION" 34 | } 35 | 36 | final def log = project.logger 37 | final def variants = getProjectVariants project 38 | variants.all { variant -> 39 | if (!variant.buildType.isDebuggable()) { 40 | log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.") 41 | return 42 | } else if (!project.frodo2.enabled) { 43 | log.debug('Frodo2 is not enabled.') 44 | return 45 | } 46 | 47 | final JavaCompile javaCompile = variant.javaCompile 48 | javaCompile.doLast { 49 | final String[] args = ["-showWeaveInfo", 50 | "-1.5", 51 | "-inpath", javaCompile.destinationDir.toString(), 52 | "-aspectpath", javaCompile.classpath.asPath, 53 | "-d", javaCompile.destinationDir.toString(), 54 | "-classpath", javaCompile.classpath.asPath, 55 | "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)] 56 | new AspectCompiler(logger).compile(args) 57 | } 58 | } 59 | } 60 | 61 | static def getProjectVariants(Project project) { 62 | if (project.plugins.hasPlugin(AppPlugin)) { 63 | project.android.applicationVariants 64 | } else { 65 | project.android.libraryVariants 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /frodo2-plugin/src/main/groovy/com/fernandocejas/frodo2/plugin/config/Build.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License.*/ 15 | package com.fernandocejas.frodo2.plugin.config 16 | 17 | import org.gradle.api.Project 18 | 19 | abstract class Build { 20 | 21 | protected static final String FRODO_VERSION = "0.9.0" 22 | protected static final String ASPECTJ_VERSION = "1.8.6" 23 | 24 | protected def project 25 | 26 | public Build(Project project) { 27 | this.project = project 28 | setupRepositories() 29 | setupDependencies() 30 | } 31 | 32 | private void setupRepositories() { 33 | this.project.buildscript.repositories.maven { 34 | url "http://dl.bintray.com/android10/maven" 35 | } 36 | 37 | this.project.repositories.maven { 38 | url "http://dl.bintray.com/android10/maven" 39 | } 40 | } 41 | 42 | private void setupDependencies() { 43 | project.dependencies { 44 | implementation "com.fernandocejas.frodo2:frodo2-api:$FRODO_VERSION" 45 | } 46 | } 47 | 48 | abstract void configure() 49 | } 50 | -------------------------------------------------------------------------------- /frodo2-plugin/src/main/groovy/com/fernandocejas/frodo2/plugin/config/BuildFactory.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fernandocejas.frodo2.plugin.config 17 | 18 | import org.gradle.api.Project 19 | import org.gradle.api.tasks.TaskInstantiationException 20 | 21 | class BuildFactory { 22 | 23 | private static final String ANDROID_APP = 'com.android.application' 24 | private static final String ANDROID_LIBRARY = 'com.android.library' 25 | private static final String JAVA_APP = 'application' 26 | private static final String JAVA_LIBRARY = 'java' 27 | 28 | private BuildFactory() {} 29 | 30 | static def create(Project project) { 31 | if (project.pluginManager.hasPlugin(ANDROID_APP) || 32 | project.pluginManager.hasPlugin(ANDROID_LIBRARY)) { 33 | new AndroidBuild(project) 34 | 35 | } else if (project.pluginManager.hasPlugin(JAVA_APP) || 36 | project.pluginManager.hasPlugin(JAVA_LIBRARY)) { 37 | new JavaBuild(project) 38 | 39 | } else { 40 | throw new TaskInstantiationException('Android or Java plugins required') 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /frodo2-plugin/src/main/groovy/com/fernandocejas/frodo2/plugin/config/JavaBuild.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License.*/ 15 | package com.fernandocejas.frodo2.plugin.config 16 | 17 | import com.fernandocejas.frodo2.plugin.aspect.AspectCompiler 18 | import org.gradle.api.Project 19 | import org.gradle.api.tasks.compile.JavaCompile 20 | 21 | class JavaBuild extends Build { 22 | 23 | JavaBuild(Project project) { 24 | super(project) 25 | } 26 | 27 | @Override 28 | void configure() { 29 | project.dependencies { 30 | implementation "org.aspectj:aspectjrt:$ASPECTJ_VERSION" 31 | implementation "com.fernandocejas.frodo2:frodo2-runtime-java:$FRODO_VERSION" 32 | implementation "com.fernandocejas.frodo2:frodo2-logger:$FRODO_VERSION" 33 | } 34 | 35 | final JavaCompile javaCompile = project.compileJava 36 | javaCompile.doLast { 37 | if (project.frodo2.enabled) { 38 | final String[] args = ["-showWeaveInfo", 39 | "-1.5", 40 | "-XnoInline", 41 | "-Xlint:warning", 42 | "-inpath", javaCompile.destinationDir.toString(), 43 | "-inpath", javaCompile.inputs.files.asPath.toString(), 44 | "-aspectpath", javaCompile.classpath.asPath, 45 | "-d", javaCompile.destinationDir.toString(), 46 | "-classpath", javaCompile.classpath.asPath] 47 | new AspectCompiler(logger).compile(args) 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /frodo2-plugin/src/main/resources/META-INF/gradle-plugins/com.fernandocejas.frodo2.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.fernandocejas.frodo2.plugin.FrodoPlugin 2 | -------------------------------------------------------------------------------- /frodo2-runtime-android/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /frodo2-runtime-android/build.gradle: -------------------------------------------------------------------------------- 1 | import org.aspectj.bridge.IMessage 2 | import org.aspectj.bridge.MessageHandler 3 | import org.aspectj.tools.ajc.Main 4 | 5 | apply plugin: 'com.android.library' 6 | apply plugin: 'com.github.dcendents.android-maven' 7 | 8 | dependencies { 9 | implementation "org.jetbrains:annotations:$project.annotationsVersion" 10 | implementation "org.aspectj:aspectjrt:$project.aspectjVersion" 11 | implementation project(':frodo2-api') 12 | implementation project(':frodo2-logger') 13 | } 14 | 15 | android { 16 | buildToolsVersion project.buildToolsVersion 17 | compileSdkVersion Integer.parseInt(project.compileSdkVersion) 18 | 19 | defaultConfig { 20 | versionName project.version 21 | minSdkVersion Integer.parseInt(project.minSdkVersion) 22 | targetSdkVersion Integer.parseInt(project.targetSdkVersion) 23 | } 24 | 25 | lintOptions { 26 | abortOnError false 27 | } 28 | 29 | compileOptions { 30 | targetCompatibility JavaVersion.VERSION_1_8 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | } 33 | } 34 | 35 | android.libraryVariants.all { variant -> 36 | 37 | // Compile aspects 38 | JavaCompile javaCompile = variant.getJavaCompiler() 39 | javaCompile.doLast { 40 | String[] args = ["-showWeaveInfo", 41 | "-1.5", 42 | "-inpath", javaCompile.destinationDir.toString(), 43 | "-aspectpath", javaCompile.classpath.asPath, 44 | "-d", javaCompile.destinationDir.toString(), 45 | "-classpath", javaCompile.classpath.asPath] 46 | 47 | final MessageHandler handler = new MessageHandler(true); 48 | final def log = project.logger 49 | new Main().run(args, handler) 50 | for (IMessage message : handler.getMessages(null, true)) { 51 | switch (message.getKind()) { 52 | case IMessage.ABORT: 53 | case IMessage.ERROR: 54 | case IMessage.FAIL: 55 | log.error message.message, message.thrown 56 | break; 57 | case IMessage.INFO: 58 | log.info message.message, message.thrown 59 | break; 60 | case IMessage.DEBUG: 61 | log.debug message.message, message.thrown 62 | break; 63 | } 64 | } 65 | } 66 | } 67 | 68 | task androidJavadocs(type: Javadoc) { 69 | source = android.sourceSets.main.java.srcDirs 70 | //noinspection GroovyAssignabilityCheck 71 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 72 | } 73 | 74 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { 75 | classifier = 'javadoc' 76 | //noinspection GroovyAssignabilityCheck 77 | from androidJavadocs.destinationDir 78 | } 79 | 80 | task androidSourcesJar(type: Jar) { 81 | classifier = 'sources' 82 | //noinspection GroovyAssignabilityCheck 83 | from android.sourceSets.main.java.srcDirs 84 | } -------------------------------------------------------------------------------- /frodo2-runtime-android/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/fcejas/Software/SDKs/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /frodo2-runtime-android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frodo2-runtime-android/src/main/java/com/fernandocejas/frodo2/android/AndroidLog.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.android; 2 | 3 | import android.util.Log; 4 | import com.fernandocejas.frodo2.logging.Logger; 5 | 6 | /** 7 | * Wrapper around {@link android.util.Log} 8 | */ 9 | class AndroidLog implements Logger { 10 | 11 | AndroidLog() {} 12 | 13 | public void log(String tag, String message) { 14 | Log.d(tag, message); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /frodo2-runtime-android/src/main/java/com/fernandocejas/frodo2/android/LogCompletable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.android; 2 | 3 | import com.fernandocejas.frodo2.logger.completable.CompletableWeaver; 4 | 5 | import org.aspectj.lang.ProceedingJoinPoint; 6 | import org.aspectj.lang.annotation.Around; 7 | import org.aspectj.lang.annotation.Aspect; 8 | import org.aspectj.lang.annotation.Pointcut; 9 | 10 | @Aspect 11 | public class LogCompletable { 12 | 13 | @Pointcut(CompletableWeaver.POINTCUT) 14 | public static boolean methodAnnotatedWithRxLogCompletable(ProceedingJoinPoint joinPoint) { 15 | return CompletableWeaver.methodAnnotatedWithRxLogCompletable(joinPoint); 16 | } 17 | 18 | @Around(CompletableWeaver.ADVICE) 19 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { 20 | return new CompletableWeaver().weaveAroundJoinPoint(joinPoint, new AndroidLog()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /frodo2-runtime-android/src/main/java/com/fernandocejas/frodo2/android/LogFlowable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.android; 2 | 3 | import com.fernandocejas.frodo2.logger.flowable.FlowableWeaver; 4 | import org.aspectj.lang.ProceedingJoinPoint; 5 | import org.aspectj.lang.annotation.Around; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | 9 | @Aspect 10 | public class LogFlowable { 11 | 12 | @Pointcut(FlowableWeaver.POINTCUT) 13 | public static boolean methodAnnotatedWithRxLogFlowable(ProceedingJoinPoint joinPoint) { 14 | return FlowableWeaver.methodAnnotatedWithRxLogFlowable(joinPoint); 15 | } 16 | 17 | @Around(FlowableWeaver.ADVICE) 18 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { 19 | return new FlowableWeaver().weaveAroundJoinPoint(joinPoint, new AndroidLog()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frodo2-runtime-android/src/main/java/com/fernandocejas/frodo2/android/LogMaybe.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.android; 2 | 3 | import com.fernandocejas.frodo2.logger.maybe.MaybeWeaver; 4 | 5 | import org.aspectj.lang.ProceedingJoinPoint; 6 | import org.aspectj.lang.annotation.Around; 7 | import org.aspectj.lang.annotation.Aspect; 8 | import org.aspectj.lang.annotation.Pointcut; 9 | 10 | @Aspect 11 | public class LogMaybe { 12 | 13 | @Pointcut(MaybeWeaver.POINTCUT) 14 | public static boolean methodAnnotatedWithRxLogMaybe(ProceedingJoinPoint joinPoint) { 15 | return MaybeWeaver.methodAnnotatedWithRxLogMaybe(joinPoint); 16 | } 17 | 18 | @Around(MaybeWeaver.ADVICE) 19 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { 20 | return new MaybeWeaver().weaveAroundJoinPoint(joinPoint, new AndroidLog()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /frodo2-runtime-android/src/main/java/com/fernandocejas/frodo2/android/LogObservable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.android; 2 | 3 | import com.fernandocejas.frodo2.logger.observable.ObservableWeaver; 4 | import org.aspectj.lang.ProceedingJoinPoint; 5 | import org.aspectj.lang.annotation.Around; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | 9 | @Aspect 10 | public class LogObservable { 11 | 12 | @Pointcut(ObservableWeaver.POINTCUT) 13 | public static boolean methodAnnotatedWithRxLogObservable(ProceedingJoinPoint joinPoint) { 14 | return ObservableWeaver.methodAnnotatedWithRxLogObservable(joinPoint); 15 | } 16 | 17 | @Around(ObservableWeaver.ADVICE) 18 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { 19 | return new ObservableWeaver().weaveAroundJoinPoint(joinPoint, new AndroidLog()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frodo2-runtime-android/src/main/java/com/fernandocejas/frodo2/android/LogSingle.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.android; 2 | 3 | import com.fernandocejas.frodo2.logger.single.SingleWeaver; 4 | import org.aspectj.lang.ProceedingJoinPoint; 5 | import org.aspectj.lang.annotation.Around; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | 9 | @Aspect 10 | public class LogSingle { 11 | 12 | @Pointcut(SingleWeaver.POINTCUT) 13 | public static boolean methodAnnotatedWithRxLogSingle(ProceedingJoinPoint joinPoint) { 14 | return SingleWeaver.methodAnnotatedWithRxLogSingle(joinPoint); 15 | } 16 | 17 | @Around(SingleWeaver.ADVICE) 18 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { 19 | return new SingleWeaver().weaveAroundJoinPoint(joinPoint, new AndroidLog()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frodo2-runtime-java/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'maven' 3 | 4 | targetCompatibility = JavaVersion.VERSION_1_8 5 | sourceCompatibility = JavaVersion.VERSION_1_8 6 | 7 | dependencies { 8 | implementation "org.aspectj:aspectjrt:$project.aspectjVersion" 9 | implementation project(':frodo2-api') 10 | implementation project(':frodo2-logger') 11 | } 12 | 13 | //noinspection GroovyAssignabilityCheck 14 | task javadocJar(type: Jar, dependsOn: ['javadoc']) { 15 | classifier = 'javadoc' 16 | from 'build/docs/javadoc' 17 | } 18 | 19 | //noinspection GroovyAssignabilityCheck 20 | task sourcesJar(type: Jar, dependsOn: classes) { 21 | classifier = 'sources' 22 | from sourceSets.main.allSource 23 | } 24 | 25 | artifacts { 26 | archives jar 27 | archives sourcesJar 28 | } -------------------------------------------------------------------------------- /frodo2-runtime-java/src/main/java/com/fernandocejas/frodo2/java/JavaLog.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.java; 2 | 3 | import com.fernandocejas.frodo2.logging.Logger; 4 | 5 | class JavaLog implements Logger { 6 | 7 | JavaLog() {} 8 | 9 | @Override 10 | public void log(String tag, String message) { 11 | System.out.println(message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /frodo2-runtime-java/src/main/java/com/fernandocejas/frodo2/java/LogCompletable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.java; 2 | 3 | import com.fernandocejas.frodo2.logger.completable.CompletableWeaver; 4 | import org.aspectj.lang.ProceedingJoinPoint; 5 | import org.aspectj.lang.annotation.Around; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | 9 | @Aspect 10 | public class LogCompletable { 11 | 12 | @Pointcut(CompletableWeaver.POINTCUT) 13 | public static boolean methodAnnotatedWithRxLogCompletable(ProceedingJoinPoint joinPoint) { 14 | return CompletableWeaver.methodAnnotatedWithRxLogCompletable(joinPoint); 15 | } 16 | 17 | @Around(CompletableWeaver.ADVICE) 18 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { 19 | return new CompletableWeaver().weaveAroundJoinPoint(joinPoint, new JavaLog()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frodo2-runtime-java/src/main/java/com/fernandocejas/frodo2/java/LogFlowable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.java; 2 | 3 | import com.fernandocejas.frodo2.logger.flowable.FlowableWeaver; 4 | import org.aspectj.lang.ProceedingJoinPoint; 5 | import org.aspectj.lang.annotation.Around; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | 9 | @Aspect 10 | public class LogFlowable { 11 | 12 | @Pointcut(FlowableWeaver.POINTCUT) 13 | public static boolean methodAnnotatedWithRxLogFlowable(ProceedingJoinPoint joinPoint) { 14 | return FlowableWeaver.methodAnnotatedWithRxLogFlowable(joinPoint); 15 | } 16 | 17 | @Around(FlowableWeaver.ADVICE) 18 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { 19 | return new FlowableWeaver().weaveAroundJoinPoint(joinPoint, new JavaLog()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frodo2-runtime-java/src/main/java/com/fernandocejas/frodo2/java/LogMaybe.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.java; 2 | 3 | import com.fernandocejas.frodo2.logger.maybe.MaybeWeaver; 4 | import org.aspectj.lang.ProceedingJoinPoint; 5 | import org.aspectj.lang.annotation.Around; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | 9 | @Aspect 10 | public class LogMaybe { 11 | 12 | @Pointcut(MaybeWeaver.POINTCUT) 13 | public static boolean methodAnnotatedWithRxLogMaybe(ProceedingJoinPoint joinPoint) { 14 | return MaybeWeaver.methodAnnotatedWithRxLogMaybe(joinPoint); 15 | } 16 | 17 | @Around(MaybeWeaver.ADVICE) 18 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { 19 | return new MaybeWeaver().weaveAroundJoinPoint(joinPoint, new JavaLog()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frodo2-runtime-java/src/main/java/com/fernandocejas/frodo2/java/LogObservable.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.java; 2 | 3 | import com.fernandocejas.frodo2.logger.observable.ObservableWeaver; 4 | import org.aspectj.lang.ProceedingJoinPoint; 5 | import org.aspectj.lang.annotation.Around; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | 9 | @Aspect 10 | public class LogObservable { 11 | 12 | @Pointcut(ObservableWeaver.POINTCUT) 13 | public static boolean methodAnnotatedWithRxLogObservable(ProceedingJoinPoint joinPoint) { 14 | return ObservableWeaver.methodAnnotatedWithRxLogObservable(joinPoint); 15 | } 16 | 17 | @Around(ObservableWeaver.ADVICE) 18 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { 19 | return new ObservableWeaver().weaveAroundJoinPoint(joinPoint, new JavaLog()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frodo2-runtime-java/src/main/java/com/fernandocejas/frodo2/java/LogSingle.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.frodo2.java; 2 | 3 | import com.fernandocejas.frodo2.logger.single.SingleWeaver; 4 | import org.aspectj.lang.ProceedingJoinPoint; 5 | import org.aspectj.lang.annotation.Around; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | 9 | @Aspect 10 | public class LogSingle { 11 | 12 | @Pointcut(SingleWeaver.POINTCUT) 13 | public static boolean methodAnnotatedWithRxLogSingle(ProceedingJoinPoint joinPoint) { 14 | return SingleWeaver.methodAnnotatedWithRxLogSingle(joinPoint); 15 | } 16 | 17 | @Around(SingleWeaver.ADVICE) 18 | public Object weaveAroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable { 19 | return new SingleWeaver().weaveAroundJoinPoint(joinPoint, new JavaLog()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frodo2-sample-android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenLocal() 4 | jcenter() 5 | google() 6 | } 7 | dependencies { 8 | classpath "com.android.tools.build:gradle:$project.androidBuildToolsVersion" 9 | classpath "com.fernandocejas.frodo2:frodo2-plugin:$project.version" 10 | } 11 | } 12 | 13 | apply plugin: 'com.android.application' 14 | apply plugin: 'com.fernandocejas.frodo2' 15 | 16 | //By default frodo2 is ON on debug build variants, although 17 | //we can enable-disable it with this configuration. 18 | frodo2 { 19 | enabled = true 20 | } 21 | 22 | android { 23 | buildToolsVersion project.buildToolsVersion 24 | compileSdkVersion Integer.parseInt(project.compileSdkVersion) 25 | 26 | defaultConfig { 27 | minSdkVersion Integer.parseInt(project.minSdkVersion) 28 | targetSdkVersion Integer.parseInt(project.targetSdkVersion) 29 | } 30 | 31 | signingConfigs { 32 | debug { 33 | storeFile file('debug.keystore') 34 | storePassword 'android' 35 | keyAlias 'androiddebugkey' 36 | keyPassword 'android' 37 | } 38 | } 39 | 40 | buildTypes { 41 | debug { 42 | applicationIdSuffix ".debug" 43 | versionNameSuffix "-debug" 44 | signingConfig signingConfigs.debug 45 | } 46 | release { 47 | applicationIdSuffix ".release" 48 | versionNameSuffix "-release" 49 | signingConfig signingConfigs.debug 50 | } 51 | } 52 | } 53 | 54 | dependencies { 55 | implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" 56 | implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion" 57 | } 58 | -------------------------------------------------------------------------------- /frodo2-sample-android/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android10/frodo2/52bb57303d5d672d9c5c6fafded1cbae873cd225/frodo2-sample-android/debug.keystore -------------------------------------------------------------------------------- /frodo2-sample-android/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/fcejas/Software/SDKs/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/java/com/fernandocejas/example/frodo2/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.example.frodo2; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.Button; 8 | 9 | public class MainActivity extends Activity { 10 | 11 | private Button btnLoadExamples; 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_main); 17 | this.mapGUI(); 18 | } 19 | 20 | private void mapGUI() { 21 | btnLoadExamples = findViewById(R.id.btnLoadExamples); 22 | btnLoadExamples.setOnClickListener(loadExamplesClickListener); 23 | } 24 | 25 | private final View.OnClickListener loadExamplesClickListener = new View.OnClickListener() { 26 | @Override 27 | public void onClick(View v) { 28 | final Intent intent = new Intent(MainActivity.this, SamplesActivity.class); 29 | startActivity(intent); 30 | } 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/java/com/fernandocejas/example/frodo2/SamplesActivity.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.example.frodo2; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.Button; 7 | import android.widget.Toast; 8 | import com.fernandocejas.example.frodo2.sample.AndroidSamples; 9 | 10 | public class SamplesActivity extends Activity { 11 | 12 | private Button btnRxLogFlowable; 13 | private Button btnRxLogObservable; 14 | private Button btnRxLogSingle; 15 | private Button btnRxLogMaybe; 16 | private Button btnRxLogCompletable; 17 | 18 | private final AndroidSamples samples = new AndroidSamples(); 19 | 20 | private View.OnClickListener rxLogFlowableListener = new View.OnClickListener() { 21 | @Override public void onClick(View v) { 22 | toastMessage("Running FLOWABLE Samples: Check LOGCAT!"); 23 | samples.runFlowableExamples(); 24 | } 25 | }; 26 | 27 | private View.OnClickListener rxLogObservableListener = new View.OnClickListener() { 28 | @Override public void onClick(View v) { 29 | toastMessage("Running OBSERVABLE Samples: Check LOGCAT!"); 30 | samples.runObservableExamples(); 31 | } 32 | }; 33 | 34 | private View.OnClickListener rxLogSingleListener = new View.OnClickListener() { 35 | @Override public void onClick(View v) { 36 | toastMessage("Running SINGLE Samples: Check LOGCAT!"); 37 | samples.runSingleExamples(); 38 | } 39 | }; 40 | 41 | private View.OnClickListener rxLogMaybeListener = new View.OnClickListener() { 42 | @Override public void onClick(View v) { 43 | toastMessage("Running MAYBE Samples: Check LOGCAT!"); 44 | samples.runMaybeExamples(); 45 | } 46 | }; 47 | 48 | private View.OnClickListener rxLogCompletableListener = new View.OnClickListener() { 49 | @Override public void onClick(View v) { 50 | toastMessage("Running COMPLETABLE Samples: Check LOGCAT!"); 51 | samples.runCompletableExamples(); 52 | } 53 | }; 54 | 55 | @Override protected void onCreate(Bundle savedInstanceState) { 56 | super.onCreate(savedInstanceState); 57 | setContentView(R.layout.activity_samples); 58 | this.initialize(); 59 | } 60 | 61 | @Override 62 | protected void onDestroy() { 63 | samples.dispose(); 64 | super.onDestroy(); 65 | } 66 | 67 | private void initialize() { 68 | this.btnRxLogFlowable = findViewById(R.id.btnRxLogFlowable); 69 | this.btnRxLogObservable = findViewById(R.id.btnRxLogObservable); 70 | this.btnRxLogSingle = findViewById(R.id.btnRxLogSingle); 71 | this.btnRxLogMaybe = findViewById(R.id.btnRxLogMaybe); 72 | this.btnRxLogCompletable = findViewById(R.id.btnRxLogCompletable); 73 | 74 | this.btnRxLogFlowable.setOnClickListener(rxLogFlowableListener); 75 | this.btnRxLogObservable.setOnClickListener(rxLogObservableListener); 76 | this.btnRxLogSingle.setOnClickListener(rxLogSingleListener); 77 | this.btnRxLogMaybe.setOnClickListener(rxLogMaybeListener); 78 | this.btnRxLogCompletable.setOnClickListener(rxLogCompletableListener); 79 | } 80 | 81 | private void toastMessage(String message) { 82 | Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/java/com/fernandocejas/example/frodo2/sample/AndroidSamples.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.example.frodo2.sample; 2 | 3 | import io.reactivex.Completable; 4 | import io.reactivex.Flowable; 5 | import io.reactivex.Maybe; 6 | import io.reactivex.Observable; 7 | import io.reactivex.Single; 8 | import io.reactivex.android.schedulers.AndroidSchedulers; 9 | import io.reactivex.disposables.CompositeDisposable; 10 | import io.reactivex.disposables.Disposable; 11 | import io.reactivex.schedulers.Schedulers; 12 | import java.util.List; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | public class AndroidSamples { 16 | 17 | private final FlowableSamples flowableSamples; 18 | private final ObservableSamples observableSamples; 19 | private final SingleSamples singleSamples; 20 | private final MaybeSamples maybeSamples; 21 | private final CompletableSamples completableSamples; 22 | 23 | private final CompositeDisposable disposables; 24 | 25 | public AndroidSamples() { 26 | flowableSamples = new FlowableSamples(); 27 | observableSamples = new ObservableSamples(); 28 | singleSamples = new SingleSamples(); 29 | maybeSamples = new MaybeSamples(); 30 | completableSamples = new CompletableSamples(); 31 | 32 | disposables = new CompositeDisposable(); 33 | } 34 | 35 | private void addDisposable(Disposable disposable) { 36 | disposables.add(disposable); 37 | } 38 | 39 | public void dispose() { 40 | if (!disposables.isDisposed()) { 41 | disposables.dispose(); 42 | } 43 | } 44 | 45 | public void runFlowableExamples() { 46 | executeRxFlowableSampleOne(); 47 | executeRxFlowableSampleTwo(); 48 | } 49 | 50 | public void runObservableExamples() { 51 | executeRxObservableSampleOne(); 52 | executeRxObservableSampleTwo(); 53 | executeRxObservableSampleThree(); 54 | } 55 | 56 | public void runSingleExamples() { 57 | executeRxSingleSamples(); 58 | } 59 | 60 | public void runMaybeExamples() { 61 | executeRxMaybeSamples(); 62 | } 63 | 64 | public void runCompletableExamples() { 65 | executeRxCompletableSamples(); 66 | } 67 | 68 | //------------------------------------------------ 69 | // F L O W A B L E S A M P L E S 70 | //------------------------------------------------ 71 | private void executeRxFlowableSampleOne() { 72 | final Flowable integers = 73 | flowableSamples.numbers().subscribeOn(Schedulers.newThread()); 74 | addDisposable(integers.subscribeWith(new MySubscriber<>())); 75 | 76 | final Flowable strings = flowableSamples.strings() 77 | .delay(2, TimeUnit.SECONDS) 78 | .subscribeOn(Schedulers.io()) 79 | .observeOn(Schedulers.newThread()); 80 | disposables.add(strings.subscribe()); 81 | } 82 | 83 | private void executeRxFlowableSampleTwo() { 84 | final Flowable voidFlowable = 85 | flowableSamples.doNothing().delay(8, TimeUnit.SECONDS).subscribeOn(Schedulers.io()); 86 | disposables.add(voidFlowable.subscribeWith(new MySubscriber<>())); 87 | 88 | final Flowable error = flowableSamples.error().delay(4, TimeUnit.SECONDS); 89 | disposables.add(error.subscribeWith(new MySubscriber<>())); 90 | } 91 | 92 | //------------------------------------------------ 93 | // O B S E R V A B L E S A M P L E S 94 | //------------------------------------------------ 95 | private void executeRxObservableSampleOne() { 96 | final Observable integers = observableSamples.numbers() 97 | .subscribeOn(Schedulers.newThread()) 98 | .observeOn(AndroidSchedulers.mainThread()); 99 | 100 | final MyObserver observer = new MyObserver() { 101 | @Override public void onNext(Integer integer) { 102 | //Do Nothing 103 | } 104 | }; 105 | addDisposable(integers.subscribeWith(observer)); 106 | 107 | final Observable strings = observableSamples.strings() 108 | .subscribeOn(Schedulers.io()) 109 | .observeOn(Schedulers.newThread()); 110 | disposables.add(strings.subscribe()); 111 | 112 | final Observable error = observableSamples.error(); 113 | disposables.add(error.subscribeWith(new MyObserver<>())); 114 | } 115 | 116 | private void executeRxObservableSampleTwo() { 117 | final Observable voidObservable = observableSamples.doNothing() 118 | .subscribeOn(Schedulers.io()); 119 | disposables.add(voidObservable.subscribeWith(new MyObserver<>())); 120 | 121 | final Observable dummyClassObservable = observableSamples.doSomething() 122 | .subscribeOn(AndroidSchedulers.mainThread()) 123 | .observeOn(AndroidSchedulers.mainThread()); 124 | disposables.add(dummyClassObservable.subscribe()); 125 | } 126 | 127 | private void executeRxObservableSampleThree() { 128 | final Observable stringWithDefer = observableSamples.stringItemWithDefer(); 129 | disposables.add(stringWithDefer.subscribeWith(new MyObserver<>())); 130 | 131 | final Observable stringObservable = observableSamples.manualCreation() 132 | .subscribeOn(Schedulers.newThread()) 133 | .observeOn(AndroidSchedulers.mainThread()); 134 | disposables.add(stringObservable.subscribe()); 135 | 136 | final Observable> listObservable = observableSamples.list() 137 | .subscribeOn(Schedulers.newThread()) 138 | .observeOn(AndroidSchedulers.mainThread()); 139 | disposables.add(listObservable.subscribe()); 140 | } 141 | 142 | //------------------------------------------------ 143 | // S I N G L E S A M P L E S 144 | //------------------------------------------------ 145 | private void executeRxSingleSamples() { 146 | final Single integer = 147 | singleSamples.number().subscribeOn(Schedulers.newThread()); 148 | addDisposable(integer.subscribe()); 149 | 150 | final Single string = singleSamples.string() 151 | .delay(2, TimeUnit.SECONDS) 152 | .subscribeOn(Schedulers.io()) 153 | .observeOn(Schedulers.newThread()); 154 | disposables.add(string.subscribe()); 155 | 156 | final Single single = 157 | singleSamples.singleFromObservable().delay(8, TimeUnit.SECONDS).subscribeOn(Schedulers.io()); 158 | disposables.add(single.subscribe()); 159 | } 160 | 161 | //------------------------------------------------ 162 | // M A Y B E S A M P L E S 163 | //------------------------------------------------ 164 | private void executeRxMaybeSamples() { 165 | final Maybe integer = 166 | maybeSamples.number().subscribeOn(Schedulers.newThread()); 167 | addDisposable(integer.subscribe()); 168 | 169 | final Maybe string = maybeSamples.string() 170 | .delay(2, TimeUnit.SECONDS) 171 | .subscribeOn(Schedulers.io()) 172 | .observeOn(Schedulers.newThread()); 173 | disposables.add(string.subscribe()); 174 | 175 | final Maybe maybe = 176 | maybeSamples.maybeFromSingle().delay(8, TimeUnit.SECONDS).subscribeOn(Schedulers.io()); 177 | disposables.add(maybe.subscribe()); 178 | } 179 | 180 | //------------------------------------------------ 181 | // C O M P L E T A B L E S A M P L E S 182 | //------------------------------------------------ 183 | private void executeRxCompletableSamples() { 184 | final Completable doSomething = completableSamples.doSomething() 185 | .subscribeOn(Schedulers.newThread()) 186 | .observeOn(AndroidSchedulers.mainThread()); 187 | disposables.add(doSomething.subscribe()); 188 | 189 | final Completable executeOperation = completableSamples.executeOperation() 190 | .subscribeOn(Schedulers.single()) 191 | .observeOn(Schedulers.single()); 192 | disposables.add(executeOperation.subscribe()); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/java/com/fernandocejas/example/frodo2/sample/CompletableSamples.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fernandocejas.example.frodo2.sample; 17 | 18 | import com.fernandocejas.frodo2.annotation.RxLogCompletable; 19 | import io.reactivex.Completable; 20 | import io.reactivex.functions.Action; 21 | import java.util.concurrent.Callable; 22 | 23 | class CompletableSamples { 24 | 25 | CompletableSamples() {} 26 | 27 | @RxLogCompletable 28 | Completable doSomething() { 29 | return Completable.fromAction(new Action() { 30 | @Override public void run() throws Exception { 31 | Thread.sleep(1000); 32 | } 33 | }); 34 | } 35 | 36 | @RxLogCompletable 37 | Completable executeOperation() { 38 | return Completable.fromCallable(sleepingTime()); 39 | } 40 | 41 | private Callable sleepingTime() { 42 | return new Callable() { 43 | @Override public Object call() throws Exception { 44 | Thread.sleep(3000); 45 | return true; 46 | } 47 | }; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/java/com/fernandocejas/example/frodo2/sample/FlowableSamples.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fernandocejas.example.frodo2.sample; 17 | 18 | import com.fernandocejas.frodo2.annotation.RxLogFlowable; 19 | import io.reactivex.Flowable; 20 | 21 | class FlowableSamples { 22 | 23 | FlowableSamples() {} 24 | 25 | @RxLogFlowable 26 | Flowable numbers() { 27 | return Flowable.just(1, 2, 3, 4); 28 | } 29 | 30 | @RxLogFlowable 31 | Flowable strings() { 32 | return Flowable.just("Hello", "My", "Name", "Is", "Fernando"); 33 | } 34 | 35 | @RxLogFlowable 36 | Flowable error() { 37 | return Flowable.error(new IllegalArgumentException("My error")); 38 | } 39 | 40 | @RxLogFlowable 41 | Flowable doNothing() { 42 | return Flowable.empty(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/java/com/fernandocejas/example/frodo2/sample/MaybeSamples.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fernandocejas.example.frodo2.sample; 17 | 18 | import com.fernandocejas.frodo2.annotation.RxLogMaybe; 19 | import io.reactivex.Maybe; 20 | import io.reactivex.Observable; 21 | import io.reactivex.Single; 22 | 23 | class MaybeSamples { 24 | 25 | MaybeSamples() {} 26 | 27 | @RxLogMaybe 28 | Maybe number() { 29 | return Maybe.just(1); 30 | } 31 | 32 | @RxLogMaybe 33 | Maybe string() { 34 | return Maybe.just("My Value"); 35 | } 36 | 37 | @RxLogMaybe 38 | Maybe maybeFromSingle() { 39 | final Observable observable = Observable.just(new MyClass("Hello World")); 40 | return Maybe.fromSingle(Single.fromObservable(observable)); 41 | } 42 | 43 | static final class MyClass { 44 | private final String name; 45 | 46 | MyClass(String name) { 47 | this.name = name; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | return "Name: " + name; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/java/com/fernandocejas/example/frodo2/sample/MyObserver.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.example.frodo2.sample; 2 | 3 | import io.reactivex.observers.ResourceObserver; 4 | 5 | class MyObserver extends ResourceObserver { 6 | @Override public void onNext(T value) {} 7 | @Override public void onError(Throwable e) {} 8 | @Override public void onComplete() {} 9 | } 10 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/java/com/fernandocejas/example/frodo2/sample/MySubscriber.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.example.frodo2.sample; 2 | 3 | import io.reactivex.subscribers.ResourceSubscriber; 4 | 5 | public class MySubscriber extends ResourceSubscriber { 6 | @Override public void onNext(T value) {} 7 | @Override public void onError(Throwable e) {} 8 | @Override public void onComplete() {} 9 | } 10 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/java/com/fernandocejas/example/frodo2/sample/ObservableSamples.java: -------------------------------------------------------------------------------- 1 | package com.fernandocejas.example.frodo2.sample; 2 | 3 | import com.fernandocejas.frodo2.annotation.RxLogObservable; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | import java.util.concurrent.Callable; 8 | 9 | import io.reactivex.Observable; 10 | import io.reactivex.ObservableEmitter; 11 | import io.reactivex.ObservableOnSubscribe; 12 | import io.reactivex.ObservableSource; 13 | import io.reactivex.android.schedulers.AndroidSchedulers; 14 | import io.reactivex.schedulers.Schedulers; 15 | 16 | class ObservableSamples { 17 | 18 | ObservableSamples() {} 19 | 20 | @RxLogObservable 21 | Observable numbers() { 22 | return Observable.just(1, 2, 3, 4) 23 | .subscribeOn(Schedulers.newThread()) 24 | .observeOn(AndroidSchedulers.mainThread()); 25 | } 26 | 27 | @RxLogObservable 28 | Observable strings() { 29 | return Observable.just("Hello", "My", "Name", "Is", "Fernando"); 30 | } 31 | 32 | @RxLogObservable 33 | Observable error() { 34 | return Observable.error(new IllegalArgumentException("My error")); 35 | } 36 | 37 | @RxLogObservable 38 | Observable stringItemWithDefer() { 39 | return Observable.defer(new Callable>() { 40 | @Override public ObservableSource call() throws Exception { 41 | return Observable.create(new ObservableOnSubscribe() { 42 | @Override public void subscribe(ObservableEmitter emitter) throws Exception { 43 | try { 44 | emitter.onNext("String item value"); 45 | emitter.onComplete(); 46 | } catch (Exception e) { 47 | emitter.onError(e); 48 | } 49 | } 50 | }).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()); 51 | } 52 | }); 53 | } 54 | 55 | @RxLogObservable 56 | public Observable manualCreation() { 57 | return Observable.create(new ObservableOnSubscribe() { 58 | @Override public void subscribe(ObservableEmitter emitter) throws Exception { 59 | try { 60 | emitter.onNext("String value emitted!"); 61 | emitter.onComplete(); 62 | } catch (Exception e) { 63 | emitter.onError(e); 64 | } 65 | } 66 | }); 67 | } 68 | 69 | @RxLogObservable 70 | Observable doNothing() { 71 | return Observable.empty(); 72 | } 73 | 74 | @RxLogObservable 75 | Observable doSomething() { 76 | return Observable.just(new MyDummyClass("Fernando")); 77 | } 78 | 79 | @RxLogObservable 80 | Observable> list() { 81 | return Observable.just(buildDummyList()); 82 | } 83 | 84 | private List buildDummyList() { 85 | return Arrays.asList(new MyDummyClass("Batman"), new MyDummyClass("Superman")); 86 | } 87 | 88 | static final class MyDummyClass { 89 | private final String name; 90 | 91 | MyDummyClass(String name) { 92 | this.name = name; 93 | } 94 | 95 | @Override 96 | public String toString() { 97 | return "Name: " + name; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/java/com/fernandocejas/example/frodo2/sample/SingleSamples.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2016 android10.org Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.fernandocejas.example.frodo2.sample; 17 | 18 | import com.fernandocejas.frodo2.annotation.RxLogSingle; 19 | import io.reactivex.Observable; 20 | import io.reactivex.Single; 21 | 22 | class SingleSamples { 23 | 24 | SingleSamples() {} 25 | 26 | @RxLogSingle 27 | Single number() { 28 | return Single.just(1); 29 | } 30 | 31 | @RxLogSingle 32 | Single string() { 33 | return Single.just("My Value"); 34 | } 35 | 36 | @RxLogSingle 37 | Single singleFromObservable() { 38 | final Observable observable = Observable.just(new MyClass("Hello World")); 39 | return Single.fromObservable(observable); 40 | } 41 | 42 | static final class MyClass { 43 | private final String name; 44 | 45 | MyClass(String name) { 46 | this.name = name; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "Name: " + name; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android10/frodo2/52bb57303d5d672d9c5c6fafded1cbae873cd225/frodo2-sample-android/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/res/drawable-hdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android10/frodo2/52bb57303d5d672d9c5c6fafded1cbae873cd225/frodo2-sample-android/src/main/res/drawable-hdpi/logo.png -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android10/frodo2/52bb57303d5d672d9c5c6fafded1cbae873cd225/frodo2-sample-android/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android10/frodo2/52bb57303d5d672d9c5c6fafded1cbae873cd225/frodo2-sample-android/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/android10/frodo2/52bb57303d5d672d9c5c6fafded1cbae873cd225/frodo2-sample-android/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /frodo2-sample-android/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 20 | 21 | 27 | 28 |