diff --git a/build.gradle b/build.gradle index 9073b716ee..29b55f5c1a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,9 @@ +apply from: file('gradle/convention.gradle') +apply from: file('gradle/maven.gradle') +//apply from: file('gradle/check.gradle') +apply from: file('gradle/license.gradle') +apply from: file('gradle/release.gradle') + ext.githubProjectName = rootProject.name buildscript { @@ -9,20 +15,53 @@ allprojects { repositories { mavenCentral() } } -apply from: file('gradle/convention.gradle') -apply from: file('gradle/maven.gradle') -//apply from: file('gradle/check.gradle') -apply from: file('gradle/license.gradle') -apply from: file('gradle/release.gradle') - subprojects { + apply plugin: 'java' + apply plugin: 'eclipse' + apply plugin: 'idea' group = "com.netflix.${githubProjectName}" - sourceSets.test.java.srcDir 'src/main/java' + ext.codeGenOutputDir = file("build/rewritten_classes") + + // make 'examples' use the same classpath + configurations { + core + examplesCompile.extendsFrom compile + examplesRuntime.extendsFrom runtime + } + + sourceSets.test.java.srcDirs.add('src/main/java') tasks.withType(Javadoc).each { it.classpath = sourceSets.main.compileClasspath } + + sourceSets { + //include /src/examples folder + examples + } + + // include 'examples' in build task + tasks.build { + dependsOn(examplesClasses) + } + + eclipse { + classpath { + // include 'provided' dependencies on the classpath + plusConfigurations += configurations.provided + + downloadSources = true + downloadJavadoc = true + } + } + + idea { + module { + // include 'provided' dependencies on the classpath + scopes.PROVIDED.plus += configurations.provided + } + } } diff --git a/gradle.properties b/gradle.properties index 9a1e264337..6230d72284 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=0.9.2-SNAPSHOT +version=0.10.0-SNAPSHOT diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e230e2b1c4..2abe81ceda 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-1.3-bin.zip +distributionUrl=http\://services.gradle.org/distributions/gradle-1.6-bin.zip diff --git a/language-adaptors/codegen/build.gradle b/language-adaptors/codegen/build.gradle new file mode 100644 index 0000000000..1541b10429 --- /dev/null +++ b/language-adaptors/codegen/build.gradle @@ -0,0 +1,24 @@ +apply plugin: 'java' +apply plugin: 'groovy' +apply plugin: 'eclipse' +apply plugin: 'idea' +apply plugin: 'osgi' + +dependencies { + compile project(':rxjava-core') + compile 'org.javassist:javassist:3.17.1-GA' + + provided 'junit:junit:4.10' +} + +jar { + exclude('**/*$UnitTest*') + + manifest { + name = 'rxjava-codegen' + instruction 'Bundle-Vendor', 'Netflix' + instruction 'Bundle-DocURL', 'https://github.com/Netflix/RxJava' + instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' + instruction 'Fragment-Host', 'com.netflix.rxjava.core' + } +} \ No newline at end of file diff --git a/language-adaptors/codegen/examples.txt b/language-adaptors/codegen/examples.txt new file mode 100644 index 0000000000..3cece97b6f --- /dev/null +++ b/language-adaptors/codegen/examples.txt @@ -0,0 +1,47 @@ +Here's the example source of Observable (heavily elided): + +public class rx.Observable { + public static Observable create(Func1, Subscription> func) { + return new Observable(func); + } + + public static Observable create(Object func) { + ... + } + + public static Observable take(final Observable items, final int num) { + return create(OperationTake.take(items, num)); + } + + public static Observable takeWhile(final Observable items, Func1 predicate) { + return create(OperationTakeWhile.takeWhile(items, predicate)); + } + + public Observable filter(Func1 predicate) { + return filter(this, predicate); + } + + public static Observable filter(Observable that, Func1 predicate) { + return create(OperationFilter.filter(that, predicate)); + } +} + +Groovy-friendly version adds: + +public class rx.Observable { + public static rx.Observable create(groovy.lang.Closure func) { + return create(new GroovyFunctionAdaptor(func)); + } + + public static rx.Observable takeWhile(final Observable items, groovy.lang.Closure predicate) { + return takeWhile(items, new GroovyFunctionAdaptor(predicate)); + } + + public rx.Observable filter(groovy.lang.Closure predicate) { + return filter(new GroovyFunctionAdaptor(predicate)); + } + + public static rxObservable filter(Observable that, groovy.lang.Closure predicate) { + return filter(that, new GroovyFunctionAdaptor(predicate)); + } +} diff --git a/language-adaptors/codegen/src/main/java/rx/codegen/ClassPathBasedRunner.java b/language-adaptors/codegen/src/main/java/rx/codegen/ClassPathBasedRunner.java new file mode 100644 index 0000000000..ace0a316d2 --- /dev/null +++ b/language-adaptors/codegen/src/main/java/rx/codegen/ClassPathBasedRunner.java @@ -0,0 +1,64 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package rx.codegen; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import rx.util.functions.FunctionLanguageAdaptor; + +public class ClassPathBasedRunner { + public static void main(String[] args) { + if (args.length != 2) { + System.out.println("Usage : Expects 2 args: (Language, File to place classfiles)"); + System.out.println("Currently supported languages: Groovy/Clojure/JRuby"); + System.exit(1); + } + String lang = args[0]; + File dir = new File(args[1]); + System.out.println("Looking for Adaptor for : " + lang); + String className = "rx.lang." + lang.toLowerCase() + "." + lang + "Adaptor"; + try { + Class adaptorClass = Class.forName(className); + System.out.println("Found Adaptor : " + adaptorClass); + FunctionLanguageAdaptor adaptor = (FunctionLanguageAdaptor) adaptorClass.newInstance(); + + CodeGenerator codeGen = new CodeGenerator(); + System.out.println("Using dir : " + dir + " for outputting classfiles"); + for (Class observableClass: getObservableClasses()) { + codeGen.addMethods(observableClass, adaptor, new File(args[1])); + } + } catch (ClassNotFoundException ex) { + System.out.println("Did not find adaptor class : " + className); + System.exit(1); + } catch (InstantiationException ex) { + System.out.println("Reflective constuctor on : " + className + " failed"); + System.exit(1); + } catch (IllegalAccessException ex) { + System.out.println("Access to constructor on : " + className + " failed"); + System.exit(1); + } + } + + private static List> getObservableClasses() { + List> observableClasses = new ArrayList>(); + observableClasses.add(rx.Observable.class); + observableClasses.add(rx.observables.BlockingObservable.class); + return observableClasses; + } +} \ No newline at end of file diff --git a/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java b/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java new file mode 100644 index 0000000000..ed737e4999 --- /dev/null +++ b/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java @@ -0,0 +1,299 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.codegen; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.Modifier; +import javassist.NotFoundException; + +import rx.util.functions.Action; +import rx.util.functions.Action0; +import rx.util.functions.Action1; +import rx.util.functions.Action2; +import rx.util.functions.Action3; +import rx.util.functions.Func0; +import rx.util.functions.Func1; +import rx.util.functions.Func2; +import rx.util.functions.Func3; +import rx.util.functions.Func4; +import rx.util.functions.Func5; +import rx.util.functions.Func6; +import rx.util.functions.Func7; +import rx.util.functions.Func8; +import rx.util.functions.Func9; +import rx.util.functions.Function; +import rx.util.functions.FunctionLanguageAdaptor; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import org.junit.Test; + +public class CodeGenerator { + + static ClassPool pool = ClassPool.getDefault(); + + public void addMethods(Class initialClass, FunctionLanguageAdaptor adaptor, File file) { + Set> nativeFunctionClasses = adaptor.getAllClassesToRewrite(); + System.out.println("Adding dynamic language support to : " + initialClass.getSimpleName()); + for (Class nativeFunctionClass: nativeFunctionClasses) { + System.out.println(" * Adding : " + nativeFunctionClass.getName()); + } + addSupportFor(initialClass, adaptor, file); + } + + private static void addSupportFor(Class observableClass, FunctionLanguageAdaptor adaptor, File file) { + CtClass clazz; + + if (!observableClass.getName().startsWith("rx.")) { + throw new IllegalStateException("Refusing to rewrite a class that is not a core Rx Observable!"); + } + + Set> nativeFunctionClasses = adaptor.getAllClassesToRewrite(); + + try { + clazz = pool.get(observableClass.getName()); + } catch (NotFoundException e) { + throw new RuntimeException("Failed to add language adaptor methods as could not find observable Class named " + observableClass.getName(), e); + } + try { + rewriteMethodsWithRxArgs(clazz, adaptor); + writeClassFile(clazz, file); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to add language adaptor methods.", e); + } + } + + private static void rewriteMethodsWithRxArgs(CtClass clazz, FunctionLanguageAdaptor adaptor) throws Exception { + List newMethods = new ArrayList(); + + for (CtMethod method : clazz.getMethods()) { + CtClass[] argTypes = method.getParameterTypes(); + boolean needsRewrite = false; + for (CtClass argType : argTypes) { + if (isRxFunctionType(argType) || isRxActionType(argType)) { + needsRewrite = true; + } + } + if (needsRewrite) { + try { + newMethods.addAll(getRewrittenMethods(clazz, method, adaptor)); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to add language adaptor method: " + method.getName(), e); + } + } + } + + for (CtMethod cm: newMethods) { + clazz.addMethod(cm); + } + } + + private static boolean isNativeFunctionType(CtClass type, Set> nativeFunctionClasses) { + for (Class nativeFunctionClass: nativeFunctionClasses) { + if (type.getName().equals(nativeFunctionClass.getName())) { + return true; + } + } + return false; + } + + private static boolean isRxFunctionType(CtClass type) throws Exception { + return implementsInterface(type, Function.class); + } + + private static boolean isRxActionType(CtClass type) throws Exception { + return implementsInterface(type, Action.class); + } + + private static boolean implementsInterface(CtClass type, Class interfaceClass) throws Exception { + // Did I pass in the exact interface? + if (type.getName().equals(interfaceClass.getName())) { + return true; + } + // Do I implement the interface? + for (CtClass implementedInterface : type.getInterfaces()) { + if (implementedInterface.getName().equals(interfaceClass.getName())) { + return true; + } + } + return false; + } + + private static List getRewrittenMethods(CtClass clazz, CtMethod method, FunctionLanguageAdaptor adaptor) throws Exception { + List newMethods = new ArrayList(); + + for (Class nativeFunctionClass: adaptor.getAllClassesToRewrite()) { + Class functionAdaptorClass = adaptor.getFunctionClassRewritingMap().get(nativeFunctionClass); + Class actionAdaptorClass = adaptor.getActionClassRewritingMap().get(nativeFunctionClass); + ArrayList parameters = new ArrayList(); + CtClass[] argTypes = method.getParameterTypes(); + + ArrayList initialArgTypes = new ArrayList(); + ArrayList finalArgTypes = new ArrayList(); + + for (CtClass argType : argTypes) { + initialArgTypes.add(argType.getName()); + if (isRxFunctionType(argType) || isRxActionType(argType)) { + // needs conversion + finalArgTypes.add(nativeFunctionClass.getName()); + parameters.add(pool.get(nativeFunctionClass.getName())); + } else { + // no conversion, copy through + finalArgTypes.add(argType.getName()); + parameters.add(argType); + } + } + + String initialArgString = makeArgList(initialArgTypes); + String finalArgString = makeArgList(finalArgTypes); + + CtClass[] oldParameters = parameters.toArray(new CtClass[parameters.size()]); + CtMethod newMethod = new CtMethod(method.getReturnType(), method.getName(), oldParameters, clazz); + newMethod.setModifiers(method.getModifiers()); + List argumentList = new ArrayList(); + StringBuffer newBody = new StringBuffer(); + newBody.append("{ return "); + if (Modifier.isStatic(method.getModifiers())) { + newBody.append(clazz.getName() + "."); + } else { + newBody.append("this."); + } + newBody.append(method.getName()); + newBody.append("("); + for (int i = 0; i < method.getParameterTypes().length; i++) { + CtClass argType = method.getParameterTypes()[i]; + if (isRxActionType(argType) && actionAdaptorClass != null) { + argumentList.add(getAdaptedArg(actionAdaptorClass, i + 1)); + } else if (isRxFunctionType(argType) && functionAdaptorClass != null) { + argumentList.add(getAdaptedArg(functionAdaptorClass, i + 1)); + } else { + argumentList.add(getUntouchedArg(i + 1)); + } + } + newBody.append(makeArgList(argumentList)); + newBody.append(")"); + newBody.append(";}"); + //Uncomment these to see all of the rewritten methods + //System.out.println(method.getReturnType().getName() + " " + method.getName() + "(" + initialArgString + ") --> " + newMethod.getReturnType().getName() + " " + newMethod.getName() + "(" + finalArgString + ")"); + //System.out.println(" " + newBody.toString()); + newMethod.setBody(newBody.toString()); + newMethods.add(newMethod); + } + return newMethods; + } + + private static String getAdaptedArg(Class adaptorClass, int index) { + StringBuffer buffer = new StringBuffer(); + buffer.append("new "); + buffer.append(adaptorClass.getName()); + buffer.append("("); + buffer.append(getUntouchedArg(index)); + buffer.append(")"); + return buffer.toString(); + } + + private static String getUntouchedArg(int index) { + StringBuffer buffer = new StringBuffer(); + buffer.append("$"); + buffer.append(index); + return buffer.toString(); + } + + private static String makeArgList(List args) { + if (args.size() > 0) { + StringBuffer buffer = new StringBuffer(args.get(0)); + for (String arg: args.subList(1, args.size())) { + buffer.append("," + arg); + } + return buffer.toString(); + } + return ""; + } + + private static void writeClassFile(CtClass clazz, File dir) { + try { + System.out.println("Using " + dir.getCanonicalPath() + " for dynamic class file"); + clazz.writeFile(dir.getCanonicalPath()); + } catch (java.io.IOException ioe) { + System.out.println("Could not write classfile to : " + dir.toString()); + System.exit(1); + } catch (javassist.CannotCompileException cce) { + System.out.println("Could not create a valid classfile"); + System.exit(2); + } + } + + public static class UnitTest { + @Test + public void testIsRxFunctionType() { + try { + assertTrue(isRxFunctionType(pool.get(Function.class.getName()))); + assertTrue(isRxFunctionType(pool.get(Func0.class.getName()))); + assertTrue(isRxFunctionType(pool.get(Func1.class.getName()))); + assertTrue(isRxFunctionType(pool.get(Func2.class.getName()))); + assertTrue(isRxFunctionType(pool.get(Func3.class.getName()))); + assertTrue(isRxFunctionType(pool.get(Func4.class.getName()))); + assertTrue(isRxFunctionType(pool.get(Func5.class.getName()))); + assertTrue(isRxFunctionType(pool.get(Func6.class.getName()))); + assertTrue(isRxFunctionType(pool.get(Func7.class.getName()))); + assertTrue(isRxFunctionType(pool.get(Func8.class.getName()))); + assertTrue(isRxFunctionType(pool.get(Func9.class.getName()))); + assertFalse(isRxFunctionType(pool.get(Action.class.getName()))); + assertFalse(isRxFunctionType(pool.get(Action0.class.getName()))); + assertFalse(isRxFunctionType(pool.get(Action1.class.getName()))); + assertFalse(isRxFunctionType(pool.get(Action2.class.getName()))); + assertFalse(isRxFunctionType(pool.get(Action3.class.getName()))); + } catch (Exception e) { + fail(e.getMessage()); + } + } + + @Test + public void testIsRxActionType() { + try { + assertFalse(isRxActionType(pool.get(Function.class.getName()))); + assertFalse(isRxActionType(pool.get(Func0.class.getName()))); + assertFalse(isRxActionType(pool.get(Func1.class.getName()))); + assertFalse(isRxActionType(pool.get(Func2.class.getName()))); + assertFalse(isRxActionType(pool.get(Func3.class.getName()))); + assertFalse(isRxActionType(pool.get(Func4.class.getName()))); + assertFalse(isRxActionType(pool.get(Func5.class.getName()))); + assertFalse(isRxActionType(pool.get(Func6.class.getName()))); + assertFalse(isRxActionType(pool.get(Func7.class.getName()))); + assertFalse(isRxActionType(pool.get(Func8.class.getName()))); + assertFalse(isRxActionType(pool.get(Func9.class.getName()))); + assertTrue(isRxActionType(pool.get(Action.class.getName()))); + assertTrue(isRxActionType(pool.get(Action0.class.getName()))); + assertTrue(isRxActionType(pool.get(Action1.class.getName()))); + assertTrue(isRxActionType(pool.get(Action2.class.getName()))); + assertTrue(isRxActionType(pool.get(Action3.class.getName()))); + } catch (Exception e) { + fail(e.getMessage()); + } + } + } +} + diff --git a/language-adaptors/rxjava-clojure/build.gradle b/language-adaptors/rxjava-clojure/build.gradle index 0ea7feb27c..6fb4ea8c30 100644 --- a/language-adaptors/rxjava-clojure/build.gradle +++ b/language-adaptors/rxjava-clojure/build.gradle @@ -1,17 +1,14 @@ -apply plugin: 'java' apply plugin: 'clojure' -apply plugin: 'eclipse' -apply plugin: 'idea' apply plugin: 'osgi' dependencies { + core project(':rxjava-core') compile project(':rxjava-core') - provided 'org.clojure:clojure:1.4.+' + compile project(':language-adaptors:codegen') + compile 'org.clojure:clojure:1.4.+' + compile 'clj-http:clj-http:0.6.4' // https://clojars.org/clj-http provided 'junit:junit-dep:4.10' provided 'org.mockito:mockito-core:1.8.5' - - // clojure - testCompile 'clj-http:clj-http:0.6.4' // https://clojars.org/clj-http } /* @@ -26,57 +23,45 @@ buildscript { } repositories { - mavenCentral() clojarsRepo() } /* - * Add Counterclockwise and include 'provided' dependencies + * Add Counterclockwise to Eclipse */ eclipse { project { natures "ccw.nature" } - classpath { - plusConfigurations += configurations.provided - downloadSources = true - downloadJavadoc = true - } } -idea { - module { - // include 'provided' dependencies on the classpath - scopes.PROVIDED.plus += configurations.provided - } +task createAdaptedObservable(type: JavaExec) { + main = 'rx.codegen.ClassPathBasedRunner' + classpath = sourceSets.main.runtimeClasspath + args = ["Clojure", codeGenOutputDir] + + inputs.files(sourceSets.main.runtimeClasspath) + outputs.dir(codeGenOutputDir) } +tasks.test { + dependsOn(createAdaptedObservable) -eclipse { - classpath { - // include 'provided' dependencies on the classpath - plusConfigurations += configurations.provided - - downloadSources = true - downloadJavadoc = true - } + //Reorders the classpath so that the newly-create Observables win + classpath = createAdaptedObservable.outputs.files + sourceSets.test.runtimeClasspath } -// include /src/examples folder -sourceSets { - examples -} +tasks.jar { + dependsOn(createAdaptedObservable) -// make 'examples' use the same classpath -configurations { - examplesCompile.extendsFrom compile - examplesRuntime.extendsFrom runtime -} + from (zipTree(configurations.core.singleFile)) { + exclude "rx/Observable.class" + exclude "rx/observables/BlockingObservable.class" + } + from(codeGenOutputDir) -// include 'examples' in build task -build.dependsOn examplesClasses + exclude('**/*$UnitTest*') -jar { manifest { name = 'rxjava-clojure' instruction 'Bundle-Vendor', 'Netflix' @@ -84,4 +69,4 @@ jar { instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' instruction 'Fragment-Host', 'com.netflix.rxjava.core' } -} \ No newline at end of file +} diff --git a/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureActionWrapper.java b/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureActionWrapper.java new file mode 100644 index 0000000000..38d4dd64a8 --- /dev/null +++ b/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureActionWrapper.java @@ -0,0 +1,41 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.lang.clojure; + +import rx.util.functions.Action0; +import rx.util.functions.Action1; + +import clojure.lang.IFn; +import clojure.lang.RT; +import clojure.lang.Var; + +public class ClojureActionWrapper implements Action0, Action1 { + private IFn ifn; + + public ClojureActionWrapper(IFn ifn) { + this.ifn = ifn; + } + + @Override + public void call() { + ifn.invoke(); + } + + @Override + public void call(T1 t1) { + ifn.invoke(t1); + } +} \ No newline at end of file diff --git a/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureAdaptor.java b/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureAdaptor.java index 4420f7c919..31cff79786 100644 --- a/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureAdaptor.java +++ b/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureAdaptor.java @@ -15,7 +15,10 @@ */ package rx.lang.clojure; -import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import org.junit.Before; import org.junit.Test; @@ -32,57 +35,24 @@ public class ClojureAdaptor implements FunctionLanguageAdaptor { @Override - public Object call(Object function, Object[] args) { - if (args.length == 0) { - return ((IFn) function).invoke(); - } else if (args.length == 1) { - return ((IFn) function).invoke(args[0]); - } else if (args.length == 2) { - return ((IFn) function).invoke(args[0], args[1]); - } else if (args.length == 3) { - return ((IFn) function).invoke(args[0], args[1], args[2]); - } else if (args.length == 4) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3]); - } else if (args.length == 5) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4]); - } else if (args.length == 6) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5]); - } else if (args.length == 7) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - } else if (args.length == 8) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); - } else if (args.length == 9) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); - } else if (args.length == 10) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); - } else if (args.length == 11) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]); - } else if (args.length == 12) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]); - } else if (args.length == 13) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12]); - } else if (args.length == 14) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13]); - } else if (args.length == 15) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14]); - } else if (args.length == 16) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15]); - } else if (args.length == 17) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15], args[16]); - } else if (args.length == 18) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15], args[16], args[17]); - } else if (args.length == 19) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15], args[16], args[17], args[18]); - } else if (args.length == 20) { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15], args[16], args[17], args[18], args[19]); - } else { - return ((IFn) function).invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15], args[16], args[17], args[18], args[19], Arrays.copyOfRange(args, 20, args.length)); - } + public Map, Class> getFunctionClassRewritingMap() { + Map, Class> m = new HashMap, Class>(); + m.put(IFn.class, ClojureFunctionWrapper.class); + return m; + } + + @Override + public Map, Class> getActionClassRewritingMap() { + Map, Class> m = new HashMap, Class>(); + m.put(IFn.class, ClojureActionWrapper.class); + return m; } @Override - public Class[] getFunctionClass() { - return new Class[] { IFn.class }; + public Set> getAllClassesToRewrite() { + Set> classes = new HashSet>(); + classes.add(IFn.class); + return classes; } public static class UnitTest { diff --git a/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureFunctionWrapper.java b/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureFunctionWrapper.java new file mode 100644 index 0000000000..1aed83fc7e --- /dev/null +++ b/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureFunctionWrapper.java @@ -0,0 +1,58 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.lang.clojure; + +import rx.util.functions.Func0; +import rx.util.functions.Func1; +import rx.util.functions.Func2; +import rx.util.functions.Func3; +import rx.util.functions.Func4; +import rx.util.functions.FunctionLanguageAdaptor; + +import clojure.lang.IFn; + +public class ClojureFunctionWrapper implements Func0, Func1, Func2, Func3, Func4 { + private IFn ifn; + + public ClojureFunctionWrapper(IFn ifn) { + this.ifn = ifn; + } + + @Override + public R call() { + return (R) ifn.invoke(); + } + + @Override + public R call(T1 t1) { + return (R) ifn.invoke(t1); + } + + @Override + public R call(T1 t1, T2 t2) { + return (R) ifn.invoke(t1, t2); + } + + @Override + public R call(T1 t1, T2 t2, T3 t3) { + return (R) ifn.invoke(t1, t2, t3); + } + + @Override + public R call(T1 t1, T2 t2, T3 t3, T4 t4) { + return (R) ifn.invoke(t1, t2, t3, t4); + } +} \ No newline at end of file diff --git a/language-adaptors/rxjava-dynamic/build.gradle b/language-adaptors/rxjava-dynamic/build.gradle new file mode 100644 index 0000000000..18d03a8d9c --- /dev/null +++ b/language-adaptors/rxjava-dynamic/build.gradle @@ -0,0 +1,45 @@ +apply plugin: 'osgi' + +dependencies { + core project(':rxjava-core') + compile project(':rxjava-core') + compile project(':language-adaptors:codegen') + provided 'junit:junit-dep:4.10' + provided 'org.mockito:mockito-core:1.8.5' +} + +task createAdaptedObservable(type: JavaExec) { + main = 'rx.codegen.ClassPathBasedRunner' + classpath = sourceSets.main.runtimeClasspath + args = ["Dynamic", codeGenOutputDir] + + inputs.files(sourceSets.main.runtimeClasspath) + outputs.dir(codeGenOutputDir) +} + +tasks.test { + dependsOn(createAdaptedObservable) + + //Reorders the classpath so that the newly-create Observables win + classpath = createAdaptedObservable.outputs.files + sourceSets.test.runtimeClasspath +} + +tasks.jar { + dependsOn(createAdaptedObservable) + + from (zipTree(configurations.core.singleFile)) { + exclude "rx/Observable.class" + exclude "rx/observables/BlockingObservable.class" + } + from(codeGenOutputDir) + + exclude('**/*$UnitTest*') + + manifest { + name = 'rxjava-dynamic' + instruction 'Bundle-Vendor', 'Netflix' + instruction 'Bundle-DocURL', 'https://github.com/Netflix/RxJava' + instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' + instruction 'Fragment-Host', 'com.netflix.rxjava.core' + } +} diff --git a/language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicActionWrapper.java b/language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicActionWrapper.java new file mode 100644 index 0000000000..697176c80f --- /dev/null +++ b/language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicActionWrapper.java @@ -0,0 +1,38 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.lang.dynamic; + +import rx.util.functions.Action0; +import rx.util.functions.Action1; +import rx.util.functions.Functions; + +public class DynamicActionWrapper implements Action0, Action1 { + private Object object; + + public DynamicActionWrapper(Object object) { + this.object = object; + } + + @Override + public void call() { + Functions.from(object).call(); + } + + @Override + public void call(T1 t1) { + Functions.from(object).call(t1); + } +} \ No newline at end of file diff --git a/language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicAdaptor.java b/language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicAdaptor.java new file mode 100644 index 0000000000..636e0e54ea --- /dev/null +++ b/language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicAdaptor.java @@ -0,0 +1,48 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.lang.dynamic; + +import java.util.HashMap; +import java.util.Map; + +import rx.util.functions.FunctionLanguageAdaptor; + +import java.util.HashSet; +import java.util.Set; + +public class DynamicAdaptor implements FunctionLanguageAdaptor { + + @Override + public Map, Class> getFunctionClassRewritingMap() { + Map, Class> m = new HashMap, Class>(); + m.put(Object.class, DynamicFunctionWrapper.class); + return m; + } + + @Override + public Map, Class> getActionClassRewritingMap() { + Map, Class> m = new HashMap, Class>(); + m.put(Object.class, DynamicActionWrapper.class); + return m; + } + + @Override + public Set> getAllClassesToRewrite() { + Set> dynamicClasses = new HashSet>(); + dynamicClasses.add(Object.class); + return dynamicClasses; + } +} diff --git a/language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicFunctionWrapper.java b/language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicFunctionWrapper.java new file mode 100644 index 0000000000..897d9f8d81 --- /dev/null +++ b/language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicFunctionWrapper.java @@ -0,0 +1,57 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.lang.dynamic; + +import rx.util.functions.Func0; +import rx.util.functions.Func1; +import rx.util.functions.Func2; +import rx.util.functions.Func3; +import rx.util.functions.Func4; +import rx.util.functions.FunctionLanguageAdaptor; +import rx.util.functions.Functions; + +public class DynamicFunctionWrapper implements Func0, Func1, Func2, Func3, Func4 { + private Object object; + + public DynamicFunctionWrapper(Object object) { + this.object = object; + } + + @Override + public R call() { + return (R) Functions.from(object).call(); + } + + @Override + public R call(T1 t1) { + return (R) Functions.from(object).call(t1); + } + + @Override + public R call(T1 t1, T2 t2) { + return (R) Functions.from(object).call(t1, t2); + } + + @Override + public R call(T1 t1, T2 t2, T3 t3) { + return (R) Functions.from(object).call(t1, t2, t3); + } + + @Override + public R call(T1 t1, T2 t2, T3 t3, T4 t4) { + return (R) Functions.from(object).call(t1, t2, t3, t4); + } +} \ No newline at end of file diff --git a/language-adaptors/rxjava-groovy/build.gradle b/language-adaptors/rxjava-groovy/build.gradle index 91c060193d..edb9cb30ea 100644 --- a/language-adaptors/rxjava-groovy/build.gradle +++ b/language-adaptors/rxjava-groovy/build.gradle @@ -1,48 +1,42 @@ -apply plugin: 'java' apply plugin: 'groovy' -apply plugin: 'eclipse' -apply plugin: 'idea' apply plugin: 'osgi' dependencies { + core project(':rxjava-core') compile project(':rxjava-core') + compile project(':language-adaptors:codegen') groovy 'org.codehaus.groovy:groovy-all:2.+' provided 'junit:junit-dep:4.10' provided 'org.mockito:mockito-core:1.8.5' } -// include /src/examples folder -sourceSets { - examples +task createAdaptedObservable(type: JavaExec) { + main = 'rx.codegen.ClassPathBasedRunner' + classpath = sourceSets.main.runtimeClasspath + args = ["Groovy", codeGenOutputDir] + + inputs.files(sourceSets.main.runtimeClasspath) + outputs.dir(codeGenOutputDir) } -// make 'examples' use the same classpath -configurations { - examplesCompile.extendsFrom compile - examplesRuntime.extendsFrom runtime +tasks.test { + dependsOn(createAdaptedObservable) + + //Reorders the classpath so that the newly-create Observables win + classpath = createAdaptedObservable.outputs.files + sourceSets.test.runtimeClasspath } -// include 'examples' in build task -build.dependsOn examplesClasses +tasks.jar { + dependsOn(createAdaptedObservable) -eclipse { - classpath { - // include 'provided' dependencies on the classpath - plusConfigurations += configurations.provided - - downloadSources = true - downloadJavadoc = true + from (zipTree(configurations.core.singleFile)) { + exclude "rx/Observable.class" + exclude "rx/observables/BlockingObservable.class" } -} + from(codeGenOutputDir) -idea { - module { - // include 'provided' dependencies on the classpath - scopes.PROVIDED.plus += configurations.provided - } -} + exclude('**/*$UnitTest*') -jar { manifest { name = 'rxjava-groovy' instruction 'Bundle-Vendor', 'Netflix' @@ -50,4 +44,4 @@ jar { instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' instruction 'Fragment-Host', 'com.netflix.rxjava.core' } -} \ No newline at end of file +} diff --git a/language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyActionWrapper.java b/language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyActionWrapper.java new file mode 100644 index 0000000000..a831a0ed42 --- /dev/null +++ b/language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyActionWrapper.java @@ -0,0 +1,39 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.lang.groovy; + +import rx.util.functions.Action0; +import rx.util.functions.Action1; + +import groovy.lang.Closure; + +public class GroovyActionWrapper implements Action0, Action1 { + private Closure closure; + + public GroovyActionWrapper(Closure closure) { + this.closure = closure; + } + + @Override + public void call() { + closure.call(); + } + + @Override + public void call(T1 t1) { + closure.call(t1); + } +} \ No newline at end of file diff --git a/language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyAdaptor.java b/language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyAdaptor.java index 70cef9c18e..530a7d2d63 100644 --- a/language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyAdaptor.java +++ b/language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyAdaptor.java @@ -15,17 +15,36 @@ */ package rx.lang.groovy; -import groovy.lang.Closure; +import java.util.HashMap; +import java.util.Map; + import rx.util.functions.FunctionLanguageAdaptor; +import groovy.lang.Closure; + +import java.util.HashSet; +import java.util.Set; + public class GroovyAdaptor implements FunctionLanguageAdaptor { @Override - public Object call(Object function, Object[] args) { - return ((Closure) function).call(args); + public Map, Class> getFunctionClassRewritingMap() { + Map, Class> m = new HashMap, Class>(); + m.put(Closure.class, GroovyFunctionWrapper.class); + return m; } - public Class[] getFunctionClass() { - return new Class[] { Closure.class }; + @Override + public Map, Class> getActionClassRewritingMap() { + Map, Class> m = new HashMap, Class>(); + m.put(Closure.class, GroovyActionWrapper.class); + return m; + } + + @Override + public Set> getAllClassesToRewrite() { + Set> groovyClasses = new HashSet>(); + groovyClasses.add(Closure.class); + return groovyClasses; } } diff --git a/language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyFunctionWrapper.java b/language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyFunctionWrapper.java new file mode 100644 index 0000000000..1b038fd1ba --- /dev/null +++ b/language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyFunctionWrapper.java @@ -0,0 +1,58 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.lang.groovy; + +import rx.util.functions.Func0; +import rx.util.functions.Func1; +import rx.util.functions.Func2; +import rx.util.functions.Func3; +import rx.util.functions.Func4; +import rx.util.functions.FunctionLanguageAdaptor; + +import groovy.lang.Closure; + +public class GroovyFunctionWrapper implements Func0, Func1, Func2, Func3, Func4 { + private Closure closure; + + public GroovyFunctionWrapper(Closure closure) { + this.closure = closure; + } + + @Override + public R call() { + return (R) closure.call(); + } + + @Override + public R call(T1 t1) { + return (R) closure.call(t1); + } + + @Override + public R call(T1 t1, T2 t2) { + return (R) closure.call(t1, t2); + } + + @Override + public R call(T1 t1, T2 t2, T3 t3) { + return (R) closure.call(t1, t2, t3); + } + + @Override + public R call(T1 t1, T2 t2, T3 t3, T4 t4) { + return (R) closure.call(t1, t2, t3, t4); + } +} \ No newline at end of file diff --git a/language-adaptors/rxjava-jruby/build.gradle b/language-adaptors/rxjava-jruby/build.gradle index cf7d9533e2..d7a0d82d39 100644 --- a/language-adaptors/rxjava-jruby/build.gradle +++ b/language-adaptors/rxjava-jruby/build.gradle @@ -1,33 +1,41 @@ -apply plugin: 'java' -apply plugin: 'eclipse' -apply plugin: 'idea' apply plugin: 'osgi' dependencies { + core project(':rxjava-core') compile project(':rxjava-core') - provided 'org.jruby:jruby:1.6+' + compile project(':language-adaptors:codegen') + compile 'org.jruby:jruby:1.6+' provided 'junit:junit-dep:4.10' provided 'org.mockito:mockito-core:1.8.5' } -eclipse { - classpath { - // include 'provided' dependencies on the classpath - plusConfigurations += configurations.provided +task createAdaptedObservable(type: JavaExec) { + main = 'rx.codegen.ClassPathBasedRunner' + classpath = sourceSets.main.runtimeClasspath + args = ["JRuby", codeGenOutputDir] - downloadSources = true - downloadJavadoc = true - } + inputs.files(sourceSets.main.runtimeClasspath) + outputs.dir(codeGenOutputDir) } -idea { - module { - // include 'provided' dependencies on the classpath - scopes.PROVIDED.plus += configurations.provided - } +tasks.test { + dependsOn(createAdaptedObservable) + + //Reorders the classpath so that the newly-create Observables win + classpath = createAdaptedObservable.outputs.files + sourceSets.test.runtimeClasspath } -jar { +tasks.jar { + dependsOn(createAdaptedObservable) + + from (zipTree(configurations.core.singleFile)) { + exclude "rx/Observable.class" + exclude "rx/observables/BlockingObservable.class" + } + from(codeGenOutputDir) + + exclude('**/*$UnitTest*') + manifest { name = 'rxjava-jruby' instruction 'Bundle-Vendor', 'Netflix' diff --git a/language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyActionWrapper.java b/language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyActionWrapper.java new file mode 100644 index 0000000000..ada202eaf1 --- /dev/null +++ b/language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyActionWrapper.java @@ -0,0 +1,48 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.lang.jruby; + +import org.jruby.Ruby; +import org.jruby.RubyProc; +import org.jruby.javasupport.JavaEmbedUtils; +import org.jruby.runtime.builtin.IRubyObject; + +import rx.util.functions.Action0; +import rx.util.functions.Action1; +import rx.util.functions.FunctionLanguageAdaptor; + +public class JRubyActionWrapper implements Action0, Action1 { + private RubyProc proc; + + public JRubyActionWrapper(RubyProc proc) { + this.proc = proc; + } + + @Override + public void call() { + Ruby ruby = proc.getRuntime(); + IRubyObject[] rubyArgs = new IRubyObject[0]; + proc.getBlock().call(ruby.getCurrentContext(), rubyArgs); + } + + @Override + public void call(T1 t1) { + Ruby ruby = proc.getRuntime(); + IRubyObject[] rubyArgs = new IRubyObject[1]; + rubyArgs[0] = JavaEmbedUtils.javaToRuby(ruby, t1); + proc.getBlock().call(ruby.getCurrentContext(), rubyArgs); + } +} \ No newline at end of file diff --git a/language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyAdaptor.java b/language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyAdaptor.java index d66dc16acf..f210d64917 100644 --- a/language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyAdaptor.java +++ b/language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyAdaptor.java @@ -19,12 +19,13 @@ import static org.mockito.Mockito.*; import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; -import org.jruby.Ruby; import org.jruby.RubyProc; import org.jruby.embed.ScriptingContainer; -import org.jruby.javasupport.JavaEmbedUtils; -import org.jruby.runtime.builtin.IRubyObject; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -40,19 +41,24 @@ public class JRubyAdaptor implements FunctionLanguageAdaptor { @Override - public Object call(Object function, Object[] args) { - RubyProc rubyProc = ((RubyProc) function); - Ruby ruby = rubyProc.getRuntime(); - IRubyObject rubyArgs[] = new IRubyObject[args.length]; - for (int i = 0; i < args.length; i++) { - rubyArgs[i] = JavaEmbedUtils.javaToRuby(ruby, args[i]); - } - return rubyProc.getBlock().call(ruby.getCurrentContext(), rubyArgs); + public Map, Class> getFunctionClassRewritingMap() { + Map, Class> m = new HashMap, Class>(); + m.put(RubyProc.class, JRubyFunctionWrapper.class); + return m; } @Override - public Class[] getFunctionClass() { - return new Class[] { RubyProc.class }; + public Map, Class> getActionClassRewritingMap() { + Map, Class> m = new HashMap, Class>(); + m.put(RubyProc.class, JRubyActionWrapper.class); + return m; + } + + @Override + public Set> getAllClassesToRewrite() { + Set> classes = new HashSet>(); + classes.add(RubyProc.class); + return classes; } public static class UnitTest { diff --git a/language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyFunctionWrapper.java b/language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyFunctionWrapper.java new file mode 100644 index 0000000000..c3e78957cb --- /dev/null +++ b/language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyFunctionWrapper.java @@ -0,0 +1,70 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.lang.jruby; + +import org.jruby.Ruby; +import org.jruby.RubyProc; +import org.jruby.javasupport.JavaEmbedUtils; +import org.jruby.runtime.builtin.IRubyObject; + +import rx.util.functions.Func0; +import rx.util.functions.Func1; +import rx.util.functions.Func2; +import rx.util.functions.Func3; +import rx.util.functions.Func4; +import rx.util.functions.FunctionLanguageAdaptor; + +public class JRubyFunctionWrapper implements Func0, Func1, Func2, Func3, Func4 { + private RubyProc proc; + + public JRubyFunctionWrapper(RubyProc proc) { + this.proc = proc; + } + + @Override + public R call() { + return (R) callRubyProc(); + } + + @Override + public R call(T1 t1) { + return (R) callRubyProc(t1); + } + + @Override + public R call(T1 t1, T2 t2) { + return (R) callRubyProc(t1, t2); + } + + @Override + public R call(T1 t1, T2 t2, T3 t3) { + return (R) callRubyProc(t1, t2, t3); + } + + @Override + public R call(T1 t1, T2 t2, T3 t3, T4 t4) { + return (R) callRubyProc(t1, t2, t3, t4); + } + + private Object callRubyProc(Object... args) { + Ruby ruby = proc.getRuntime(); + IRubyObject[] rubyArgs = new IRubyObject[args.length]; + for (int i = 0; i < args.length; i++) { + rubyArgs[i] = JavaEmbedUtils.javaToRuby(ruby, args[i]); + } + return (R) proc.getBlock().call(ruby.getCurrentContext(), rubyArgs); + } +} \ No newline at end of file diff --git a/language-adaptors/rxjava-scala/build.gradle b/language-adaptors/rxjava-scala/build.gradle index 43704248d6..be61f1d846 100644 --- a/language-adaptors/rxjava-scala/build.gradle +++ b/language-adaptors/rxjava-scala/build.gradle @@ -1,11 +1,10 @@ apply plugin: 'scala' -apply plugin: 'eclipse' -apply plugin: 'idea' apply plugin: 'osgi' tasks.withType(ScalaCompile) { scalaCompileOptions.fork = true scalaCompileOptions.unchecked = true + scalaCompileOptions.setAdditionalParameters(['-feature']) configure(scalaCompileOptions.forkOptions) { memoryMaximumSize = '1g' @@ -13,46 +12,35 @@ tasks.withType(ScalaCompile) { } } +sourceSets { + test { + scala { + srcDir 'src/main/scala' + } + } +} + dependencies { // Scala compiler and related tools - scalaTools 'org.scala-lang:scala-compiler:2.10+' - scalaTools 'org.scala-lang:scala-library:2.10+' - provided 'org.scalatest:scalatest_2.10:1.9.1' + compile 'org.scala-lang:scala-compiler:2.10+' + compile 'org.scala-lang:scala-library:2.10+' compile project(':rxjava-core') - provided 'junit:junit-dep:4.10' - provided 'org.mockito:mockito-core:1.8.5' - - testCompile 'org.scalatest:scalatest_2.10:1.9.1' + compile 'junit:junit-dep:4.10' + compile 'org.mockito:mockito-core:1.8.5' + compile 'org.scalatest:scalatest_2.10:1.9.1' } task test(overwrite: true, dependsOn: testClasses) << { ant.taskdef(name: 'scalatest', classname: 'org.scalatest.tools.ScalaTestAntTask', - classpath: sourceSets.test.runtimeClasspath.asPath + classpath: configurations.testRuntime.asPath + ':' + compileScala.destinationDir ) - ant.scalatest(runpath: sourceSets.test.classesDir, + ant.scalatest(runpath: sourceSets.test.output.classesDir, haltonfailure: 'true', fork: 'false') {reporter(type: 'stdout')} } -eclipse { - classpath { - // include 'provided' dependencies on the classpath - plusConfigurations += configurations.provided - - downloadSources = true - downloadJavadoc = true - } -} - -idea { - module { - // include 'provided' dependencies on the classpath - scopes.PROVIDED.plus += configurations.provided - } -} - jar { manifest { name = 'rxjava-scala' diff --git a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/RxImplicits.scala b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/RxImplicits.scala new file mode 100644 index 0000000000..56f9ab679e --- /dev/null +++ b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/RxImplicits.scala @@ -0,0 +1,592 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package rx.lang.scala + +object RxImplicits { + import java.{ lang => jlang } + import language.implicitConversions + + import rx.Observable + import rx.observables.BlockingObservable + import rx.util.functions._ + + /** + * Converts 0-arg function to Rx Action0 + */ + implicit def scalaFunction0ProducingUnitToAction0(f: (() => Unit)): Action0 = + new Action0 { + def call(): Unit = f() + } + + /** + * Converts 1-arg function to Rx Action1 + */ + implicit def scalaFunction1ProducingUnitToAction1[A](f: (A => Unit)): Action1[A] = + new Action1[A] { + def call(a: A): Unit = f(a) + } + + /** + * Converts 1-arg predicate to Rx Func1[A, java.lang.Boolean] + */ + implicit def scalaBooleanFunction1ToRxBooleanFunc1[A](f: (A => Boolean)): Func1[A, jlang.Boolean] = + new Func1[A, jlang.Boolean] { + def call(a: A): jlang.Boolean = f(a).booleanValue + } + + /** + * Converts a specific function shape (used in takeWhile) to the equivalent Java types with an Rx Func2 + */ + implicit def convertTakeWhileFuncToRxFunc2[A](f: (A, Int) => Boolean): Func2[A, jlang.Integer, jlang.Boolean] = + new Func2[A, jlang.Integer, jlang.Boolean] { + def call(a: A, b: jlang.Integer): jlang.Boolean = f(a, b).booleanValue + } + + /** + * Converts a function shaped ilke compareTo into the equivalent Rx Func2 + */ + implicit def convertComparisonFuncToRxFunc2[A](f: (A, A) => Int): Func2[A, A, jlang.Integer] = + new Func2[A, A, jlang.Integer] { + def call(a1: A, a2: A): jlang.Integer = f(a1, a2).intValue + } + + /* + * This implicit allows Scala code to use any exception type and still work + * with invariant Func1 interface + */ + implicit def exceptionFunction1ToRxExceptionFunc1[A <: Exception, B](f: (A => B)): Func1[Exception, B] = + new Func1[Exception, B] { + def call(ex: Exception): B = f(ex.asInstanceOf[A]) + } + + /** + * The following implicits convert functions of different arities into the Rx equivalents + */ + implicit def scalaFunction0ToRxFunc0[A](f: () => A): Func0[A] = + new Func0[A] { + def call(): A = f() + } + + implicit def scalaFunction1ToRxFunc1[A, B](f: (A => B)): Func1[A, B] = + new Func1[A, B] { + def call(a: A): B = f(a) + } + + implicit def scalaFunction2ToRxFunc2[A, B, C](f: (A, B) => C): Func2[A, B, C] = + new Func2[A, B, C] { + def call(a: A, b: B) = f(a, b) + } + + implicit def scalaFunction3ToRxFunc3[A, B, C, D](f: (A, B, C) => D): Func3[A, B, C, D] = + new Func3[A, B, C, D] { + def call(a: A, b: B, c: C) = f(a, b, c) + } + + implicit def scalaFunction4ToRxFunc4[A, B, C, D, E](f: (A, B, C, D) => E): Func4[A, B, C, D, E] = + new Func4[A, B, C, D, E] { + def call(a: A, b: B, c: C, d: D) = f(a, b, c, d) + } + + /** + * This implicit class implements all of the methods necessary for including Observables in a + * for-comprehension. Note that return type is always Observable, so that the ScalaObservable + * type never escapes the for-comprehension + */ + implicit class ScalaObservable[A](wrapped: Observable[A]) { + def map[B](f: A => B): Observable[B] = wrapped.map(f) + def flatMap[B](f: A => Observable[B]): Observable[B] = wrapped.mapMany(f) + def foreach(f: A => Unit): Unit = wrapped.toBlockingObservable.forEach(f) + def withFilter(p: A => Boolean): WithFilter = new WithFilter(p) + + class WithFilter(p: A => Boolean) { + def map[B](f: A => B): Observable[B] = wrapped.filter(p).map(f) + def flatMap[B](f: A => Observable[B]): Observable[B] = wrapped.filter(p).flatMap(f) + def foreach(f: A => Unit): Unit = wrapped.filter(p).toBlockingObservable.forEach(f) + def withFilter(p: A => Boolean): Observable[A] = wrapped.filter(p) + } + } +} + +import org.scalatest.junit.JUnitSuite + +class UnitTestSuite extends JUnitSuite { + import rx.lang.scala.RxImplicits._ + + import org.junit.{ Before, Test } + import org.junit.Assert._ + import org.mockito.Matchers.any + import org.mockito.Mockito._ + import org.mockito.{ MockitoAnnotations, Mock } + import rx.{ Notification, Observer, Observable, Subscription } + import rx.observables.GroupedObservable + import collection.mutable.ArrayBuffer + import collection.JavaConverters._ + + @Mock private[this] + val observer: Observer[Any] = null + + @Mock private[this] + val subscription: Subscription = null + + val isOdd = (i: Int) => i % 2 == 1 + val isEven = (i: Int) => i % 2 == 0 + + class ObservableWithException(s: Subscription, values: String*) extends Observable[String] { + var t: Thread = null + + override def subscribe(observer: Observer[String]): Subscription = { + println("ObservableWithException subscribed to ...") + t = new Thread(new Runnable() { + override def run() { + try { + println("running ObservableWithException thread") + values.toList.foreach(v => { + println("ObservableWithException onNext: " + v) + observer.onNext(v) + }) + throw new RuntimeException("Forced Failure") + } catch { + case ex: Exception => observer.onError(ex) + } + } + }) + println("starting ObservableWithException thread") + t.start() + println("done starting ObservableWithException thread") + s + } + } + + @Before def before { + MockitoAnnotations.initMocks(this) + } + + // tests of static methods + + @Test def testSingle { + assertEquals(1, Observable.from(1).toBlockingObservable.single) + } + + @Test def testSinglePredicate { + val found = Observable.from(1, 2, 3).toBlockingObservable.single(isEven) + assertEquals(2, found) + } + + @Test def testSingleOrDefault { + assertEquals(0, Observable.from[Int]().toBlockingObservable.singleOrDefault(0)) + assertEquals(1, Observable.from(1).toBlockingObservable.singleOrDefault(0)) + try { + Observable.from(1, 2, 3).toBlockingObservable.singleOrDefault(0) + fail("Did not catch any exception, expected IllegalStateException") + } catch { + case ex: IllegalStateException => println("Caught expected IllegalStateException") + case ex: Throwable => fail("Caught unexpected exception " + ex.getCause + ", expected IllegalStateException") + } + } + + @Test def testSingleOrDefaultPredicate { + assertEquals(2, Observable.from(1, 2, 3).toBlockingObservable.singleOrDefault(0, isEven)) + assertEquals(0, Observable.from(1, 3).toBlockingObservable.singleOrDefault(0, isEven)) + try { + Observable.from(1, 2, 3).toBlockingObservable.singleOrDefault(0, isOdd) + fail("Did not catch any exception, expected IllegalStateException") + } catch { + case ex: IllegalStateException => println("Caught expected IllegalStateException") + case ex: Throwable => fail("Caught unexpected exception " + ex.getCause + ", expected IllegalStateException") + } + } + + @Test def testFromJavaInterop { + val observable = Observable.from(List(1, 2, 3).asJava) + assertSubscribeReceives(observable)(1, 2, 3) + } + + @Test def testSubscribe { + val observable = Observable.from("1", "2", "3") + assertSubscribeReceives(observable)("1", "2", "3") + } + + //should not compile - adapted from https://gist.github.com/jmhofer/5195589 + /*@Test def testSubscribeOnInt() { + val observable = Observable.from("1", "2", "3") + observable.subscribe((arg: Int) => { + println("testSubscribe: arg = " + arg) + }) + }*/ + + @Test def testDefer { + val lazyObservableFactory = () => Observable.from(1, 2) + val observable = Observable.defer(lazyObservableFactory) + assertSubscribeReceives(observable)(1, 2) + } + + @Test def testJust { + val observable = Observable.just("foo") + assertSubscribeReceives(observable)("foo") + } + + @Test def testMerge { + val observable1 = Observable.from(1, 2, 3) + val observable2 = Observable.from(4, 5, 6) + val observableList = List(observable1, observable2).asJava + val merged = Observable.merge(observableList) + assertSubscribeReceives(merged)(1, 2, 3, 4, 5, 6) + } + + @Test def testFlattenMerge { + val observable = Observable.from(Observable.from(1, 2, 3)) + val merged = Observable.merge(observable) + assertSubscribeReceives(merged)(1, 2, 3) + } + + @Test def testSequenceMerge { + val observable1 = Observable.from(1, 2, 3) + val observable2 = Observable.from(4, 5, 6) + val merged = Observable.merge(observable1, observable2) + assertSubscribeReceives(merged)(1, 2, 3, 4, 5, 6) + } + + @Test def testConcat { + val observable1 = Observable.from(1, 2, 3) + val observable2 = Observable.from(4, 5, 6) + val concatenated = Observable.concat(observable1, observable2) + assertSubscribeReceives(concatenated)(1, 2, 3, 4, 5, 6) + } + + @Test def testSynchronize { + val observable = Observable.from(1, 2, 3) + val synchronized = Observable.synchronize(observable) + assertSubscribeReceives(synchronized)(1, 2, 3) + } + + @Test def testZip3() { + val numbers = Observable.from(1, 2, 3) + val colors = Observable.from("red", "green", "blue") + val names = Observable.from("lion-o", "cheetara", "panthro") + + case class Character(id: Int, color: String, name: String) + + val liono = Character(1, "red", "lion-o") + val cheetara = Character(2, "green", "cheetara") + val panthro = Character(3, "blue", "panthro") + + val characters = Observable.zip(numbers, colors, names, Character.apply _) + assertSubscribeReceives(characters)(liono, cheetara, panthro) + } + + @Test def testZip4() { + val numbers = Observable.from(1, 2, 3) + val colors = Observable.from("red", "green", "blue") + val names = Observable.from("lion-o", "cheetara", "panthro") + val isLeader = Observable.from(true, false, false) + + case class Character(id: Int, color: String, name: String, isLeader: Boolean) + + val liono = Character(1, "red", "lion-o", true) + val cheetara = Character(2, "green", "cheetara", false) + val panthro = Character(3, "blue", "panthro", false) + + val characters = Observable.zip(numbers, colors, names, isLeader, Character.apply _) + assertSubscribeReceives(characters)(liono, cheetara, panthro) + } + + //tests of instance methods + + // missing tests for : takeUntil, groupBy, next, mostRecent + + @Test def testFilter { + val numbers = Observable.from(1, 2, 3, 4, 5, 6, 7, 8, 9) + val observable = numbers.filter(isEven) + assertSubscribeReceives(observable)(2, 4, 6, 8) + } + + @Test def testLast { + val observable = Observable.from(1, 2, 3, 4).toBlockingObservable + assertEquals(4, observable.toBlockingObservable.last) + } + + @Test def testLastPredicate { + val observable = Observable.from(1, 2, 3, 4) + assertEquals(3, observable.toBlockingObservable.last(isOdd)) + } + + @Test def testLastOrDefault { + val observable = Observable.from(1, 2, 3, 4) + assertEquals(4, observable.toBlockingObservable.lastOrDefault(5)) + assertEquals(5, Observable.from[Int]().toBlockingObservable.lastOrDefault(5)) + } + + @Test def testLastOrDefaultPredicate { + val observable = Observable.from(1, 2, 3, 4) + assertEquals(3, observable.toBlockingObservable.lastOrDefault(5, isOdd)) + assertEquals(5, Observable.from[Int]().toBlockingObservable.lastOrDefault(5, isOdd)) + } + + @Test def testMap { + val numbers = Observable.from(1, 2, 3, 4, 5, 6, 7, 8, 9) + val mappedNumbers = ArrayBuffer.empty[Int] + numbers.map((x: Int) => x * x).subscribe((squareVal: Int) => { + mappedNumbers.append(squareVal) + }) + assertEquals(List(1, 4, 9, 16, 25, 36, 49, 64, 81), mappedNumbers.toList) + } + + @Test def testMapMany { + val numbers = Observable.from(1, 2, 3, 4) + val f = (i: Int) => Observable.from(List(i, -i).asJava) + val mappedNumbers = ArrayBuffer.empty[Int] + numbers.mapMany(f).subscribe((i: Int) => { + mappedNumbers.append(i) + }) + assertEquals(List(1, -1, 2, -2, 3, -3, 4, -4), mappedNumbers.toList) + } + + @Test def testMaterialize { + val observable = Observable.from(1, 2, 3, 4) + val expectedNotifications: List[Notification[Int]] = + ((1.to(4).map(i => new Notification(i))) :+ new Notification()).toList + val actualNotifications: ArrayBuffer[Notification[Int]] = ArrayBuffer.empty + observable.materialize.subscribe((n: Notification[Int]) => { + actualNotifications.append(n) + }) + assertEquals(expectedNotifications, actualNotifications.toList) + } + + @Test def testDematerialize { + val notifications: List[Notification[Int]] = + ((1.to(4).map(i => new Notification(i))) :+ new Notification()).toList + val observableNotifications: Observable[Notification[Int]] = + Observable.from(notifications.asJava) + val observable: Observable[Int] = + observableNotifications.dematerialize() + assertSubscribeReceives(observable)(1, 2, 3, 4) + } + + @Test def testOnErrorResumeNextObservableNoError { + val observable = Observable.from(1, 2, 3, 4) + val resumeObservable = Observable.from(5, 6, 7, 8) + val observableWithErrorHandler = observable.onErrorResumeNext(resumeObservable) + assertSubscribeReceives(observableWithErrorHandler)(1, 2, 3, 4) + } + + @Test def testOnErrorResumeNextObservableErrorOccurs { + val observable = new ObservableWithException(subscription, "foo", "bar") + val resumeObservable = Observable.from("a", "b", "c", "d") + val observableWithErrorHandler = observable.onErrorResumeNext(resumeObservable) + observableWithErrorHandler.subscribe(observer.asInstanceOf[Observer[String]]) + + try { + observable.t.join() + } catch { + case ex: InterruptedException => fail(ex.getMessage) + } + + List("foo", "bar", "a", "b", "c", "d").foreach(t => verify(observer, times(1)).onNext(t)) + verify(observer, never()).onError(any(classOf[Exception])) + verify(observer, times(1)).onCompleted() + } + + @Test def testOnErrorResumeNextFuncNoError { + val observable = Observable.from(1, 2, 3, 4) + val resumeFunc = (ex: RuntimeException) => Observable.from(5, 6, 7, 8) + val observableWithErrorHandler = observable.onErrorResumeNext(resumeFunc) + assertSubscribeReceives(observableWithErrorHandler)(1, 2, 3, 4) + } + + @Test def testOnErrorResumeNextFuncErrorOccurs { + val observable = new ObservableWithException(subscription, "foo", "bar") + val resumeFunc = (ex: RuntimeException) => Observable.from("a", "b", "c", "d") + val observableWithErrorHandler = observable.onErrorResumeNext(resumeFunc) + observableWithErrorHandler.subscribe(observer.asInstanceOf[Observer[String]]) + + try { + observable.t.join() + } catch { + case ex: InterruptedException => fail(ex.getMessage) + } + + List("foo", "bar", "a", "b", "c", "d").foreach(t => verify(observer, times(1)).onNext(t)) + verify(observer, never()).onError(any(classOf[Exception])) + verify(observer, times(1)).onCompleted() + } + + @Test def testOnErrorReturnFuncNoError { + val observable = Observable.from(1, 2, 3, 4) + val returnFunc = (ex: RuntimeException) => 87 + val observableWithErrorHandler = observable.onErrorReturn(returnFunc) + assertSubscribeReceives(observableWithErrorHandler)(1, 2, 3, 4) + } + + @Test def testOnErrorReturnFuncErrorOccurs { + val observable = new ObservableWithException(subscription, "foo", "bar") + val returnFunc = (ex: RuntimeException) => "baz" + val observableWithErrorHandler = observable.onErrorReturn(returnFunc) + observableWithErrorHandler.subscribe(observer.asInstanceOf[Observer[String]]) + + try { + observable.t.join() + } catch { + case ex: InterruptedException => fail(ex.getMessage) + } + + List("foo", "bar", "baz").foreach(t => verify(observer, times(1)).onNext(t)) + verify(observer, never()).onError(any(classOf[Exception])) + verify(observer, times(1)).onCompleted() + } + + @Test def testReduce { + val observable = Observable.from(1, 2, 3, 4) + assertEquals(10, observable.reduce((a: Int, b: Int) => a + b).toBlockingObservable.single) + } + + @Test def testSkip { + val observable = Observable.from(1, 2, 3, 4) + val skipped = observable.skip(2) + assertSubscribeReceives(skipped)(3, 4) + } + + /** + * Both testTake and testTakeWhileWithIndex exposed a bug with unsubscribes not properly propagating. + * observable.take(2) produces onNext(first), onNext(second), and 4 onCompleteds + * it should produce onNext(first), onNext(second), and 1 onCompleted + * + * Switching to Observable.create(OperationTake.take(observable, 2)) works as expected + */ + @Test def testTake { + import rx.operators._ + + val observable = Observable.from(1, 2, 3, 4, 5) + val took = Observable.create(OperationTake.take(observable, 2)) + assertSubscribeReceives(took)(1, 2) + } + + @Test def testTakeWhile { + val observable = Observable.from(1, 3, 5, 6, 7, 9, 11) + val took = observable.takeWhile(isOdd) + assertSubscribeReceives(took)(1, 3, 5) + } + + /*@Test def testTakeWhileWithIndex { + val observable = Observable.from(1, 3, 5, 6, 7, 9, 11, 12, 13, 15, 17) + val took = observable.takeWhileWithIndex((i: Int, idx: Int) => isOdd(i) && idx > 4) + assertSubscribeReceives(took)(9, 11) + }*/ + + @Test def testTakeLast { + val observable = Observable.from(1, 2, 3, 4, 5, 6, 7, 8, 9) + val tookLast = observable.takeLast(3) + assertSubscribeReceives(tookLast)(7, 8, 9) + } + + @Test def testToList { + val observable = Observable.from(1, 2, 3, 4) + val toList = observable.toList + assertSubscribeReceives(toList)(List(1, 2, 3, 4).asJava) + } + + @Test def testToSortedList { + val observable = Observable.from(1, 3, 4, 2) + val toSortedList = observable.toSortedList + assertSubscribeReceives(toSortedList)(List(1, 2, 3, 4).asJava) + } + + @Test def testToArbitrarySortedList { + val observable = Observable.from("a", "aaa", "aaaa", "aa") + val sortByLength = (s1: String, s2: String) => s1.length.compareTo(s2.length) + val toSortedList = observable.toSortedList(sortByLength) + assertSubscribeReceives(toSortedList)(List("a", "aa", "aaa", "aaaa").asJava) + } + + @Test def testToIterable { + val observable = Observable.from(1, 2) + val it = observable.toBlockingObservable.toIterable.iterator + assertTrue(it.hasNext) + assertEquals(1, it.next) + assertTrue(it.hasNext) + assertEquals(2, it.next) + assertFalse(it.hasNext) + } + + @Test def testStartWith { + val observable = Observable.from(1, 2, 3, 4) + val newStart = observable.startWith(-1, 0) + assertSubscribeReceives(newStart)(-1, 0, 1, 2, 3, 4) + } + + @Test def testOneLineForComprehension { + val mappedObservable = for { + i: Int <- Observable.from(1, 2, 3, 4) + } yield i + 1 + assertSubscribeReceives(mappedObservable)(2, 3, 4, 5) + assertFalse(mappedObservable.isInstanceOf[ScalaObservable[_]]) + } + + @Test def testSimpleMultiLineForComprehension { + val flatMappedObservable = for { + i: Int <- Observable.from(1, 2, 3, 4) + j: Int <- Observable.from(1, 10, 100, 1000) + } yield i + j + assertSubscribeReceives(flatMappedObservable)(2, 12, 103, 1004) + assertFalse(flatMappedObservable.isInstanceOf[ScalaObservable[_]]) + } + + @Test def testMultiLineForComprehension { + val doubler = (i: Int) => Observable.from(i, i) + val flatMappedObservable = for { + i: Int <- Observable.from(1, 2, 3, 4) + j: Int <- doubler(i) + } yield j + //can't use assertSubscribeReceives since each number comes in 2x + flatMappedObservable.subscribe(observer.asInstanceOf[Observer[Int]]) + List(1, 2, 3, 4).foreach(i => verify(observer, times(2)).onNext(i)) + verify(observer, never()).onError(any(classOf[Exception])) + verify(observer, times(1)).onCompleted() + assertFalse(flatMappedObservable.isInstanceOf[ScalaObservable[_]]) + } + + @Test def testFilterInForComprehension { + val doubler = (i: Int) => Observable.from(i, i) + val filteredObservable = for { + i: Int <- Observable.from(1, 2, 3, 4) + j: Int <- doubler(i) if isOdd(i) + } yield j + //can't use assertSubscribeReceives since each number comes in 2x + filteredObservable.subscribe(observer.asInstanceOf[Observer[Int]]) + List(1, 3).foreach(i => verify(observer, times(2)).onNext(i)) + verify(observer, never()).onError(any(classOf[Exception])) + verify(observer, times(1)).onCompleted() + assertFalse(filteredObservable.isInstanceOf[ScalaObservable[_]]) + } + + @Test def testForEachForComprehension { + val doubler = (i: Int) => Observable.from(i, i) + val intBuffer = ArrayBuffer.empty[Int] + val forEachComprehension = for { + i: Int <- Observable.from(1, 2, 3, 4) + j: Int <- doubler(i) if isEven(i) + } { + intBuffer.append(j) + } + assertEquals(List(2, 2, 4, 4), intBuffer.toList) + } + + private def assertSubscribeReceives[T](o: Observable[T])(values: T*) = { + o.subscribe(observer.asInstanceOf[Observer[T]]) + values.toList.foreach(t => verify(observer, times(1)).onNext(t)) + verify(observer, never()).onError(any(classOf[Exception])) + verify(observer, times(1)).onCompleted() + } +} diff --git a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/ScalaAdaptor.scala b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/ScalaAdaptor.scala deleted file mode 100644 index 12418d516d..0000000000 --- a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/ScalaAdaptor.scala +++ /dev/null @@ -1,204 +0,0 @@ -/** - * Copyright 2013 Netflix, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package rx.lang.scala - -import rx.util.functions.FunctionLanguageAdaptor -import org.junit.{Assert, Before, Test} -import rx.Observable -import org.scalatest.junit.JUnitSuite -import org.mockito.Mockito._ -import org.mockito.{MockitoAnnotations, Mock} - -import scala.collection.JavaConverters._ -import collection.mutable.ArrayBuffer - -class ScalaAdaptor extends FunctionLanguageAdaptor { - - val ON_NEXT = "onNext" - val ON_ERROR = "onError" - val ON_COMPLETED = "onCompleted" - - def getFunctionClass: Array[Class[_]] = { - return Array(classOf[Map[String, _]], classOf[(AnyRef) => Object], classOf[(AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef) => Object], classOf[(AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) =>Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object], - classOf[(AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object]) - } - - def call(function: AnyRef, args: Array[AnyRef]) : Object = { - function match { - case (func: Map[String, _]) => return matchOption(func.get(ON_NEXT), args) - case _ => return matchFunction(function, args) - } - } - - private def matchOption(funcOption: Option[_], args: Array[AnyRef]) : Object = { - funcOption match { - case Some(func: AnyRef) => return matchFunction(func, args) - case _ => return None - } - } - - private def matchFunction(function: AnyRef, args: Array[AnyRef]) : Object = function match { - case (f: ((AnyRef) => Object)) => return f(args(0)) - case (f: ((AnyRef, AnyRef) => Object)) => return f(args(0), args(1)) - case (f: ((AnyRef, AnyRef, AnyRef) => Object)) => return f(args(0), args(1), args(2)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11), args(12)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11), args(12), args(13)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11), args(12), args(13), args(14)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11), args(12), args(13), args(14), args(15)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11), args(12), args(13), args(14), args(15), args(16)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11), args(12), args(13), args(14), args(15), args(16), args(17)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11), args(12), args(13), args(14), args(15), args(16), args(17), args(18)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11), args(12), args(13), args(14), args(15), args(16), args(17), args(18), args(19)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11), args(12), args(13), args(14), args(15), args(16), args(17), args(18), args(19), args(20)) - case (f: ((AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef, AnyRef) => Object)) => - return f(args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9), args(10), args(11), args(12), args(13), args(14), args(15), args(16), args(17), args(18), args(19), args(20), args(21)) - - } -} - -class UnitTestSuite extends JUnitSuite { - @Mock private[this] - val assertion: ScriptAssertion = null - - @Before def before { - MockitoAnnotations.initMocks(this) - } - - @Test def testTake() { - Observable.from("1", "2", "3").take(1).subscribe(Map( - "onNext" -> ((callback: String) => { - print("testTake: callback = " + callback) - assertion.received(callback) - }) - )) - verify(assertion, times(1)).received("1") - } - - @Test def testClosureVersusMap() { - // using closure - Observable.from("1", "2", "3") - .take(2) - .subscribe((callback: String) => { - println(callback) - }) - - // using Map of closures - Observable.from("1", "2", "3") - .take(2) - .subscribe(Map( - "onNext" -> ((callback: String) => { - println(callback) - }))) - } - - @Test def testFilterWithToList() { - val numbers = Observable.from[Int](1, 2, 3, 4, 5, 6, 7, 8, 9) - numbers.filter((x: Int) => 0 == (x % 2)).toList().subscribe( - (callback: java.util.List[Int]) => { - val lst = callback.asScala.toList - println("filter onNext -> got " + lst) - assertion.received(lst) - } - ) - verify(assertion, times(1)).received(List(2,4,6,8)) - } - - @Test def testTakeLast() { - val numbers = Observable.from[Int](1, 2, 3, 4, 5, 6, 7, 8, 9) - numbers.takeLast(1).subscribe((callback: Int) => { - println("testTakeLast: onNext -> got " + callback) - assertion.received(callback) - }) - verify(assertion, times(1)).received(9) - } - - @Test def testMap() { - val numbers = Observable.from(1, 2, 3, 4, 5, 6, 7, 8, 9) - val mappedNumbers = new ArrayBuffer[Int]() - numbers.map(((x: Int)=> { x * x })).subscribe(((squareVal: Int) => { - println("square is " + squareVal ) - mappedNumbers += squareVal - })) - Assert.assertEquals(List(1,4,9,16,25,36,49,64,81), mappedNumbers.toList) - - } - - @Test def testZip() { - val numbers = Observable.from(1, 2, 3) - val colors = Observable.from("red", "green", "blue") - val characters = Observable.from("lion-o", "cheetara", "panthro") - - Observable.zip(numbers.toList, colors.toList, characters.toList, ((n: java.util.List[Int], c: java.util.List[String], t: java.util.List[String]) => { Map( - "numbers" -> n, - "colors" -> c, - "thundercats" -> t - )})).subscribe((m: Map[String, _]) => { - println("zipped map is " + m.toString()) - }) - - - } - - trait ScriptAssertion { - def error(ex: Exception) - - def received(obj: Any) - } -} diff --git a/rxjava-contrib/rxjava-swing/build.gradle b/rxjava-contrib/rxjava-swing/build.gradle index 986f7ca6b9..0076915eee 100644 --- a/rxjava-contrib/rxjava-swing/build.gradle +++ b/rxjava-contrib/rxjava-swing/build.gradle @@ -1,6 +1,3 @@ -apply plugin: 'java' -apply plugin: 'eclipse' -apply plugin: 'idea' apply plugin: 'osgi' sourceCompatibility = JavaVersion.VERSION_1_6 @@ -12,23 +9,6 @@ dependencies { provided 'org.mockito:mockito-core:1.8.5' } -eclipse { - classpath { - // include 'provided' dependencies on the classpath - plusConfigurations += configurations.provided - - downloadSources = true - downloadJavadoc = true - } -} - -idea { - module { - // include 'provided' dependencies on the classpath - scopes.PROVIDED.plus += configurations.provided - } -} - javadoc { options { doclet = "org.benjchristensen.doclet.DocletExclude" @@ -40,6 +20,8 @@ javadoc { } jar { + exclude('**/*$UnitTest*') + manifest { name = 'rxjava-swing' instruction 'Bundle-Vendor', 'Netflix' diff --git a/rxjava-core/build.gradle b/rxjava-core/build.gradle index 72a984c88d..39232193e8 100644 --- a/rxjava-core/build.gradle +++ b/rxjava-core/build.gradle @@ -11,23 +11,6 @@ dependencies { provided 'org.mockito:mockito-core:1.8.5' } -eclipse { - classpath { - // include 'provided' dependencies on the classpath - plusConfigurations += configurations.provided - - downloadSources = true - downloadJavadoc = true - } -} - -idea { - module { - // include 'provided' dependencies on the classpath - scopes.PROVIDED.plus += configurations.provided - } -} - javadoc { // we do not want the org.rx.operations package include exclude '**/operations/**' @@ -48,7 +31,4 @@ jar { instruction 'Bundle-DocURL', 'https://github.com/Netflix/RxJava' instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' } - // commenting out for now as it's breaking the rxjava-scala build and I can't figure out why - // exclude('**/*$UnitTest*') } - diff --git a/rxjava-core/src/main/java/rx/Observable.java b/rxjava-core/src/main/java/rx/Observable.java index 0110f375d5..cfa21e5ec2 100644 --- a/rxjava-core/src/main/java/rx/Observable.java +++ b/rxjava-core/src/main/java/rx/Observable.java @@ -96,7 +96,6 @@ import rx.util.functions.Func4; import rx.util.functions.FuncN; import rx.util.functions.Function; -import rx.util.functions.FunctionLanguageAdaptor; import rx.util.functions.Functions; /** @@ -117,7 +116,7 @@ */ public class Observable { -//TODO use a consistent parameter naming scheme (for example: for all operators that modify a source Observable, the parameter representing that source Observable should have the same name, e.g. "source" -- currently such parameters are named any of "sequence", "that", "source", "items", or "observable") + //TODO use a consistent parameter naming scheme (for example: for all operators that modify a source Observable, the parameter representing that source Observable should have the same name, e.g. "source" -- currently such parameters are named any of "sequence", "that", "source", "items", or "observable") private final static RxJavaObservableExecutionHook hook = RxJavaPlugins.getInstance().getObservableExecutionHook(); @@ -151,8 +150,7 @@ protected Observable() { *

* It returns a reference to the {@link Subscription} interface. This enables Observers to * unsubscribe, that is, to stop receiving items and notifications before the Observable stops - * sending them, which also invokes the Observer's {@link Observer#onCompleted onCompleted} - * method. + * sending them, which also invokes the Observer's {@link Observer#onCompleted onCompleted} method. *

* An Observable<T> instance is responsible for accepting all subscriptions * and notifying all Observers. Unless the documentation for a particular @@ -229,8 +227,7 @@ public Subscription subscribe(Observer observer) { *

* It returns a reference to the {@link Subscription} interface. This enables Observers to * unsubscribe, that is, to stop receiving items and notifications before the Observable stops - * sending them, which also invokes the Observer's {@link Observer#onCompleted onCompleted} - * method. + * sending them, which also invokes the Observer's {@link Observer#onCompleted onCompleted} method. *

* An Observable<T> instance is responsible for accepting all subscriptions * and notifying all Observers. Unless the documentation for a particular @@ -312,50 +309,6 @@ public Subscription subscribe(final Map callbacks, Scheduler sch return subscribeOn(scheduler).subscribe(callbacks); } - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Subscription subscribe(final Object o) { - if (o instanceof Observer) { - // in case a dynamic language is not correctly handling the overloaded methods and we receive an Observer just forward to the correct method. - return subscribe((Observer) o); - } - - if (o == null) { - throw new IllegalArgumentException("onNext can not be null"); - } - - // lookup and memoize onNext - final FuncN onNext = Functions.from(o); - - /** - * Wrapping since raw functions provided by the user are being invoked. - * - * See https://github.com/Netflix/RxJava/issues/216 for discussion on "Guideline 6.4: Protect calls to user code from within an operator" - */ - return protectivelyWrapAndSubscribe(new Observer() { - - @Override - public void onCompleted() { - // do nothing - } - - @Override - public void onError(Exception e) { - handleError(e); - throw new OnErrorNotImplementedException(e); - } - - @Override - public void onNext(Object args) { - onNext.call(args); - } - - }); - } - - public Subscription subscribe(final Object o, Scheduler scheduler) { - return subscribeOn(scheduler).subscribe(o); - } - public Subscription subscribe(final Action1 onNext) { if (onNext == null) { throw new IllegalArgumentException("onNext can not be null"); @@ -391,48 +344,6 @@ public Subscription subscribe(final Action1 onNext, Scheduler scheduler) { return subscribeOn(scheduler).subscribe(onNext); } - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Subscription subscribe(final Object onNext, final Object onError) { - if (onNext == null) { - throw new IllegalArgumentException("onNext can not be null"); - } - if (onError == null) { - throw new IllegalArgumentException("onError can not be null"); - } - - // lookup and memoize onNext - final FuncN onNextFunction = Functions.from(onNext); - - /** - * Wrapping since raw functions provided by the user are being invoked. - * - * See https://github.com/Netflix/RxJava/issues/216 for discussion on "Guideline 6.4: Protect calls to user code from within an operator" - */ - return protectivelyWrapAndSubscribe(new Observer() { - - @Override - public void onCompleted() { - // do nothing - } - - @Override - public void onError(Exception e) { - handleError(e); - Functions.from(onError).call(e); - } - - @Override - public void onNext(Object args) { - onNextFunction.call(args); - } - - }); - } - - public Subscription subscribe(final Object onNext, final Object onError, Scheduler scheduler) { - return subscribeOn(scheduler).subscribe(onNext, onError); - } - public Subscription subscribe(final Action1 onNext, final Action1 onError) { if (onNext == null) { throw new IllegalArgumentException("onNext can not be null"); @@ -471,51 +382,6 @@ public Subscription subscribe(final Action1 onNext, final Action1 return subscribeOn(scheduler).subscribe(onNext, onError); } - @SuppressWarnings({ "rawtypes", "unchecked" }) - public Subscription subscribe(final Object onNext, final Object onError, final Object onComplete) { - if (onNext == null) { - throw new IllegalArgumentException("onNext can not be null"); - } - if (onError == null) { - throw new IllegalArgumentException("onError can not be null"); - } - if (onComplete == null) { - throw new IllegalArgumentException("onComplete can not be null"); - } - - // lookup and memoize onNext - final FuncN onNextFunction = Functions.from(onNext); - - /** - * Wrapping since raw functions provided by the user are being invoked. - * - * See https://github.com/Netflix/RxJava/issues/216 for discussion on "Guideline 6.4: Protect calls to user code from within an operator" - */ - return protectivelyWrapAndSubscribe(new Observer() { - - @Override - public void onCompleted() { - Functions.from(onComplete).call(); - } - - @Override - public void onError(Exception e) { - handleError(e); - Functions.from(onError).call(e); - } - - @Override - public void onNext(Object args) { - onNextFunction.call(args); - } - - }); - } - - public Subscription subscribe(final Object onNext, final Object onError, final Object onComplete, Scheduler scheduler) { - return subscribeOn(scheduler).subscribe(onNext, onError, onComplete); - } - public Subscription subscribe(final Action1 onNext, final Action1 onError, final Action0 onComplete) { if (onNext == null) { throw new IllegalArgumentException("onNext can not be null"); @@ -605,8 +471,7 @@ public Subscription call(Observer t1) { } /** - * an Observable that invokes {@link Observer#onError onError} when the {@link Observer} - * subscribes to it. + * an Observable that invokes {@link Observer#onError onError} when the {@link Observer} subscribes to it. * * @param * the type of item emitted by the Observable @@ -635,14 +500,12 @@ public Subscription call(Observer observer) { } /** - * Creates an Observable that will execute the given function when an {@link Observer} - * subscribes to it. + * Creates an Observable that will execute the given function when an {@link Observer} subscribes to it. *

* *

* Write the function you pass to create so that it behaves as an Observable: It - * should invoke the Observer's {@link Observer#onNext onNext}, - * {@link Observer#onError onError}, and {@link Observer#onCompleted onCompleted} methods + * should invoke the Observer's {@link Observer#onNext onNext}, {@link Observer#onError onError}, and {@link Observer#onCompleted onCompleted} methods * appropriately. *

* A well-formed Observable must invoke either the Observer's onCompleted method @@ -665,49 +528,6 @@ public static Observable create(Func1, Subscription> func) { return new Observable(func); } - /** - * Creates an Observable that will execute the given function when an {@link Observer} - * subscribes to it. - *

- * - *

- * This method accepts {@link Object} to allow different languages to pass in methods using - * {@link FunctionLanguageAdaptor}. - *

- * Write the function you pass to create so that it behaves as an Observable: It - * should invoke the Observer's {@link Observer#onNext onNext}, - * {@link Observer#onError onError}, and {@link Observer#onCompleted onCompleted} methods - * appropriately. - *

- * A well-formed Observable must invoke either the Observer's onCompleted method - * exactly once or its onError method exactly once. - *

- * See Rx Design Guidelines (PDF) - * for detailed information. - * - * @param - * the type of the items that this Observable emits - * @param func - * a function that accepts an Observer<T>, invokes its - * onNext, onError, and onCompleted methods - * as appropriate, and returns a {@link Subscription} that allows the Observer to - * cancel the subscription - * @return an Observable that, when an {@link Observer} subscribes to it, will execute the given - * function - */ - public static Observable create(final Object func) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(func); - return create(new Func1, Subscription>() { - - @Override - public Subscription call(Observer t1) { - return (Subscription) _f.call(t1); - } - - }); - } - /** * Returns an Observable that emits no data to the {@link Observer} and immediately invokes * its {@link Observer#onCompleted onCompleted} method. @@ -724,8 +544,7 @@ public static Observable empty() { } /** - * Returns an Observable that invokes an {@link Observer}'s {@link Observer#onError onError} - * method when the Observer subscribes to it + * Returns an Observable that invokes an {@link Observer}'s {@link Observer#onError onError} method when the Observer subscribes to it *

* * @@ -733,8 +552,7 @@ public static Observable empty() { * the particular error to report * @param * the type of the items (ostensibly) emitted by the Observable - * @return an Observable that invokes the {@link Observer}'s - * {@link Observer#onError onError} method when the Observer subscribes to it + * @return an Observable that invokes the {@link Observer}'s {@link Observer#onError onError} method when the Observer subscribes to it */ public static Observable error(Exception exception) { return new ThrowObservable(exception); @@ -757,33 +575,6 @@ public static Observable filter(Observable that, Func1 pre return create(OperationFilter.filter(that, predicate)); } - /** - * Filters an Observable by discarding any items it emits that do not meet some test. - *

- * - * - * @param that - * the Observable to filter - * @param function - * a function that evaluates an item emitted by the source Observable, and - * returns true if it passes the filter - * @return an Observable that emits only those items emitted by the source Observable that the - * filter evaluates as true - */ - public static Observable filter(Observable that, final Object function) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(function); - return filter(that, new Func1() { - - @Override - public Boolean call(T t1) { - return (Boolean) _f.call(t1); - - } - - }); - } - /** * Filters an Observable by discarding any items it emits that do not meet some test. *

@@ -829,10 +620,9 @@ public static Observable from(Iterable iterable) { * the type of items in the Array, and the type of items to be emitted by the * resulting Observable * @return an Observable that emits each item in the source Array - * @see #toObservable(Object...) */ public static Observable from(T... items) { - return toObservable(items); + return from(Arrays.asList(items)); } /** @@ -882,8 +672,7 @@ public static Observable subscribeOn(Observable source, Scheduler sche * the {@link Scheduler} to notify Observers on * @param * the type of the items emitted by the Observable - * @return the source Observable modified so that its Observers are notified on the specified - * {@link Scheduler} + * @return the source Observable modified so that its Observers are notified on the specified {@link Scheduler} */ public static Observable observeOn(Observable source, Scheduler scheduler) { return create(OperationObserveOn.observeOn(source, scheduler)); @@ -911,39 +700,6 @@ public static Observable defer(Func0> observableFactory) { return create(OperationDefer.defer(observableFactory)); } - /** - * Returns an Observable that calls an Observable factory to create its Observable for each - * new Observer that subscribes. - *

- * - *

- * The defer operator allows you to defer or delay emitting items from an Observable - * until such time as an {@link Observer} subscribes to the Observable. This allows an Observer - * to easily obtain an updates or refreshed version of the sequence. - * - * @param observableFactory - * the Observable factory function to invoke for each {@link Observer} that - * subscribes to the resulting Observable - * @param - * the type of the items emitted by the Observable - * @return an Observable whose {@link Observer}s trigger an invocation of the given Observable - * factory function - */ - public static Observable defer(Object observableFactory) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(observableFactory); - - return create(OperationDefer.defer(new Func0>() { - - @Override - @SuppressWarnings("unchecked") - public Observable call() { - return (Observable) _f.call(); - } - - })); - } - /** * Returns an Observable that emits a single item and then completes. *

@@ -991,37 +747,6 @@ public static Observable map(Observable sequence, Func1 func) return create(OperationMap.map(sequence, func)); } - /** - * Applies a function of your choosing to every item emitted by an Observable, and emits the - * results of these transformations as its own Observable items. - *

- * - * - * @param sequence - * the source Observable - * @param func - * a function to apply to each item emitted by the source Observable - * @param - * the type of items emitted by the the source Observable - * @param - * the type of items to be emitted by the resulting Observable - * @return an Observable that emits the items from the source Observable as transformed by the - * given function - */ - public static Observable map(Observable sequence, final Object func) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(func); - return map(sequence, new Func1() { - - @SuppressWarnings("unchecked") - @Override - public R call(T t1) { - return (R) _f.call(t1); - } - - }); - } - /** * Creates a new Observable by applying a function that you supply to each item emitted by * the source Observable, where that function returns an Observable, and then merging those @@ -1051,46 +776,7 @@ public static Observable mapMany(Observable sequence, Func1 - * - *

- * Note: mapMany and flatMap are equivalent. - * - * @param sequence - * the source Observable - * @param func - * a function that, when applied to each item emitted by the source Observable, - * generates an Observable - * @param - * the type of items emitted by the source Observable - * @param - * the type of items emitted by the Observables that are returned from - * func - * @return an Observable that emits the result of applying the transformation function to each - * item emitted by the source Observable and merging the results of the Observables - * obtained from this transformation - */ - public static Observable mapMany(Observable sequence, final Object func) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(func); - return mapMany(sequence, new Func1() { - - @SuppressWarnings("unchecked") - @Override - public R call(T t1) { - return (R) _f.call(t1); - } - - }); - } - - /** - * Turns all of the notifications from a source Observable into {@link Observer#onNext onNext} - * emissions, and marks them with their original notification types within {@link Notification} - * objects. + * Turns all of the notifications from a source Observable into {@link Observer#onNext onNext} emissions, and marks them with their original notification types within {@link Notification} objects. *

* * @@ -1105,8 +791,7 @@ public static Observable> materialize(final Observable se } /** - * Reverses the effect of {@link #materialize materialize} by transforming the - * {@link Notification} objects emitted by a source Observable into the items or notifications + * Reverses the effect of {@link #materialize materialize} by transforming the {@link Notification} objects emitted by a source Observable into the items or notifications * they represent. *

* @@ -1114,8 +799,7 @@ public static Observable> materialize(final Observable se * @param sequence * an Observable that emits {@link Notification} objects that represent the items and * notifications emitted by an Observable - * @return an Observable that emits the items and notifications embedded in the - * {@link Notification} objects emitted by the source Observable + * @return an Observable that emits the items and notifications embedded in the {@link Notification} objects emitted by the source Observable * @see MSDN: Observable.Dematerialize */ public static Observable dematerialize(final Observable> sequence) { @@ -1227,8 +911,7 @@ public static Observable concat(Observable... source) { * an {@link Action0} to be invoked when the source Observable completes * or errors * @return an Observable that emits the same items as the source, then invokes the action - * @see MSDN: - * Observable.Finally Method + * @see MSDN: Observable.Finally Method */ public static Observable finallyDo(Observable source, Action0 action) { return create(OperationFinally.finallyDo(source, action)); @@ -1263,38 +946,10 @@ public static Observable flatMap(Observable sequence, Func1 - * + * Groups the items emitted by an Observable according to a specified criterion, and emits these + * grouped items as {@link GroupedObservable}s, one GroupedObservable per group. *

- * Note: mapMany and flatMap are equivalent. - * - * @param sequence - * the source Observable - * @param func - * a function that, when applied to each item emitted by the source Observable, - * generates an Observable - * @param - * the type of items emitted by the source Observable - * @param - * the type of items emitted by the Observables that are returned from - * func - * @return an Observable that emits the result of applying the transformation function to each - * item emitted by the source Observable and merging the results of the Observables - * obtained from this transformation - * @see #mapMany(Observable, Func1) - */ - public static Observable flatMap(Observable sequence, final Object func) { - return mapMany(sequence, func); - } - - /** - * Groups the items emitted by an Observable according to a specified criterion, and emits these - * grouped items as {@link GroupedObservable}s, one GroupedObservable per group. - *

- * + * * * @param source * an Observable whose items you want to group @@ -1317,51 +972,6 @@ public static Observable> groupBy(Observable - * - * - * @param source - * an Observable whose items you want to group - * @param keySelector - * a function that extracts the key for each item omitted by the source Observable - * @param elementSelector - * a function to map each item emitted by the source Observable to an item emitted - * by a {@link GroupedObservable} - * @param - * the key type - * @param - * the type of items emitted by the source Observable - * @param - * the type of items to be emitted by the resulting {@link GroupedObservable}s - * @return an Observable that emits {@link GroupedObservable}s, each of which corresponds to a - * unique key value and emits items representing items from the source Observable that - * share that key value - */ - @SuppressWarnings("rawtypes") - public static Observable> groupBy(Observable source, final Object keySelector, final Object elementSelector) { - final FuncN _k = Functions.from(keySelector); - final FuncN _e = Functions.from(elementSelector); - - return groupBy(source, new Func1() { - - @SuppressWarnings("unchecked") - @Override - public K call(T t1) { - return (K) _k.call(t1); - } - }, new Func1() { - - @SuppressWarnings("unchecked") - @Override - public R call(T t1) { - return (R) _e.call(t1); - } - }); - } - /** * Groups the items emitted by an Observable according to a specified criterion, and emits these * grouped items as {@link GroupedObservable}s, one GroupedObservable per group. @@ -1383,38 +993,6 @@ public R call(T t1) { public static Observable> groupBy(Observable source, final Func1 keySelector) { return create(OperationGroupBy.groupBy(source, keySelector)); } - - /** - * Groups the items emitted by an Observable according to a specified criterion, and emits these - * grouped items as {@link GroupedObservable}s, one GroupedObservable per group. - *

- * - * - * @param source - * an Observable whose items you want to group - * @param keySelector - * a function that extracts the key for each item emitted by the source Observable - * @param - * the key type - * @param - * the type of items to be emitted by the resulting {@link GroupedObservable}s - * @return an Observable that emits {@link GroupedObservable}s, each of which corresponds to a - * unique key value and emits items representing items from the source Observable that - * share that key value - */ - @SuppressWarnings("rawtypes") - public static Observable> groupBy(Observable source, final Object keySelector) { - final FuncN _k = Functions.from(keySelector); - - return groupBy(source, new Func1() { - - @SuppressWarnings("unchecked") - @Override - public K call(T t1) { - return (K) _k.call(t1); - } - }); - } /** * This behaves like {@link #merge(java.util.List)} except that if any of the merged Observables @@ -1495,7 +1073,7 @@ public static Observable mergeDelayError(Observable... source) { * Returns an Observable that never sends any items or notifications to an {@link Observer}. *

* - *

+ *

* This Observable is useful primarily for testing purposes. * * @param @@ -1538,47 +1116,7 @@ public static Observable onErrorResumeNext(final Observable that, fina } /** - * Instruct an Observable to pass control to another Observable (the return value of a function) - * rather than invoking {@link Observer#onError onError} if it encounters an error. - *

- * - *

- * By default, when an Observable encounters an error that prevents it from emitting the - * expected item to its Observer, the Observable invokes its {@link Observer}'s - * methods. The onErrorResumeNext method changes this behavior. If you pass a - * function that returns an Observable (resumeFunction) to - * onErrorResumeNext, if the source Observable encounters an error, instead of - * invoking its Observer's onError function, it will instead relinquish control to - * this new Observable, which will invoke the Observer's {@link Observer#onNext onNext} method - * if it is able to do so. In such a case, because no Observable necessarily invokes - * onError, the Observer may never know that an error happened. - *

- * You can use this to prevent errors from propagating or to supply fallback data should errors - * be encountered. - * - * @param that - * the source Observable - * @param resumeFunction - * a function that returns an Observable that will take over if the source Observable - * encounters an error - * @return the source Observable, with its behavior modified as described - */ - public static Observable onErrorResumeNext(final Observable that, final Object resumeFunction) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(resumeFunction); - return onErrorResumeNext(that, new Func1>() { - - @SuppressWarnings("unchecked") - @Override - public Observable call(Exception e) { - return (Observable) _f.call(e); - } - }); - } - - /** - * Instruct an Observable to pass control to another Observable rather than invoking - * {@link Observer#onError onError} if it encounters an error. + * Instruct an Observable to pass control to another Observable rather than invoking {@link Observer#onError onError} if it encounters an error. *

* *

@@ -1619,8 +1157,7 @@ public static Observable onErrorResumeNext(final Observable that, fina * methods. The onErrorReturn method changes this behavior. If you pass a function * (resumeFunction) to onErrorReturn, if the source Observable * encounters an error, instead of invoking its Observer's onError method, it will - * instead pass the return value of resumeFunction to the Observer's - * {@link Observer#onNext onNext} method. + * instead pass the return value of resumeFunction to the Observer's {@link Observer#onNext onNext} method. *

* You can use this to prevent errors from propagating or to supply fallback data should errors * be encountered. @@ -1628,8 +1165,7 @@ public static Observable onErrorResumeNext(final Observable that, fina * @param that * the source Observable * @param resumeFunction - * a function that returns an item that will be passed into an {@link Observer}'s - * {@link Observer#onNext onNext} method if the Observable encounters an error that + * a function that returns an item that will be passed into an {@link Observer}'s {@link Observer#onNext onNext} method if the Observable encounters an error that * would otherwise cause it to invoke {@link Observer#onError onError} * @return the source Observable, with its behavior modified as described */ @@ -1639,10 +1175,10 @@ public static Observable onErrorReturn(final Observable that, Func1 * + * * @param that * the source Observable * @return a {@link ConnectableObservable} that upon connection causes the source Observable to @@ -1673,8 +1209,7 @@ public static Observable cache(final Observable that) { } /** - * Returns a {@link ConnectableObservable}, which waits until its - * {@link ConnectableObservable#connect} method is called before it begins emitting items to + * Returns a {@link ConnectableObservable}, which waits until its {@link ConnectableObservable#connect} method is called before it begins emitting items to * those {@link Observer}s that have subscribed to it. *

* @@ -1717,46 +1252,14 @@ public static Observable reduce(Observable sequence, Func2 ac return takeLast(create(OperationScan.scan(sequence, accumulator)), 1); } - /** - * A version of reduce() for use by dynamic languages. - *

- * - * - * @see #reduce(Observable, Func2) - */ - public static Observable reduce(final Observable sequence, final Object accumulator) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(accumulator); - return reduce(sequence, new Func2() { - - @SuppressWarnings("unchecked") - @Override - public T call(T t1, T t2) { - return (T) _f.call(t1, t2); - } - - }); - } - /** * Synonymous with reduce() *

* - * - * @see #reduce(Observable, Func2) - */ - public static Observable aggregate(Observable sequence, Func2 accumulator) { - return reduce(sequence, accumulator); - } - - /** - * A version of aggregate() for use by dynamic languages. - *

- * * * @see #reduce(Observable, Func2) */ - public static Observable aggregate(Observable sequence, Object accumulator) { + public static Observable aggregate(Observable sequence, Func2 accumulator) { return reduce(sequence, accumulator); } @@ -1793,47 +1296,15 @@ public static Observable reduce(Observable sequence, R initialValue return takeLast(create(OperationScan.scan(sequence, initialValue, accumulator)), 1); } - /** - * A version of reduce() for use by dynamic languages. - *

- * - * - * @see #reduce(Observable, Object, Func2) - */ - public static Observable reduce(final Observable sequence, final R initialValue, final Object accumulator) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(accumulator); - return reduce(sequence, initialValue, new Func2() { - @SuppressWarnings("unchecked") - @Override - public R call(R r, T t) { - return (R) _f.call(r, t); - } - }); - } - /** * Synonymous with reduce(). *

* - * - * @see #reduce(Observable, Object, Func2) */ public static Observable aggregate(Observable sequence, R initialValue, Func2 accumulator) { return reduce(sequence, initialValue, accumulator); } - /** - * A version of aggregate() for use by dynamic languages. - *

- * - * - * @see #reduce(Observable, Object, Func2) - */ - public static Observable aggregate(Observable sequence, R initialValue, Object accumulator) { - return reduce(sequence, initialValue, accumulator); - } - /** * Returns an Observable that applies a function of your choosing to the first item emitted by a * source Observable, then feeds the result of that function along with the second item emitted @@ -1858,27 +1329,6 @@ public static Observable scan(Observable sequence, Func2 accu return create(OperationScan.scan(sequence, accumulator)); } - /** - * A version of scan() for use by dynamic languages. - *

- * - * - * @see #scan(Observable, Func2) - */ - public static Observable scan(final Observable sequence, final Object accumulator) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(accumulator); - return scan(sequence, new Func2() { - - @SuppressWarnings("unchecked") - @Override - public T call(T t1, T t2) { - return (T) _f.call(t1, t2); - } - - }); - } - /** * Returns an Observable that applies a function of your choosing to the first item emitted by a * source Observable, then feeds the result of that function along with the second item emitted @@ -1910,26 +1360,6 @@ public static Observable scan(Observable sequence, R initialValue, return create(OperationScan.scan(sequence, initialValue, accumulator)); } - /** - * A version of scan() for use by dynamic languages. - *

- * - * - * @see #scan(Observable, Object, Func2) - */ - public static Observable scan(final Observable sequence, final R initialValue, final Object accumulator) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(accumulator); - return scan(sequence, initialValue, new Func2() { - - @SuppressWarnings("unchecked") - @Override - public R call(R r, T t) { - return (R) _f.call(r, t); - } - }); - } - /** * Returns an Observable that emits a Boolean that indicates whether all items emitted by a * source Observable satisfy a condition. @@ -1949,33 +1379,6 @@ public static Observable all(final Observable sequence, final Fu return create(OperationAll.all(sequence, predicate)); } - /** - * Returns an Observable that emits a Boolean that indicates whether all items emitted by a - * source Observable satisfy a condition. - *

- * - * - * @param sequence - * an Observable whose emitted items you are evaluating - * @param predicate - * a function that evaluates each emitted item and returns a Boolean - * @param - * the type of items emitted by the source Observable - * @return an Observable that emits true if all items emitted by the source - * Observable satisfy the predicate; otherwise, false - */ - public static Observable all(final Observable sequence, Object predicate) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(predicate); - - return all(sequence, new Func1() { - @Override - public Boolean call(T t) { - return (Boolean) _f.call(t); - } - }); - } - /** * Returns an Observable that skips the first num items emitted by the source * Observable and emits the remaining items. @@ -2002,7 +1405,7 @@ public static Observable skip(final Observable items, int num) { * emits the items emitted by the most recently published of those Observables. *

* - * + * * @param sequenceOfSequences * the source Observable that emits Observables * @return an Observable that emits only the items emitted by the most recently published @@ -2018,9 +1421,8 @@ public static Observable switchDo(Observable> sequenceOfSeq *

* *

- * A well-behaved Observable does not interleave its invocations of the - * {@link Observer#onNext onNext}, {@link Observer#onCompleted onCompleted}, and - * {@link Observer#onError onError} methods of its {@link Observer}s; it invokes + * A well-behaved Observable does not interleave its invocations of the {@link Observer#onNext onNext}, {@link Observer#onCompleted onCompleted}, and {@link Observer#onError onError} methods of + * its {@link Observer}s; it invokes * onCompleted or onError only once; and it never invokes * onNext after invoking either onCompleted or onError. * synchronize enforces this, and the Observable it returns invokes @@ -2043,8 +1445,7 @@ public static Observable synchronize(Observable observable) { *

* *

- * This method returns an Observable that will invoke a subscribing {@link Observer}'s - * {@link Observer#onNext onNext} method a maximum of num times before invoking + * This method returns an Observable that will invoke a subscribing {@link Observer}'s {@link Observer#onNext onNext} method a maximum of num times before invoking * {@link Observer#onCompleted onCompleted}. * * @param items @@ -2094,31 +1495,6 @@ public static Observable takeWhile(final Observable items, Func1 - * - * - * @param items - * the source Observable - * @param predicate - * a function to test each item emitted by the source Observable for a condition - * @return an Observable that emits items from the source Observable so long as the predicate - * continues to return true for each item, then completes - */ - public static Observable takeWhile(final Observable items, Object predicate) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(predicate); - - return takeWhile(items, new Func1() { - @Override - public Boolean call(T t) { - return (Boolean) _f.call(t); - } - }); - } - /** * Returns an Observable that emits the items emitted by a source Observable so long as a given * predicate remains true, where the predicate can operate on both the item and its index @@ -2138,35 +1514,6 @@ public static Observable takeWhileWithIndex(final Observable items, Fu return create(OperationTakeWhile.takeWhileWithIndex(items, predicate)); } - /** - * Returns an Observable that emits the items emitted by a source Observable so long as a given - * predicate remains true, where the predicate can operate on both the item and its index - * relative to the complete sequence. - *

- * - * - * @param items - * the source Observable - * @param predicate - * a function to test each item emitted by the source Observable for a condition; - * the second parameter of the function represents the index of the source item - * @return an Observable that emits items from the source Observable so long as the predicate - * continues to return true for each item, then completes - */ - public static Observable takeWhileWithIndex(final Observable items, Object predicate) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(predicate); - - return create(OperationTakeWhile.takeWhileWithIndex(items, new Func2() - { - @Override - public Boolean call(T t, Integer integer) - { - return (Boolean) _f.call(t, integer); - } - })); - } - /** * Wraps each item emitted by a source Observable in a {@link Timestamped} object. *

@@ -2184,8 +1531,7 @@ public Observable> timestamp() { *

* *

- * Normally, an Observable that emits multiple items will do so by invoking its - * {@link Observer}'s {@link Observer#onNext onNext} method for each such item. You can change + * Normally, an Observable that emits multiple items will do so by invoking its {@link Observer}'s {@link Observer#onNext onNext} method for each such item. You can change * this behavior, instructing the Observable to compose a List of all of the items and then to * invoke the Observer's onNext function once, passing it the entire list, by * calling toList. @@ -2207,8 +1553,7 @@ public static Observable> toList(final Observable that) { * emit items into the specified {@link Subject}. * * @param source - * the source Observable whose emitted items will be pushed into the specified - * {@link Subject} + * the source Observable whose emitted items will be pushed into the specified {@link Subject} * @param subject * the {@link Subject} to push source items into * @param @@ -2333,7 +1678,7 @@ public static Observable from(Future future, long timeout, TimeUnit un * the type of items in the array, and also the type of items emitted by the * resulting Observable * @return an Observable that emits each item in the source array - * @deprecated Use {@link #from(Object...)} + * @deprecated Use {@link #from(T...)} */ public static Observable toObservable(T... items) { return toObservable(Arrays.asList(items)); @@ -2375,34 +1720,8 @@ public static Observable> toSortedList(Observable sequence, Func2 } /** - * Return an Observable that emits the items emitted by the source Observable, in a sorted - * order based on a specified comparison function - *

- * - * - * @param sequence - * the source Observable - * @param sortFunction - * a function that compares two items emitted by the source Observable and returns - * an Integer that indicates their sort order - * @return an Observable that emits the items from the source Observable in sorted order - */ - public static Observable> toSortedList(Observable sequence, final Object sortFunction) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(sortFunction); - return create(OperationToObservableSortedList.toSortedList(sequence, new Func2() { - - @Override - public Integer call(T t1, T t2) { - return (Integer) _f.call(t1, t2); - } - - })); - } - - /** - * Returns an Observable that emits the results of a function of your choosing applied to pairs - * of items emitted, in sequence, by two other Observables. + * Returns an Observable that emits the results of a function of your choosing applied to pairs + * of items emitted, in sequence, by two other Observables. *

* *

@@ -2412,8 +1731,7 @@ public Integer call(T t1, T t2) { * the new Observable will be the result of the function applied to the second item emitted by * w0 and the second item emitted by w1; and so forth. *

- * The resulting Observable<R> returned from zip will invoke - * {@link Observer#onNext onNext} as many times as the number of onNext invocations + * The resulting Observable<R> returned from zip will invoke {@link Observer#onNext onNext} as many times as the number of onNext invocations * of the source Observable that emits the fewest items. * * @param w0 @@ -2476,68 +1794,6 @@ public static Observable sequenceEqual(Observable first, Observa return zip(first, second, equality); } - /** - * Returns an Observable that emits Boolean values that indicate whether the pairs of items - * emitted by two source Observables are equal based on the results of a specified equality - * function. - *

- * - * - * @param first - * one Observable to compare - * @param second - * the second Observable to compare - * @param equality - * a function used to compare items emitted by both Observables - * @param - * the type of items emitted by each Observable - * @return an Observable that emits Booleans that indicate whether the corresponding items - * emitted by the source Observables are equal - */ - public static Observable sequenceEqual(Observable first, Observable second, Object equality) { - return zip(first, second, equality); - } - - /** - * Returns an Observable that emits the results of a function of your choosing applied to pairs - * of items emitted, in sequence, by two other Observables. - *

- * - *

- * zip applies this function in strict sequence, so the first item emitted by the - * new Observable will be the result of the function applied to the first item emitted by - * w0 and the first item emitted by w1; the second item emitted by - * the new Observable will be the result of the function applied to the second item emitted by - * w0 and the second item emitted by w1; and so forth. - *

- * The resulting Observable<R> returned from zip will invoke - * {@link Observer#onNext onNext} as many times as the number of onNext invocations - * of the source Observable that emits the fewest items. - * - * @param w0 - * one source Observable - * @param w1 - * another source Observable - * @param function - * a function that, when applied to a pair of items, each emitted by one of the two - * source Observables, results in an item that will be emitted by the resulting - * Observable - * @return an Observable that emits the zipped results - */ - public static Observable zip(Observable w0, Observable w1, final Object function) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(function); - return zip(w0, w1, new Func2() { - - @SuppressWarnings("unchecked") - @Override - public R call(T0 t0, T1 t1) { - return (R) _f.call(t0, t1); - } - - }); - } - /** * Returns an Observable that emits the results of a function of your choosing applied to * combinations of three items emitted, in sequence, by three other Observables. @@ -2551,8 +1807,7 @@ public R call(T0 t0, T1 t1) { * function applied to the second item emitted by w0, the second item emitted by * w1, and the second item emitted by w2; and so forth. *

- * The resulting Observable<R> returned from zip will invoke - * {@link Observer#onNext onNext} as many times as the number of onNext invocations + * The resulting Observable<R> returned from zip will invoke {@link Observer#onNext onNext} as many times as the number of onNext invocations * of the source Observable that emits the fewest items. * * @param w0 @@ -2570,48 +1825,6 @@ public static Observable zip(Observable w0, Observable - * - *

- * zip applies this function in strict sequence, so the first item emitted by the - * new Observable will be the result of the function applied to the first item emitted by - * w0, the first item emitted by w1, and the first item emitted by - * w2; the second item emitted by the new Observable will be the result of the - * function applied to the second item emitted by w0, the second item emitted by - * w1, and the second item emitted by w2; and so forth. - *

- * The resulting Observable<R> returned from zip will invoke - * {@link Observer#onNext onNext} as many times as the number of onNext invocations - * of the source Observable that emits the fewest items. - * - * @param w0 - * one source Observable - * @param w1 - * another source Observable - * @param w2 - * a third source Observable - * @param function - * a function that, when applied to an item emitted by each of the source - * Observables, results in an item that will be emitted by the resulting Observable - * @return an Observable that emits the zipped results - */ - public static Observable zip(Observable w0, Observable w1, Observable w2, final Object function) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(function); - return zip(w0, w1, w2, new Func3() { - - @SuppressWarnings("unchecked") - @Override - public R call(T0 t0, T1 t1, T2 t2) { - return (R) _f.call(t0, t1, t2); - } - - }); - } - /** * Returns an Observable that emits the results of a function of your choosing applied to * combinations of four items emitted, in sequence, by four other Observables. @@ -2625,8 +1838,7 @@ public R call(T0 t0, T1 t1, T2 t2) { * the new Observable will be the result of the function applied to the second item emitted by * each of those Observables; and so forth. *

- * The resulting Observable<R> returned from zip will invoke - * {@link Observer#onNext onNext} as many times as the number of onNext invocations + * The resulting Observable<R> returned from zip will invoke {@link Observer#onNext onNext} as many times as the number of onNext invocations * of the source Observable that emits the fewest items. * * @param w0 @@ -2647,191 +1859,35 @@ public static Observable zip(Observable w0, Observabl } /** - * Returns an Observable that emits the results of a function of your choosing applied to - * combinations of four items emitted, in sequence, by four other Observables. - *

- * - *

- * zip applies this function in strict sequence, so the first item emitted by the - * new Observable will be the result of the function applied to the first item emitted by - * w0, the first item emitted by w1, the first item emitted by - * w2, and the first item emitted by w3; the second item emitted by - * the new Observable will be the result of the function applied to the second item emitted by - * each of those Observables; and so forth. - *

- * The resulting Observable<R> returned from zip will invoke - * {@link Observer#onNext onNext} as many times as the number of onNext invocations - * of the source Observable that emits the fewest items. + * Combines the given observables, emitting an event containing an aggregation of the latest values of each of the source observables + * each time an event is received from one of the source observables, where the aggregation is defined by the given function. * * @param w0 - * one source Observable + * The first source observable. * @param w1 - * another source Observable - * @param w2 - * a third source Observable - * @param w3 - * a fourth source Observable - * @param function - * a function that, when applied to an item emitted by each of the source - * Observables, results in an item that will be emitted by the resulting Observable - * @return an Observable that emits the zipped results - */ - public static Observable zip(Observable w0, Observable w1, Observable w2, Observable w3, final Object function) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(function); - return zip(w0, w1, w2, w3, new Func4() { - - @SuppressWarnings("unchecked") - @Override - public R call(T0 t0, T1 t1, T2 t2, T3 t3) { - return (R) _f.call(t0, t1, t2, t3); - } - - }); - } - - /** - * Returns an Observable that emits the results of a function of your choosing applied to - * combinations of four items emitted, in sequence, by four other Observables. - *

- * zip applies this function in strict sequence, so the first item emitted by the - * new Observable will be the result of the function applied to the first item emitted by - * all of the Observalbes; the second item emitted by the new Observable will be the result of - * the function applied to the second item emitted by each of those Observables; and so forth. - *

- * The resulting Observable returned from zip will invoke - * onNext as many times as the number of onNext invokations of the - * source Observable that emits the fewest items. - *

- * - * - * @param ws - * An Observable of source Observables - * @param reduceFunction - * a function that, when applied to an item emitted by each of the source - * Observables, results in an item that will be emitted by the resulting Observable - * @return an Observable that emits the zipped results - */ - public static Observable zip(Observable> ws, final FuncN reduceFunction) { - return ws.toList().mapMany(new Func1>, Observable>() { - @Override - public Observable call(List> wsList) { - return create(OperationZip.zip(wsList, reduceFunction)); - } - }); - } - - /** - * Returns an Observable that emits the results of a function of your choosing applied to - * combinations of four items emitted, in sequence, by four other Observables. - *

- * zip applies this function in strict sequence, so the first item emitted by the - * new Observable will be the result of the function applied to the first item emitted by - * all of the Observalbes; the second item emitted by the new Observable will be the result of - * the function applied to the second item emitted by each of those Observables; and so forth. - *

- * The resulting Observable returned from zip will invoke - * onNext as many times as the number of onNext invocations of the - * source Observable that emits the fewest items. - *

- * - * - * @param ws - * An Observable of source Observables - * @param function - * a function that, when applied to an item emitted by each of the source - * Observables, results in an item that will be emitted by the resulting Observable - * @return an Observable that emits the zipped results - */ - public static Observable zip(Observable> ws, final Object function) { - @SuppressWarnings({ "unchecked" }) - final FuncN _f = Functions.from(function); - return zip(ws, _f); - } - - /** - * Returns an Observable that emits the results of a function of your choosing applied to - * combinations of four items emitted, in sequence, by four other Observables. - *

- * zip applies this function in strict sequence, so the first item emitted by the - * new Observable will be the result of the function applied to the first item emitted by - * all of the Observalbes; the second item emitted by the new Observable will be the result of - * the function applied to the second item emitted by each of those Observables; and so forth. - *

- * The resulting Observable returned from zip will invoke - * onNext as many times as the number of onNext invokations of the - * source Observable that emits the fewest items. - *

- * - * - * @param ws - * A collection of source Observables - * @param reduceFunction - * a function that, when applied to an item emitted by each of the source - * Observables, results in an item that will be emitted by the resulting Observable - * @return an Observable that emits the zipped results - */ - public static Observable zip(Collection> ws, FuncN reduceFunction) { - return create(OperationZip.zip(ws, reduceFunction)); - } - - /** - * Returns an Observable that emits the results of a function of your choosing applied to - * combinations of four items emitted, in sequence, by four other Observables. - *

- * zip applies this function in strict sequence, so the first item emitted by the - * new Observable will be the result of the function applied to the first item emitted by - * all of the Observalbes; the second item emitted by the new Observable will be the result of - * the function applied to the second item emitted by each of those Observables; and so forth. - *

- * The resulting Observable returned from zip will invoke - * onNext as many times as the number of onNext invocations of the - * source Observable that emits the fewest items. - *

- * - * - * @param ws - * A collection of source Observables - * @param function - * a function that, when applied to an item emitted by each of the source - * Observables, results in an item that will be emitted by the resulting Observable - * @return an Observable that emits the zipped results - */ - public static Observable zip(Collection> ws, final Object function) { - @SuppressWarnings({ "unchecked" }) - final FuncN _f = Functions.from(function); - return zip(ws, _f); - } - - /** - * Combines the given observables, emitting an event containing an aggregation of the latest values of each of the source observables - * each time an event is received from one of the source observables, where the aggregation is defined by the given function. - * @param w0 - * The first source observable. - * @param w1 - * The second source observable. - * @param combineFunction - * The aggregation function used to combine the source observable values. + * The second source observable. + * @param combineFunction + * The aggregation function used to combine the source observable values. * @return A function from an observer to a subscription. This can be used to create an observable from. */ - public static Observable combineLatest(Observable w0, Observable w1, Func2 combineFunction) { + public static Observable combineLatest(Observable w0, Observable w1, Func2 combineFunction) { return create(OperationCombineLatest.combineLatest(w0, w1, combineFunction)); } - + /** * @see #combineLatest(Observable, Observable, Func2) */ - public static Observable combineLatest(Observable w0, Observable w1, Observable w2, Func3 combineFunction) { + public static Observable combineLatest(Observable w0, Observable w1, Observable w2, Func3 combineFunction) { return create(OperationCombineLatest.combineLatest(w0, w1, w2, combineFunction)); } /** * @see #combineLatest(Observable, Observable, Func2) */ - public static Observable combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Func4 combineFunction) { + public static Observable combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Func4 combineFunction) { return create(OperationCombineLatest.combineLatest(w0, w1, w2, w3, combineFunction)); } - + /** * Filters an Observable by discarding any of its emissions that do not meet some test. *

@@ -2848,44 +1904,19 @@ public Observable filter(Func1 predicate) { } /** - * Registers an {@link Action0} to be called when this Observable invokes - * {@link Observer#onCompleted onCompleted} or {@link Observer#onError onError}. + * Registers an {@link Action0} to be called when this Observable invokes {@link Observer#onCompleted onCompleted} or {@link Observer#onError onError}. *

* * * @param action * an {@link Action0} to be invoked when the source Observable finishes - * @return an Observable that emits the same items as the source Observable, then invokes the - * {@link Action0} + * @return an Observable that emits the same items as the source Observable, then invokes the {@link Action0} * @see MSDN: Observable.Finally Method */ public Observable finallyDo(Action0 action) { return create(OperationFinally.finallyDo(this, action)); } - /** - * Filters an Observable by discarding any items it emits that do not meet some test. - *

- * - * - * @param callback - * a function that evaluates an item emitted by the source Observable, returning - * true if it passes the filter - * @return an Observable that emits only those items in the original Observable that the filter - * evaluates as "true" - */ - public Observable filter(final Object callback) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(callback); - return filter(this, new Func1() { - - @Override - public Boolean call(T t1) { - return (Boolean) _f.call(t1); - } - }); - } - /** * Creates a new Observable by applying a function that you supply to each item emitted by * the source Observable, where that function returns an Observable, and then merging those @@ -2907,27 +1938,6 @@ public Observable flatMap(Func1> func) { return mapMany(func); } - /** - * Creates a new Observable by applying a function that you supply to each item emitted by - * the source Observable, where that function returns an Observable, and then merging those - * resulting Observables and emitting the results of this merger. - *

- * - *

- * Note: mapMany and flatMap are equivalent. - * - * @param callback - * a function that, when applied to an item emitted by the source Observable, returns - * an Observable - * @return an Observable that emits the result of applying the transformation function to each - * item emitted by the source Observable and merging the results of the Observables - * obtained from this transformation. - * @see #mapMany(Object) - */ - public Observable flatMap(final Object callback) { - return mapMany(callback); - } - /** * Filters an Observable by discarding any items it emits that do not meet some test. *

@@ -2958,30 +1968,6 @@ public Observable map(Func1 func) { return map(this, func); } - /** - * Applies a function of your choosing to each item emitted by an Observable, and returns this - * transformation as a new Observable. - *

- * - * - * @param callback - * a function to apply to each item emitted by the Observable - * @return an Observable that emits the items from the source Observable, transformed by the - * given function - */ - public Observable map(final Object callback) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(callback); - return map(this, new Func1() { - - @Override - @SuppressWarnings("unchecked") - public R call(T t1) { - return (R) _f.call(t1); - } - }); - } - /** * Creates a new Observable by applying a function that you supply to each item emitted by * the source Observable, where that function returns an Observable, and then merging those @@ -3004,39 +1990,7 @@ public Observable mapMany(Func1> func) { } /** - * Creates a new Observable by applying a function that you supply to each item emitted by - * the source Observable, where that function returns an Observable, and then merging those - * resulting Observables and emitting the results of this merger. - *

- * - *

- * Note: mapMany and flatMap are equivalent. - * - * @param callback - * a function that, when applied to an item emitted by the source Observable, returns - * an Observable - * @return an Observable that emits the result of applying the transformation function to each - * item emitted by the source Observable and merging the results of the Observables - * obtained from this transformation. - * @see #flatMap(Object) - */ - public Observable mapMany(final Object callback) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(callback); - return mapMany(this, new Func1>() { - - @Override - @SuppressWarnings("unchecked") - public Observable call(T t1) { - return (Observable) _f.call(t1); - } - }); - } - - /** - * Turns all of the notifications from a source Observable into {@link Observer#onNext onNext} - * emissions, and marks them with their original notification types within {@link Notification} - * objects. + * Turns all of the notifications from a source Observable into {@link Observer#onNext onNext} emissions, and marks them with their original notification types within {@link Notification} objects. *

* * @@ -3083,8 +2037,7 @@ public Observable observeOn(Scheduler scheduler) { *

* * - * @return an Observable that emits the items and notifications embedded in the - * {@link Notification} objects emitted by the source Observable + * @return an Observable that emits the items and notifications embedded in the {@link Notification} objects emitted by the source Observable * @see MSDN: Observable.dematerialize * @throws Exception * if the source Observable is not of type {@code Observable>}. @@ -3095,8 +2048,7 @@ public Observable dematerialize() { } /** - * Instruct an Observable to pass control to another Observable rather than invoking - * {@link Observer#onError onError} if it encounters an error. + * Instruct an Observable to pass control to another Observable rather than invoking {@link Observer#onError onError} if it encounters an error. *

* *

@@ -3107,8 +2059,7 @@ public Observable dematerialize() { * function that returns an Observable (resumeFunction) to * onErrorResumeNext, if the original Observable encounters an error, instead of * invoking its Observer's onError method, it will instead relinquish control to - * the Observable returned from resumeFunction, which will invoke the Observer's - * {@link Observer#onNext onNext} method if it is able to do so. In such a case, because no + * the Observable returned from resumeFunction, which will invoke the Observer's {@link Observer#onNext onNext} method if it is able to do so. In such a case, because no * Observable necessarily invokes onError, the Observer may never know that an * error happened. *

@@ -3125,44 +2076,7 @@ public Observable onErrorResumeNext(final Func1> res } /** - * Instruct an Observable to emit an item (returned by a specified function) rather than - * invoking {@link Observer#onError onError} if it encounters an error. - *

- * - *

- * By default, when an Observable encounters an error that prevents it from emitting the - * expected item to its {@link Observer}, the Observable invokes its Observer's - * onError method, and then quits without invoking any more of its Observer's - * methods. The onErrorReturn method changes this behavior. If you pass a function - * (resumeFunction) to an Observable's onErrorReturn method, if the - * original Observable encounters an error, instead of invoking its Observer's - * onError function, it will instead pass the return value of - * resumeFunction to the Observer's {@link Observer#onNext onNext} method. - *

- * You can use this to prevent errors from propagating or to supply fallback data should errors - * be encountered. - * - * @param resumeFunction - * a function that returns an item that the Observable will emit if the source - * Observable encounters an error - * @return the original Observable with appropriately modified behavior - */ - public Observable onErrorResumeNext(final Object resumeFunction) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(resumeFunction); - return onErrorResumeNext(this, new Func1>() { - - @Override - @SuppressWarnings("unchecked") - public Observable call(Exception e) { - return (Observable) _f.call(e); - } - }); - } - - /** - * Instruct an Observable to pass control to another Observable rather than invoking - * {@link Observer#onError onError} if it encounters an error. + * Instruct an Observable to pass control to another Observable rather than invoking {@link Observer#onError onError} if it encounters an error. *

* *

@@ -3173,8 +2087,7 @@ public Observable call(Exception e) { * another Observable (resumeSequence) to an Observable's * onErrorResumeNext method, if the original Observable encounters an error, * instead of invoking its Observer's onError method, it will instead relinquish - * control to resumeSequence which will invoke the Observer's - * {@link Observer#onNext onNext} method if it is able to do so. In such a case, because no + * control to resumeSequence which will invoke the Observer's {@link Observer#onNext onNext} method if it is able to do so. In such a case, because no * Observable necessarily invokes onError, the Observer may never know that an * error happened. *

@@ -3217,42 +2130,6 @@ public Observable onErrorReturn(Func1 resumeFunction) { return onErrorReturn(this, resumeFunction); } - /** - * Instruct an Observable to emit a particular item rather than invoking - * {@link Observer#onError onError} if it encounters an error. - *

- * - *

- * By default, when an Observable encounters an error that prevents it from emitting the - * expected item to its {@link Observer}, the Observable invokes its Observer's - * onError method, and then quits without invoking any more of its Observer's - * methods. The onErrorReturn method changes this behavior. If you pass a function - * (resumeFunction) to an Observable's onErrorReturn method, if the - * original Observable encounters an error, instead of invoking its Observer's - * onError function, it will instead pass the return value of - * resumeFunction to the Observer's {@link Observer#onNext onNext} method. - *

- * You can use this to prevent errors from propagating or to supply fallback data should errors - * be encountered. - * - * @param resumeFunction - * a function that returns an item that the new Observable will emit if the source - * Observable encounters an error - * @return the original Observable with appropriately modified behavior - */ - public Observable onErrorReturn(final Object resumeFunction) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(resumeFunction); - return onErrorReturn(this, new Func1() { - - @Override - @SuppressWarnings("unchecked") - public T call(Exception e) { - return (T) _f.call(e); - } - }); - } - /** * Returns an Observable that applies a function of your choosing to the first item emitted by a * source Observable, then feeds the result of that function along with the second item emitted @@ -3280,8 +2157,7 @@ public Observable reduce(Func2 accumulator) { /** * Returns a {@link ConnectableObservable} that shares a single subscription to the underlying - * Observable that will replay all of its items and notifications to any future - * {@link Observer}. + * Observable that will replay all of its items and notifications to any future {@link Observer}. *

* * @@ -3313,49 +2189,26 @@ public Observable cache() { } /** - * Returns a {@link ConnectableObservable}, which waits until its - * {@link ConnectableObservable#connect connect} method is called before it begins emitting + * Returns a {@link ConnectableObservable}, which waits until its {@link ConnectableObservable#connect connect} method is called before it begins emitting * items to those {@link Observer}s that have subscribed to it. *

* * * @return a {@link ConnectableObservable} that upon connection causes the source Observable to - * emit items to its {@link Observer}s + * emit items to its {@link Observer}s */ public ConnectableObservable publish() { return publish(this); } - /** - * A version of reduce() for use by dynamic languages. - *

- * - * - * @see #reduce(Func2) - */ - public Observable reduce(Object accumulator) { - return reduce(this, accumulator); - } - /** * Synonymous with reduce(). *

* - * - * @see #reduce(Func2) - */ - public Observable aggregate(Func2 accumulator) { - return aggregate(this, accumulator); - } - - /** - * A version of aggregate() for use by dynamic languages. - *

- * * * @see #reduce(Func2) */ - public Observable aggregate(Object accumulator) { + public Observable aggregate(Func2 accumulator) { return aggregate(this, accumulator); } @@ -3386,39 +2239,15 @@ public Observable reduce(R initialValue, Func2 accumulator) { return reduce(this, initialValue, accumulator); } - /** - * A version of reduce() for use by dynamic languages. - *

- * - * - * @see #reduce(Object, Func2) - */ - public Observable reduce(R initialValue, Object accumulator) { - return reduce(this, initialValue, accumulator); - } - /** * Synonymous with reduce(). *

* - * - * @see #reduce(Object, Func2) */ public Observable aggregate(R initialValue, Func2 accumulator) { return aggregate(this, initialValue, accumulator); } - /** - * A version of aggregate() for use by dynamic languages. - *

- * - * - * @see #reduce(Object, Func2) - */ - public Observable aggregate(R initialValue, Object accumulator) { - return aggregate(this, initialValue, accumulator); - } - /** * Returns an Observable that applies a function of your choosing to the first item emitted by a * source Observable, then feeds the result of that function along with the second item emitted @@ -3434,8 +2263,7 @@ public Observable aggregate(R initialValue, Object accumulator) { * * @param accumulator * an accumulator function to be invoked on each item emitted by the source - * Observable, whose result will be emitted to {@link Observer}s via - * {@link Observer#onNext onNext} and used in the next accumulator call. + * Observable, whose result will be emitted to {@link Observer}s via {@link Observer#onNext onNext} and used in the next accumulator call. * @return an Observable that emits the results of each call to the accumulator function * @see MSDN: Observable.Scan */ @@ -3479,17 +2307,6 @@ public Observable sample(long period, TimeUnit unit, Scheduler scheduler) { return create(OperationSample.sample(this, period, unit, scheduler)); } - /** - * A version of scan() for use by dynamic languages. - *

- * - * - * @see #scan(Func2) - */ - public Observable scan(final Object accumulator) { - return scan(this, accumulator); - } - /** * Returns an Observable that applies a function of your choosing to the first item emitted by a * source Observable, then feeds the result of that function along with the second item emitted @@ -3507,27 +2324,14 @@ public Observable scan(final Object accumulator) { * the initial (seed) accumulator value * @param accumulator * an accumulator function to be invoked on each item emitted by the source - * Observable, whose result will be emitted to {@link Observer}s via - * {@link Observer#onNext onNext} and used in the next accumulator call. + * Observable, whose result will be emitted to {@link Observer}s via {@link Observer#onNext onNext} and used in the next accumulator call. * @return an Observable that emits the results of each call to the accumulator function - * @see MSDN: - * Observable.Scan + * @see MSDN: Observable.Scan */ public Observable scan(R initialValue, Func2 accumulator) { return scan(this, initialValue, accumulator); } - /** - * A version of scan() for use by dynamic languages. - *

- * - * - * @see #scan(Object, Func2) - */ - public Observable scan(final R initialValue, final Object accumulator) { - return scan(this, initialValue, accumulator); - } - /** * Returns an Observable that emits a Boolean that indicates whether all of the items emitted by * the source Observable satisfy a condition. @@ -3543,21 +2347,6 @@ public Observable all(Func1 predicate) { return all(this, predicate); } - /** - * Returns an Observable that emits a Boolean that indicates whether all of the items emitted by - * the source Observable satisfy a condition. - *

- * - * - * @param predicate - * a function that evaluates an item and returns a Boolean - * @return an Observable that emits true if all items emitted by the source - * Observable satisfy the predicate; otherwise, false - */ - public Observable all(Object predicate) { - return all(this, predicate); - } - /** * Returns an Observable that skips the first num items emitted by the source * Observable and emits the remainder. @@ -3582,8 +2371,7 @@ public Observable skip(int num) { *

* *

- * This method returns an Observable that will invoke a subscribing {@link Observer}'s - * {@link Observer#onNext onNext} function a maximum of num times before invoking + * This method returns an Observable that will invoke a subscribing {@link Observer}'s {@link Observer#onNext onNext} function a maximum of num times before invoking * {@link Observer#onCompleted onCompleted}. * * @param num @@ -3612,22 +2400,6 @@ public Observable takeWhile(final Func1 predicate) { return takeWhile(this, predicate); } - /** - * Returns an Observable that emits items emitted by the source Observable so long as a - * specified condition is true. - *

- * - * - * @param predicate - * a function that evaluates an item emitted by the source Observable and returns a - * Boolean - * @return an Observable that emits the items from the source Observable so long as each item - * satisfies the condition defined by predicate - */ - public Observable takeWhile(final Object predicate) { - return takeWhile(this, predicate); - } - /** * Returns an Observable that emits the items emitted by a source Observable so long as a given * predicate remains true, where the predicate can operate on both the item and its index @@ -3645,24 +2417,6 @@ public Observable takeWhileWithIndex(final Func2 predica return takeWhileWithIndex(this, predicate); } - /** - * Returns an Observable that emits the items emitted by a source Observable so long as a given - * predicate remains true, where the predicate can operate on both the item and its index - * relative to the complete sequence. - *

- * - * - * @param predicate - * a function that evaluates an item emitted by the source Observable and returns a - * Boolean; the second parameter of the function represents the index of the source - * item - * @return an Observable that emits items from the source Observable so long as the predicate - * continues to return true for each item, then completes - */ - public Observable takeWhileWithIndex(final Object predicate) { - return takeWhileWithIndex(this, predicate); - } - /** * Returns an Observable that emits only the last count items emitted by the source * Observable. @@ -3703,12 +2457,10 @@ public Observable takeUntil(Observable other) { *

* *

- * Normally, an Observable that returns multiple items will do so by invoking its - * {@link Observer}'s {@link Observer#onNext onNext} method for each such item. You can change + * Normally, an Observable that returns multiple items will do so by invoking its {@link Observer}'s {@link Observer#onNext onNext} method for each such item. You can change * this behavior, instructing the Observable to compose a list of all of these items and then to * invoke the Observer's onNext function once, passing it the entire list, by - * calling the Observable's toList method prior to calling its {@link #subscribe} - * method. + * calling the Observable's toList method prior to calling its {@link #subscribe} method. *

* Be careful not to use this operator on Observables that emit infinite or very large numbers * of items, as you do not have the option to unsubscribe. @@ -3751,21 +2503,6 @@ public Observable> toSortedList(Func2 sortFunction) { return toSortedList(this, sortFunction); } - /** - * Return an Observable that emits the items emitted by the source Observable, in a sorted - * order based on a specified comparison function - *

- * - * - * @param sortFunction - * a function that compares two items emitted by the source Observable and returns - * an Integer that indicates their sort order - * @return an Observable that emits the items from the source Observable in sorted order - */ - public Observable> toSortedList(final Object sortFunction) { - return toSortedList(this, sortFunction); - } - /** * Emit a specified set of items before beginning to emit items from the source Observable. *

@@ -3801,28 +2538,6 @@ public Observable startWith(T... values) { public Observable> groupBy(final Func1 keySelector, final Func1 elementSelector) { return groupBy(this, keySelector, elementSelector); } - - /** - * Groups the items emitted by an Observable according to a specified criterion, and emits these - * grouped items as {@link GroupedObservable}s, one GroupedObservable per group. - *

- * - * - * @param keySelector - * a function that extracts the key from an item - * @param elementSelector - * a function to map a source item to an item in a {@link GroupedObservable} - * @param - * the key type - * @param - * the type of items emitted by the resulting {@link GroupedObservable}s - * @return an Observable that emits {@link GroupedObservable}s, each of which corresponds to a - * unique key value and emits items representing items from the source Observable that - * share that key value - */ - public Observable> groupBy(final Object keySelector, final Object elementSelector) { - return groupBy(this, keySelector, elementSelector); - } /** * Groups the items emitted by an Observable according to a specified criterion, and emits these @@ -3841,31 +2556,12 @@ public Observable> groupBy(final Object keySelect public Observable> groupBy(final Func1 keySelector) { return groupBy(this, keySelector); } - - /** - * Groups the items emitted by an Observable according to a specified criterion, and emits these - * grouped items as {@link GroupedObservable}s, one GroupedObservable per group. - *

- * - * - * @param keySelector - * a function that extracts the key for each item - * @param - * the key type - * @return an Observable that emits {@link GroupedObservable}s, each of which corresponds to a - * unique key value and emits items representing items from the source Observable that - * share that key value - */ - public Observable> groupBy(final Object keySelector) { - return groupBy(this, keySelector); - } /** * Converts an Observable into a {@link BlockingObservable} (an Observable with blocking * operators). - * - * @see Blocking - * Observable Operators + * + * @see Blocking Observable Operators */ public BlockingObservable toBlockingObservable() { return BlockingObservable.from(this); @@ -4391,10 +3087,10 @@ public void run() { }).start(); return Subscriptions.empty(); } - }).subscribe(new Action1() { + }).subscribe(new Action1() { @Override - public void call(Object t1) { + public void call(String t1) { } diff --git a/rxjava-core/src/main/java/rx/observables/BlockingObservable.java b/rxjava-core/src/main/java/rx/observables/BlockingObservable.java index 3ef4dbcebc..62ebdb1854 100644 --- a/rxjava-core/src/main/java/rx/observables/BlockingObservable.java +++ b/rxjava-core/src/main/java/rx/observables/BlockingObservable.java @@ -117,22 +117,6 @@ public static T last(final Observable source, final Func1 pre return last(source.filter(predicate)); } - /** - * Returns the last item emitted by an {@link Observable} that matches a given predicate. - *

- * - * - * @param source - * the source {@link Observable} - * @param predicate - * a predicate function to evaluate items emitted by the {@link Observable} - * @return the last item emitted by the {@link Observable} for which the predicate function - * returns true - */ - public static T last(final Observable source, final Object predicate) { - return last(source.filter(predicate)); - } - /** * Returns the last item emitted by an {@link Observable}, or a default value if no item is * emitted. @@ -173,35 +157,6 @@ public static T lastOrDefault(Observable source, T defaultValue, Func1 - * - * - * @param source - * the source {@link Observable} - * @param defaultValue - * a default value to return if the {@link Observable} emits no matching items - * @param predicate - * a predicate function to evaluate items emitted by the {@link Observable} - * @param - * the type of items emitted by the {@link Observable} - * @return the last item emitted by an {@link Observable} that matches the predicate, or the - * default value if no matching item is emitted - */ - public static T lastOrDefault(Observable source, T defaultValue, Object predicate) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(predicate); - - return lastOrDefault(source, defaultValue, new Func1() { - @Override - public Boolean call(T args) { - return (Boolean) _f.call(args); - } - }); - } - /** * Returns an {@link Iterable} that always returns the item most recently emitted by an * {@link Observable}. @@ -293,24 +248,6 @@ public static T single(Observable source, Func1 predicate) { return from(source).single(predicate); } - /** - * If the {@link Observable} completes after emitting a single item that matches a given - * predicate, return that item, otherwise throw an exception. - * - * - * @param source - * the source {@link Observable} - * @param predicate - * a predicate function to evaluate items emitted by the {@link Observable} - * @return the single item emitted by the source {@link Observable} that matches the predicate - * @throws IllegalStateException - * if the {@link Observable} does not emit exactly one item that matches the - * predicate - */ - public static T single(Observable source, Object predicate) { - return from(source).single(predicate); - } - /** * If the {@link Observable} completes after emitting a single item, return that item, otherwise * return a default value. @@ -347,25 +284,6 @@ public static T singleOrDefault(Observable source, T defaultValue, Func1< return from(source).singleOrDefault(defaultValue, predicate); } - /** - * If the {@link Observable} completes after emitting a single item that matches a given - * predicate, return that item, otherwise return a default value. - *

- * - * - * @param source - * the source {@link Observable} - * @param defaultValue - * a default value to return if the {@link Observable} emits no matching items - * @param predicate - * a predicate function to evaluate items emitted by the {@link Observable} - * @return the single item emitted by the source {@link Observable} that matches the predicate, - * or a default value if no such value is emitted - */ - public static T singleOrDefault(Observable source, T defaultValue, Object predicate) { - return from(source).singleOrDefault(defaultValue, predicate); - } - /** * Returns a {@link Future} representing the single value emitted by an {@link Observable}. *

@@ -476,45 +394,6 @@ public void onNext(T args) { } } - /** - * Invoke a method on each item emitted by the {@link Observable}; block until the Observable - * completes. - *

- * NOTE: This will block even if the Observable is asynchronous. - *

- * This is similar to {@link #subscribe(Observer)}, but it blocks. Because it blocks it does - * not need the {@link Observer#onCompleted()} or {@link Observer#onError(Exception)} methods. - *

- * - * - * @param o - * the {@link Action1} to invoke for every item emitted by the {@link Observable} - * @throws RuntimeException - * if an error occurs - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - public void forEach(final Object o) { - if (o instanceof Action1) { - // in case a dynamic language is not correctly handling the overloaded methods and we receive an Action1 just forward to the correct method. - forEach((Action1) o); - } - - // lookup and memoize onNext - if (o == null) { - throw new RuntimeException("onNext must be implemented"); - } - final FuncN onNext = Functions.from(o); - - forEach(new Action1() { - - @Override - public void call(Object args) { - onNext.call(args); - } - - }); - } - /** * Returns an {@link Iterator} that iterates over all items emitted by a specified * {@link Observable}. @@ -555,27 +434,6 @@ public T last(final Func1 predicate) { return last(this, predicate); } - /** - * Returns the last item emitted by a specified {@link Observable} that matches a predicate. - *

- * - * - * @param predicate - * a predicate function to evaluate items emitted by the {@link Observable} - * @return the last item emitted by the {@link Observable} that matches the predicate - */ - public T last(final Object predicate) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(predicate); - - return last(this, new Func1() { - @Override - public Boolean call(T args) { - return (Boolean) _f.call(args); - } - }); - } - /** * Returns the last item emitted by a specified {@link Observable}, or a default value if no * items are emitted. @@ -620,23 +478,6 @@ public T lastOrDefault(T defaultValue, Func1 predicate) { return lastOrDefault(this, defaultValue, predicate); } - /** - * Returns the last item emitted by a specified {@link Observable} that matches a predicate, or - * a default value if no such items are emitted. - *

- * - * - * @param defaultValue - * a default value to return if the {@link Observable} emits no matching items - * @param predicate - * a predicate function to evaluate items emitted by the {@link Observable} - * @return the last item emitted by the {@link Observable} that matches the predicate, or the - * default value if no matching items are emitted - */ - public T lastOrDefault(T defaultValue, Object predicate) { - return lastOrDefault(this, defaultValue, predicate); - } - /** * Returns an {@link Iterable} that always returns the item most recently emitted by an * {@link Observable}. @@ -692,28 +533,6 @@ public T single(Func1 predicate) { return _singleOrDefault(from(this.filter(predicate)), false, null); } - /** - * If the {@link Observable} completes after emitting a single item that matches a given - * predicate, return that item, otherwise throw an exception. - *

- * - * - * @param predicate - * a predicate function to evaluate items emitted by the {@link Observable} - * @return the single item emitted by the source {@link Observable} that matches the predicate - */ - public T single(Object predicate) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(predicate); - - return single(new Func1() { - @Override - public Boolean call(T t) { - return (Boolean) _f.call(t); - } - }); - } - /** * If the {@link Observable} completes after emitting a single item, return that item; if it * emits more than one item, throw an exception; if it emits no items, return a default value. @@ -747,32 +566,6 @@ public T singleOrDefault(T defaultValue, Func1 predicate) { return _singleOrDefault(from(this.filter(predicate)), true, defaultValue); } - /** - * If the {@link Observable} completes after emitting a single item that matches a predicate, - * return that item; if it emits more than one such item, throw an exception; if it emits no - * items, return a default value. - *

- * - * - * @param defaultValue - * a default value to return if the {@link Observable} emits no matching items - * @param predicate - * a predicate function to evaluate items emitted by the {@link Observable} - * @return the single item emitted by the {@link Observable} that matches the predicate, or the - * default value if no such items are emitted - */ - public T singleOrDefault(T defaultValue, final Object predicate) { - @SuppressWarnings("rawtypes") - final FuncN _f = Functions.from(predicate); - - return singleOrDefault(defaultValue, new Func1() { - @Override - public Boolean call(T t) { - return (Boolean) _f.call(t); - } - }); - } - /** * Returns a {@link Future} representing the single value emitted by an {@link Observable}. *

diff --git a/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java b/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java index 77996bab67..c3c0ee3235 100644 --- a/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java +++ b/rxjava-core/src/main/java/rx/operators/OperationCombineLatest.java @@ -62,7 +62,7 @@ public class OperationCombineLatest { * The aggregation function used to combine the source observable values. * @return A function from an observer to a subscription. This can be used to create an observable from. */ - public static Func1, Subscription> combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction) { + public static Func1, Subscription> combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction) { Aggregator a = new Aggregator(Functions.fromFunc(combineLatestFunction)); a.addObserver(new CombineObserver(a, w0)); a.addObserver(new CombineObserver(a, w1)); @@ -72,7 +72,7 @@ public static Func1, Subscription> combineLatest /** * @see #combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction) */ - public static Func1, Subscription> combineLatest(Observable w0, Observable w1, Observable w2, Func3 combineLatestFunction) { + public static Func1, Subscription> combineLatest(Observable w0, Observable w1, Observable w2, Func3 combineLatestFunction) { Aggregator a = new Aggregator(Functions.fromFunc(combineLatestFunction)); a.addObserver(new CombineObserver(a, w0)); a.addObserver(new CombineObserver(a, w1)); @@ -83,7 +83,7 @@ public static Func1, Subscription> combineLa /** * @see #combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction) */ - public static Func1, Subscription> combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Func4 combineLatestFunction) { + public static Func1, Subscription> combineLatest(Observable w0, Observable w1, Observable w2, Observable w3, Func4 combineLatestFunction) { Aggregator a = new Aggregator(Functions.fromFunc(combineLatestFunction)); a.addObserver(new CombineObserver(a, w0)); a.addObserver(new CombineObserver(a, w1)); @@ -93,11 +93,11 @@ public static Func1, Subscription> combi } private static class CombineObserver implements Observer { - final Observable w; - final Aggregator a; + final Observable w; + final Aggregator a; private Subscription subscription; - public CombineObserver(Aggregator a, Observable w) { + public CombineObserver(Aggregator a, Observable w) { this.a = a; this.w = w; } @@ -130,9 +130,9 @@ public void onNext(T args) { * whenever we have received an event from one of the observables, as soon as each Observable has received * at least one event. */ - private static class Aggregator implements Func1, Subscription> { + private static class Aggregator implements Func1, Subscription> { - private volatile Observer observer; + private volatile Observer observer; private final FuncN combineLatestFunction; private final AtomicBoolean running = new AtomicBoolean(true); @@ -169,7 +169,7 @@ void addObserver(CombineObserver w) { * * @param w The observer that has completed. */ - void complete(CombineObserver w) { + void complete(CombineObserver w) { int completed = numCompleted.incrementAndGet(); // if all CombineObservers are completed, we mark the whole thing as completed if (completed == observers.size()) { @@ -199,7 +199,7 @@ void error(Exception e) { * @param w * @param arg */ - void next(CombineObserver w, T arg) { + void next(CombineObserver w, T arg) { if (observer == null) { throw new RuntimeException("This shouldn't be running if an Observer isn't registered"); } @@ -232,7 +232,7 @@ void next(CombineObserver w, T arg) { } @Override - public Subscription call(Observer observer) { + public Subscription call(Observer observer) { if (this.observer != null) { throw new IllegalStateException("Only one Observer can subscribe to this Observable."); } diff --git a/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java b/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java index 5261e4dbdf..5b90a2bbdc 100644 --- a/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java +++ b/rxjava-core/src/main/java/rx/subjects/AsyncSubject.java @@ -122,9 +122,8 @@ public static class UnitTest { @Test public void testNeverCompleted() { - AsyncSubject subject = AsyncSubject.create(); + AsyncSubject subject = AsyncSubject.create(); - @SuppressWarnings("unchecked") Observer aObserver = mock(Observer.class); subject.subscribe(aObserver); @@ -144,9 +143,8 @@ private void assertNeverCompletedObserver(Observer aObserver) @Test public void testCompleted() { - AsyncSubject subject = AsyncSubject.create(); + AsyncSubject subject = AsyncSubject.create(); - @SuppressWarnings("unchecked") Observer aObserver = mock(Observer.class); subject.subscribe(aObserver); @@ -167,9 +165,8 @@ private void assertCompletedObserver(Observer aObserver) @Test public void testError() { - AsyncSubject subject = AsyncSubject.create(); + AsyncSubject subject = AsyncSubject.create(); - @SuppressWarnings("unchecked") Observer aObserver = mock(Observer.class); subject.subscribe(aObserver); @@ -193,7 +190,7 @@ private void assertErrorObserver(Observer aObserver) @Test public void testUnsubscribeBeforeCompleted() { - AsyncSubject subject = AsyncSubject.create(); + AsyncSubject subject = AsyncSubject.create(); @SuppressWarnings("unchecked") Observer aObserver = mock(Observer.class); diff --git a/rxjava-core/src/main/java/rx/subjects/PublishSubject.java b/rxjava-core/src/main/java/rx/subjects/PublishSubject.java index 0714ecfe50..1284af52b4 100644 --- a/rxjava-core/src/main/java/rx/subjects/PublishSubject.java +++ b/rxjava-core/src/main/java/rx/subjects/PublishSubject.java @@ -194,12 +194,12 @@ public static class UnitTest { @Test public void test() { PublishSubject subject = PublishSubject.create(); - final AtomicReference>> actualRef = new AtomicReference>>(); + final AtomicReference>> actualRef = new AtomicReference>>(); Observable>> wNotificationsList = subject.materialize().toList(); - wNotificationsList.subscribe(new Action1>>() { + wNotificationsList.subscribe(new Action1>>() { @Override - public void call(List> actual) { + public void call(List> actual) { actualRef.set(actual); } }); @@ -244,9 +244,8 @@ public void unsubscribe() { @Test public void testCompleted() { - PublishSubject subject = PublishSubject.create(); + PublishSubject subject = PublishSubject.create(); - @SuppressWarnings("unchecked") Observer aObserver = mock(Observer.class); subject.subscribe(aObserver); @@ -255,7 +254,6 @@ public void testCompleted() { subject.onNext("three"); subject.onCompleted(); - @SuppressWarnings("unchecked") Observer anotherObserver = mock(Observer.class); subject.subscribe(anotherObserver); @@ -285,9 +283,8 @@ private void assertNeverObserver(Observer aObserver) @Test public void testError() { - PublishSubject subject = PublishSubject.create(); + PublishSubject subject = PublishSubject.create(); - @SuppressWarnings("unchecked") Observer aObserver = mock(Observer.class); subject.subscribe(aObserver); @@ -296,7 +293,6 @@ public void testError() { subject.onNext("three"); subject.onError(testException); - @SuppressWarnings("unchecked") Observer anotherObserver = mock(Observer.class); subject.subscribe(anotherObserver); @@ -319,9 +315,8 @@ private void assertErrorObserver(Observer aObserver) @Test public void testSubscribeMidSequence() { - PublishSubject subject = PublishSubject.create(); + PublishSubject subject = PublishSubject.create(); - @SuppressWarnings("unchecked") Observer aObserver = mock(Observer.class); subject.subscribe(aObserver); @@ -330,7 +325,6 @@ public void testSubscribeMidSequence() { assertObservedUntilTwo(aObserver); - @SuppressWarnings("unchecked") Observer anotherObserver = mock(Observer.class); subject.subscribe(anotherObserver); @@ -352,9 +346,8 @@ private void assertCompletedStartingWithThreeObserver(Observer aObserver @Test public void testUnsubscribeFirstObserver() { - PublishSubject subject = PublishSubject.create(); + PublishSubject subject = PublishSubject.create(); - @SuppressWarnings("unchecked") Observer aObserver = mock(Observer.class); Subscription subscription = subject.subscribe(aObserver); @@ -364,7 +357,6 @@ public void testUnsubscribeFirstObserver() { subscription.unsubscribe(); assertObservedUntilTwo(aObserver); - @SuppressWarnings("unchecked") Observer anotherObserver = mock(Observer.class); subject.subscribe(anotherObserver); @@ -396,9 +388,8 @@ private void assertObservedUntilTwo(Observer aObserver) */ @Test public void testUnsubscribeAfterOnCompleted() { - PublishSubject subject = PublishSubject.create(); + PublishSubject subject = PublishSubject.create(); - @SuppressWarnings("unchecked") Observer anObserver = mock(Observer.class); subject.subscribe(anObserver); @@ -412,7 +403,6 @@ public void testUnsubscribeAfterOnCompleted() { inOrder.verify(anObserver, times(1)).onCompleted(); inOrder.verify(anObserver, Mockito.never()).onError(any(Exception.class)); - @SuppressWarnings("unchecked") Observer anotherObserver = mock(Observer.class); subject.subscribe(anotherObserver); @@ -425,10 +415,9 @@ public void testUnsubscribeAfterOnCompleted() { @Test public void testUnsubscribeAfterOnError() { - PublishSubject subject = PublishSubject.create(); + PublishSubject subject = PublishSubject.create(); RuntimeException exception = new RuntimeException("failure"); - @SuppressWarnings("unchecked") Observer anObserver = mock(Observer.class); subject.subscribe(anObserver); @@ -442,7 +431,6 @@ public void testUnsubscribeAfterOnError() { inOrder.verify(anObserver, times(1)).onError(exception); inOrder.verify(anObserver, Mockito.never()).onCompleted(); - @SuppressWarnings("unchecked") Observer anotherObserver = mock(Observer.class); subject.subscribe(anotherObserver); diff --git a/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java b/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java index ff5f2badcc..026ab5df61 100644 --- a/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java +++ b/rxjava-core/src/main/java/rx/subjects/ReplaySubject.java @@ -185,7 +185,7 @@ public static class UnitTest { @SuppressWarnings("unchecked") @Test public void testCompleted() { - ReplaySubject subject = ReplaySubject.create(); + ReplaySubject subject = ReplaySubject.create(); Observer o1 = mock(Observer.class); subject.subscribe(o1); @@ -222,7 +222,7 @@ private void assertCompletedObserver(Observer aObserver) @SuppressWarnings("unchecked") @Test public void testError() { - ReplaySubject subject = ReplaySubject.create(); + ReplaySubject subject = ReplaySubject.create(); Observer aObserver = mock(Observer.class); subject.subscribe(aObserver); @@ -255,7 +255,7 @@ private void assertErrorObserver(Observer aObserver) @SuppressWarnings("unchecked") @Test public void testSubscribeMidSequence() { - ReplaySubject subject = ReplaySubject.create(); + ReplaySubject subject = ReplaySubject.create(); Observer aObserver = mock(Observer.class); subject.subscribe(aObserver); @@ -279,7 +279,7 @@ public void testSubscribeMidSequence() { @SuppressWarnings("unchecked") @Test public void testUnsubscribeFirstObserver() { - ReplaySubject subject = ReplaySubject.create(); + ReplaySubject subject = ReplaySubject.create(); Observer aObserver = mock(Observer.class); Subscription subscription = subject.subscribe(aObserver); diff --git a/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java b/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java index 1db0b7a660..41055f0672 100644 --- a/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java +++ b/rxjava-core/src/main/java/rx/subscriptions/Subscriptions.java @@ -79,23 +79,6 @@ public static CompositeSubscription create(Subscription... subscriptions) { return new CompositeSubscription(subscriptions); } - /** - * A {@link Subscription} implemented via an anonymous function (such as closures from other languages). - * - * @return {@link Subscription} - */ - public static Subscription create(final Object unsubscribe) { - final FuncN f = Functions.from(unsubscribe); - return new Subscription() { - - @Override - public void unsubscribe() { - f.call(); - } - - }; - } - /** * A {@link Subscription} that does nothing when its unsubscribe method is called. */ diff --git a/rxjava-core/src/main/java/rx/util/functions/Action.java b/rxjava-core/src/main/java/rx/util/functions/Action.java new file mode 100644 index 0000000000..95b3176971 --- /dev/null +++ b/rxjava-core/src/main/java/rx/util/functions/Action.java @@ -0,0 +1,26 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package rx.util.functions; + +/** + * All Action interfaces extend from this. + *

+ * Marker interface to allow instanceof checks. + */ +public interface Action { + +} diff --git a/rxjava-core/src/main/java/rx/util/functions/Action0.java b/rxjava-core/src/main/java/rx/util/functions/Action0.java index 62d57bd563..832b78dd52 100644 --- a/rxjava-core/src/main/java/rx/util/functions/Action0.java +++ b/rxjava-core/src/main/java/rx/util/functions/Action0.java @@ -15,6 +15,6 @@ */ package rx.util.functions; -public interface Action0 extends Function { +public interface Action0 extends Action { public void call(); } \ No newline at end of file diff --git a/rxjava-core/src/main/java/rx/util/functions/Action1.java b/rxjava-core/src/main/java/rx/util/functions/Action1.java index 14fa7ced8c..68c1b804ed 100644 --- a/rxjava-core/src/main/java/rx/util/functions/Action1.java +++ b/rxjava-core/src/main/java/rx/util/functions/Action1.java @@ -15,6 +15,6 @@ */ package rx.util.functions; -public interface Action1 extends Function { +public interface Action1 extends Action { public void call(T1 t1); } \ No newline at end of file diff --git a/rxjava-core/src/main/java/rx/util/functions/Action2.java b/rxjava-core/src/main/java/rx/util/functions/Action2.java index 8a17875a9e..ba4826bdca 100644 --- a/rxjava-core/src/main/java/rx/util/functions/Action2.java +++ b/rxjava-core/src/main/java/rx/util/functions/Action2.java @@ -15,6 +15,6 @@ */ package rx.util.functions; -public interface Action2 extends Function { +public interface Action2 extends Action { public void call(T1 t1, T2 t2); } \ No newline at end of file diff --git a/rxjava-core/src/main/java/rx/util/functions/Action3.java b/rxjava-core/src/main/java/rx/util/functions/Action3.java index 2b613b621e..3c2b083c6f 100644 --- a/rxjava-core/src/main/java/rx/util/functions/Action3.java +++ b/rxjava-core/src/main/java/rx/util/functions/Action3.java @@ -15,6 +15,6 @@ */ package rx.util.functions; -public interface Action3 extends Function { +public interface Action3 extends Action { public void call(T1 t1, T2 t2, T3 t3); } \ No newline at end of file diff --git a/rxjava-core/src/main/java/rx/util/functions/Function.java b/rxjava-core/src/main/java/rx/util/functions/Function.java index cfe85a221f..be3440323b 100644 --- a/rxjava-core/src/main/java/rx/util/functions/Function.java +++ b/rxjava-core/src/main/java/rx/util/functions/Function.java @@ -1,9 +1,25 @@ +/** + * Copyright 2013 Netflix, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package rx.util.functions; /** * All Func and Action interfaces extend from this. *

- * Marker interface to allow isntanceof checks. + * Marker interface to allow instanceof checks. */ public interface Function { diff --git a/rxjava-core/src/main/java/rx/util/functions/FunctionLanguageAdaptor.java b/rxjava-core/src/main/java/rx/util/functions/FunctionLanguageAdaptor.java index 6ec87f358a..9e471e7329 100644 --- a/rxjava-core/src/main/java/rx/util/functions/FunctionLanguageAdaptor.java +++ b/rxjava-core/src/main/java/rx/util/functions/FunctionLanguageAdaptor.java @@ -15,16 +15,10 @@ */ package rx.util.functions; -public interface FunctionLanguageAdaptor { +import java.util.Map; +import java.util.Set; - /** - * Invoke the function and return the results. - * - * @param function - * @param args - * @return Object results from function execution - */ - Object call(Object function, Object[] args); +public interface FunctionLanguageAdaptor { /** * The Class of the Function that this adaptor serves. @@ -35,5 +29,13 @@ public interface FunctionLanguageAdaptor { * * @return Class[] of classes that this adaptor should be invoked for. */ - public Class[] getFunctionClass(); + //public Class[] getFunctionClass(); + + //TODO MRJ: Add Javadoc + public Map, Class> getActionClassRewritingMap(); + + //TODO MRJ: Add Javadoc + public Map, Class> getFunctionClassRewritingMap(); + + public Set> getAllClassesToRewrite(); } diff --git a/rxjava-core/src/main/java/rx/util/functions/Functions.java b/rxjava-core/src/main/java/rx/util/functions/Functions.java index 53671c210d..0581e46e13 100644 --- a/rxjava-core/src/main/java/rx/util/functions/Functions.java +++ b/rxjava-core/src/main/java/rx/util/functions/Functions.java @@ -15,74 +15,12 @@ */ package rx.util.functions; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; - /** - * Allows execution of functions from multiple different languages. - *

- * Language support is provided via implementations of {@link FunctionLanguageAdaptor}. - *

- * This class will dynamically look for known language adaptors on the classpath at startup or new ones can be registered using {@link #registerLanguageAdaptor(Class[], FunctionLanguageAdaptor)}. + * Utility class for getting concrete implementations of Functions/Actions */ public class Functions { - private final static ConcurrentHashMap, FunctionLanguageAdaptor> languageAdaptors = new ConcurrentHashMap, FunctionLanguageAdaptor>(); - - static { - /* optimistically look for supported languages if they are in the classpath */ - loadLanguageAdaptor("Groovy"); - loadLanguageAdaptor("JRuby"); - loadLanguageAdaptor("Clojure"); - loadLanguageAdaptor("Scala"); - // as new languages arise we can add them here but this does not prevent someone from using 'registerLanguageAdaptor' directly - } - - private static boolean loadLanguageAdaptor(String name) { - String className = "rx.lang." + name.toLowerCase() + "." + name + "Adaptor"; - try { - Class c = Class.forName(className); - FunctionLanguageAdaptor a = (FunctionLanguageAdaptor) c.newInstance(); - registerLanguageAdaptor(a.getFunctionClass(), a); - /* - * Using System.err/System.out as this is the only place in the library where we do logging and it's only at startup. - * I don't want to include SL4J/Log4j just for this and no one uses Java Logging. - */ - System.out.println("RxJava => Successfully loaded function language adaptor: " + name + " with path: " + className); - } catch (ClassNotFoundException e) { - System.err.println("RxJava => Could not find function language adaptor: " + name + " with path: " + className); - return false; - } catch (Exception e) { - System.err.println("RxJava => Failed trying to initialize function language adaptor: " + className); - e.printStackTrace(); - return false; - } - return true; - } - - public static void registerLanguageAdaptor(Class[] functionClasses, FunctionLanguageAdaptor adaptor) { - for (Class functionClass : functionClasses) { - if (functionClass.getPackage().getName().startsWith("java.")) { - throw new IllegalArgumentException("FunctionLanguageAdaptor implementations can not specify java.lang.* classes."); - } - languageAdaptors.put(functionClass, adaptor); - } - } - - public static void removeLanguageAdaptor(Class functionClass) { - languageAdaptors.remove(functionClass); - } - - public static Collection getRegisteredLanguageAdaptors() { - return languageAdaptors.values(); - } - - /** - * Utility method for determining the type of closure/function and executing it. - * - * @param function - */ - @SuppressWarnings({ "rawtypes" }) + @SuppressWarnings({ "unchecked", "rawtypes" }) public static FuncN from(final Object function) { if (function == null) { throw new RuntimeException("function is null. Can't send arguments to null function."); @@ -91,131 +29,13 @@ public static FuncN from(final Object function) { /* check for typed Rx Function implementation first */ if (function instanceof Function) { return fromFunction((Function) function); - } else { - /* not an Rx Function so try language adaptors */ - - // check for language adaptor - for (final Class c : languageAdaptors.keySet()) { - if (c.isInstance(function)) { - final FunctionLanguageAdaptor la = languageAdaptors.get(c); - // found the language adaptor so wrap in FuncN and return - return new FuncN() { - - @Override - public Object call(Object... args) { - return la.call(function, args); - } - - }; - } - } - // no language adaptor found + } else if (function instanceof Action) { + return fromAction((Action) function); } - // no support found throw new RuntimeException("Unsupported closure type: " + function.getClass().getSimpleName()); } - // - // @SuppressWarnings("unchecked") - // private static R executionRxFunction(Function function, Object... args) { - // // check Func* classes - // if (function instanceof Func0) { - // Func0 f = (Func0) function; - // if (args.length != 0) { - // throw new RuntimeException("The closure was Func0 and expected no arguments, but we received: " + args.length); - // } - // return (R) f.call(); - // } else if (function instanceof Func1) { - // Func1 f = (Func1) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Func1 and expected 1 argument, but we received: " + args.length); - // } - // return f.call(args[0]); - // } else if (function instanceof Func2) { - // Func2 f = (Func2) function; - // if (args.length != 2) { - // throw new RuntimeException("The closure was Func2 and expected 2 arguments, but we received: " + args.length); - // } - // return f.call(args[0], args[1]); - // } else if (function instanceof Func3) { - // Func3 f = (Func3) function; - // if (args.length != 3) { - // throw new RuntimeException("The closure was Func3 and expected 3 arguments, but we received: " + args.length); - // } - // return (R) f.call(args[0], args[1], args[2]); - // } else if (function instanceof Func4) { - // Func4 f = (Func4) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Func4 and expected 4 arguments, but we received: " + args.length); - // } - // return f.call(args[0], args[1], args[2], args[3]); - // } else if (function instanceof Func5) { - // Func5 f = (Func5) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Func5 and expected 5 arguments, but we received: " + args.length); - // } - // return f.call(args[0], args[1], args[2], args[3], args[4]); - // } else if (function instanceof Func6) { - // Func6 f = (Func6) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Func6 and expected 6 arguments, but we received: " + args.length); - // } - // return f.call(args[0], args[1], args[2], args[3], args[4], args[5]); - // } else if (function instanceof Func7) { - // Func7 f = (Func7) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Func7 and expected 7 arguments, but we received: " + args.length); - // } - // return f.call(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - // } else if (function instanceof Func8) { - // Func8 f = (Func8) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Func8 and expected 8 arguments, but we received: " + args.length); - // } - // return f.call(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); - // } else if (function instanceof Func9) { - // Func9 f = (Func9) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Func9 and expected 9 arguments, but we received: " + args.length); - // } - // return f.call(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); - // } else if (function instanceof FuncN) { - // FuncN f = (FuncN) function; - // return f.call(args); - // } else if (function instanceof Action0) { - // Action0 f = (Action0) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Action0 and expected 0 arguments, but we received: " + args.length); - // } - // f.call(); - // return null; - // } else if (function instanceof Action1) { - // Action1 f = (Action1) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Action1 and expected 1 argument, but we received: " + args.length); - // } - // f.call(args[0]); - // return null; - // } else if (function instanceof Action2) { - // Action2 f = (Action2) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Action2 and expected 2 argument, but we received: " + args.length); - // } - // f.call(args[0], args[1]); - // return null; - // } else if (function instanceof Action3) { - // Action3 f = (Action3) function; - // if (args.length != 1) { - // throw new RuntimeException("The closure was Action1 and expected 1 argument, but we received: " + args.length); - // } - // f.call(args[0], args[1], args[2]); - // return null; - // } - // - // throw new RuntimeException("Unknown implementation of Function: " + function.getClass().getSimpleName()); - // } - @SuppressWarnings({ "unchecked", "rawtypes" }) private static FuncN fromFunction(Function function) { // check Func* classes @@ -241,19 +61,27 @@ private static FuncN fromFunction(Function function) { return fromFunc((Func9) function); } else if (function instanceof FuncN) { return (FuncN) function; - } else if (function instanceof Action0) { - return fromAction((Action0) function); - } else if (function instanceof Action1) { - return fromAction((Action1) function); - } else if (function instanceof Action2) { - return fromAction((Action2) function); - } else if (function instanceof Action3) { - return fromAction((Action3) function); } throw new RuntimeException("Unknown implementation of Function: " + function.getClass().getSimpleName()); } + @SuppressWarnings({ "unchecked", "rawtypes" }) + private static FuncN fromAction(Action action) { + // check Action* classes + if (action instanceof Action0) { + return fromAction((Action0) action); + } else if (action instanceof Action1) { + return fromAction((Action1) action); + } else if (action instanceof Action2) { + return fromAction((Action2) action); + } else if (action instanceof Action3) { + return fromAction((Action3) action); + } + + throw new RuntimeException("Unknown implementation of Action: " + action.getClass().getSimpleName()); + } + /** * Convert a function to FuncN to allow heterogeneous handling of functions with different arities. * diff --git a/settings.gradle b/settings.gradle index f07f904404..93c3e179ed 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,4 +4,6 @@ include 'rxjava-core', \ 'language-adaptors:rxjava-jruby', \ 'language-adaptors:rxjava-clojure', \ 'language-adaptors:rxjava-scala', \ +'language-adaptors:rxjava-dynamic', \ +'language-adaptors:codegen', \ 'rxjava-contrib:rxjava-swing'