From 7f1a9898d1d890ce37f7b4e3be86c2c5711eb510 Mon Sep 17 00:00:00 2001 From: Matt Jacobs Date: Tue, 2 Jul 2013 22:04:09 -0700 Subject: [PATCH 1/9] Make rxjava-core typesafe --- .../java/rx/observables/SwingObservable.java | 2 - rxjava-core/src/main/java/rx/Observable.java | 1164 +---------------- .../rx/observables/BlockingObservable.java | 207 --- .../main/java/rx/subjects/AsyncSubject.java | 11 +- .../main/java/rx/subjects/PublishSubject.java | 30 +- .../main/java/rx/subjects/ReplaySubject.java | 8 +- 6 files changed, 27 insertions(+), 1395 deletions(-) diff --git a/rxjava-contrib/rxjava-swing/src/main/java/rx/observables/SwingObservable.java b/rxjava-contrib/rxjava-swing/src/main/java/rx/observables/SwingObservable.java index fa9ecd3095..a2facde800 100644 --- a/rxjava-contrib/rxjava-swing/src/main/java/rx/observables/SwingObservable.java +++ b/rxjava-contrib/rxjava-swing/src/main/java/rx/observables/SwingObservable.java @@ -15,8 +15,6 @@ */ package rx.observables; -import static rx.Observable.filter; - import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; diff --git a/rxjava-core/src/main/java/rx/Observable.java b/rxjava-core/src/main/java/rx/Observable.java index b93f1621cf..8233b848ed 100644 --- a/rxjava-core/src/main/java/rx/Observable.java +++ b/rxjava-core/src/main/java/rx/Observable.java @@ -280,7 +280,7 @@ public Subscription subscribe(final Map callbacks) { return protectivelyWrapAndSubscribe(new Observer() { @Override - public void onCompleted() { + public void onCompleted() { Object onComplete = callbacks.get("onCompleted"); if (onComplete != null) { Functions.from(onComplete).call(); @@ -288,7 +288,7 @@ public void onCompleted() { } @Override - public void onError(Exception e) { + public void onError(Exception e) { handleError(e); Object onError = callbacks.get("onError"); if (onError != null) { @@ -299,61 +299,17 @@ public void onError(Exception e) { } @Override - public void onNext(Object args) { + public void onNext(Object args) { onNext.call(args); } - }); + }); } public Subscription subscribe(final Map callbacks, Scheduler scheduler) { 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"); @@ -389,48 +345,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"); @@ -469,51 +383,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"); @@ -663,49 +532,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. @@ -755,33 +581,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. *

@@ -909,39 +708,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. *

@@ -989,37 +755,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 @@ -1048,43 +783,6 @@ 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} @@ -1261,36 +959,8 @@ public static Observable flatMap(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 - * @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. + * 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. *

* * @@ -1315,51 +985,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. @@ -1381,38 +1006,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 @@ -1535,45 +1128,6 @@ public static Observable onErrorResumeNext(final Observable that, fina return create(OperationOnErrorResumeNextViaFunction.onErrorResumeNextViaFunction(that, resumeFunction)); } - /** - * 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. @@ -1715,27 +1269,6 @@ 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() *

@@ -1747,17 +1280,6 @@ public static Observable aggregate(Observable sequence, Func2 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) { - return reduce(sequence, 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 @@ -1791,25 +1313,6 @@ 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(). *

@@ -1821,17 +1324,6 @@ public static Observable aggregate(Observable sequence, R initialVa 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 @@ -1856,27 +1348,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 @@ -1908,26 +1379,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. @@ -1947,33 +1398,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. @@ -2092,31 +1516,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 @@ -2136,35 +1535,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. *

@@ -2373,34 +1743,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. *

* *

@@ -2474,68 +1818,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. @@ -2568,48 +1850,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. @@ -2644,50 +1884,6 @@ public static Observable zip(Observable w0, Observabl return create(OperationZip.zip(w0, w1, w2, w3, 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 - * 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. - * - * @param w0 - * one 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); - } - - }); - } - /** * Filters an Observable by discarding any items it emits that do not meet some test. *

@@ -2719,29 +1915,6 @@ 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 @@ -2763,27 +1936,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. *

@@ -2814,30 +1966,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 @@ -2859,36 +1987,6 @@ public Observable mapMany(Func1> func) { return mapMany(this, 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} @@ -2980,42 +2078,6 @@ public Observable onErrorResumeNext(final Func1> res return onErrorResumeNext(this, resumeFunction); } - /** - * 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. @@ -3073,42 +2135,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 @@ -3182,17 +2208,6 @@ 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(). *

@@ -3204,17 +2219,6 @@ 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) { - return aggregate(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 @@ -3242,17 +2246,6 @@ 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(). *

@@ -3264,17 +2257,6 @@ 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 @@ -3335,17 +2317,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 @@ -3373,17 +2344,6 @@ 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. @@ -3399,21 +2359,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. @@ -3468,22 +2413,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 @@ -3501,24 +2430,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. @@ -3607,21 +2518,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. *

@@ -3657,28 +2553,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 @@ -3697,24 +2571,6 @@ 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 @@ -4246,10 +3102,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/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); From c93ba88e8bdc797376b0fb9f6ebddf531a9755cb Mon Sep 17 00:00:00 2001 From: Matt Jacobs Date: Wed, 3 Jul 2013 01:39:33 -0700 Subject: [PATCH 2/9] Add Code generator that adapts the core Observable to a dynamic language's native function support * Only hooked up to rxjava-groovy in this commit --- build.gradle | 2 + language-adaptors/codegen/build.gradle | 50 ++++ language-adaptors/codegen/examples.txt | 47 +++ .../java/rx/codegen/ClassPathBasedRunner.java | 48 +++ .../main/java/rx/codegen/CodeGenerator.java | 281 ++++++++++++++++++ language-adaptors/rxjava-clojure/build.gradle | 10 - .../rx/lang/clojure/ClojureActionWrapper.java | 41 +++ .../java/rx/lang/clojure/ClojureAdaptor.java | 59 +--- .../lang/clojure/ClojureFunctionWrapper.java | 58 ++++ language-adaptors/rxjava-groovy/build.gradle | 32 +- .../rx/lang/groovy/GroovyActionWrapper.java | 39 +++ .../java/rx/lang/groovy/GroovyAdaptor.java | 29 +- .../rx/lang/groovy/GroovyFunctionWrapper.java | 58 ++++ .../rx/lang/jruby/JRubyActionWrapper.java | 48 +++ .../main/java/rx/lang/jruby/JRubyAdaptor.java | 23 +- .../rx/lang/jruby/JRubyFunctionWrapper.java | 70 +++++ .../scala/rx/lang/scala/ScalaAdaptor.scala | 9 +- .../java/rx/subscriptions/Subscriptions.java | 17 -- .../main/java/rx/util/functions/Action.java | 10 + .../main/java/rx/util/functions/Action0.java | 2 +- .../main/java/rx/util/functions/Action1.java | 2 +- .../main/java/rx/util/functions/Action2.java | 2 +- .../main/java/rx/util/functions/Action3.java | 2 +- .../functions/FunctionLanguageAdaptor.java | 22 +- .../java/rx/util/functions/Functions.java | 222 ++------------ settings.gradle | 1 + 26 files changed, 861 insertions(+), 323 deletions(-) create mode 100644 language-adaptors/codegen/build.gradle create mode 100644 language-adaptors/codegen/examples.txt create mode 100644 language-adaptors/codegen/src/main/java/rx/codegen/ClassPathBasedRunner.java create mode 100644 language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java create mode 100644 language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureActionWrapper.java create mode 100644 language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureFunctionWrapper.java create mode 100644 language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyActionWrapper.java create mode 100644 language-adaptors/rxjava-groovy/src/main/java/rx/lang/groovy/GroovyFunctionWrapper.java create mode 100644 language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyActionWrapper.java create mode 100644 language-adaptors/rxjava-jruby/src/main/java/rx/lang/jruby/JRubyFunctionWrapper.java create mode 100644 rxjava-core/src/main/java/rx/util/functions/Action.java diff --git a/build.gradle b/build.gradle index 9073b716ee..3e8a9cfde7 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,8 @@ apply from: file('gradle/maven.gradle') apply from: file('gradle/license.gradle') apply from: file('gradle/release.gradle') +ext.coreJarDir = new File(rootDir, "/rxjava-core/build/libs").getCanonicalPath() + subprojects { group = "com.netflix.${githubProjectName}" diff --git a/language-adaptors/codegen/build.gradle b/language-adaptors/codegen/build.gradle new file mode 100644 index 0000000000..f97f16ae72 --- /dev/null +++ b/language-adaptors/codegen/build.gradle @@ -0,0 +1,50 @@ +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' + provided 'org.mockito:mockito-core:1.8.5' +} + +//task createDynamicallyAdaptedObservable(type: JavaExec) { +// main = 'rx.lang.utils.LanguageAdaptorCodeGenerator' +// classpath = sourceSets.main.runtimeClasspath +// args dynamicClassDir + +// FileTree coreTree = fileTree('../../rxjava-core/src/main').include('**/*.java') +// FileTree adaptorTree = fileTree('src/main').include("**/*.java") +// inputs.files (coreTree + adaptorTree) +//} + +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-language-adaptor-utils' + 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..5630724abd --- /dev/null +++ b/language-adaptors/codegen/src/main/java/rx/codegen/ClassPathBasedRunner.java @@ -0,0 +1,48 @@ +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..a67bff1714 --- /dev/null +++ b/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java @@ -0,0 +1,281 @@ +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.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); + + for (CtMethod cm: clazz.getMethods()) { + System.out.println(cm.getName() + " : " + cm.getSignature() + " : " + cm.getDeclaringClass().getName()); + } + + 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 "); + 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(";}"); + 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..7b2c8275c4 100644 --- a/language-adaptors/rxjava-clojure/build.gradle +++ b/language-adaptors/rxjava-clojure/build.gradle @@ -52,16 +52,6 @@ idea { } -eclipse { - classpath { - // include 'provided' dependencies on the classpath - plusConfigurations += configurations.provided - - downloadSources = true - downloadJavadoc = true - } -} - // include /src/examples folder sourceSets { examples 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..594ee51802 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,8 @@ */ package rx.lang.clojure; -import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import org.junit.Before; import org.junit.Test; @@ -32,57 +33,17 @@ 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 Class[] getFunctionClass() { - return new Class[] { IFn.class }; + public Map, Class> getActionClassRewritingMap() { + Map, Class> m = new HashMap, Class>(); + m.put(IFn.class, ClojureActionWrapper.class); + return m; } 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-groovy/build.gradle b/language-adaptors/rxjava-groovy/build.gradle index 91c060193d..5164254586 100644 --- a/language-adaptors/rxjava-groovy/build.gradle +++ b/language-adaptors/rxjava-groovy/build.gradle @@ -6,6 +6,7 @@ apply plugin: 'osgi' dependencies { 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' @@ -24,6 +25,33 @@ configurations { // include 'examples' in build task build.dependsOn examplesClasses +test.dependsOn jar + +task createAdaptedObservable(type: JavaExec) { + main = 'rx.codegen.ClassPathBasedRunner' + classpath = sourceSets.main.runtimeClasspath + args = ["Groovy", sourceSets.main.output.classesDir] +} + +task jar(overwrite: true, type: Jar, dependsOn: "createAdaptedObservable") { + description = 'Copies the RxJava core JAR and replaces Observable with Groovy-friendly versions.' + destinationDir = jar.archivePath.getParentFile() + archiveName = baseName + "-" + version + "." + extension + + from (zipTree(coreJarDir + "/rxjava-core-" + version + ".jar")) { + exclude "rx/Observable.class" + exclude "rx/observables/BlockingObservable.class" + } + from (sourceSets.main.output.classesDir) { + include "rx/Observable.class" + include "rx/observables/BlockingObservable.class" + } + + /* manifest { + name = 'rxjava-core' + attributes('Bundle-Vendor': 'Netflix', 'Bundle-DocURL': 'https://github.com/Netflix/RxJava', 'Import-Package': '!org.junit,!junit.framework,!org.mockito.*,*') + }*/ +} eclipse { classpath { @@ -42,7 +70,7 @@ idea { } } -jar { +/*jar { manifest { name = 'rxjava-groovy' instruction 'Bundle-Vendor', 'Netflix' @@ -50,4 +78,4 @@ jar { instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' instruction 'Fragment-Host', 'com.netflix.rxjava.core' } -} \ No newline at end of file +}*/ \ 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/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..1b6b71abe0 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,11 @@ import static org.mockito.Mockito.*; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; -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 +39,17 @@ 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; } 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/src/main/scala/rx/lang/scala/ScalaAdaptor.scala b/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/ScalaAdaptor.scala index 12418d516d..d2d2138976 100644 --- 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 @@ -53,14 +53,7 @@ class ScalaAdaptor extends FunctionLanguageAdaptor { 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 = { + private def matchOption(funcOption: Option[_], args: Array[AnyRef]) : Object = { funcOption match { case Some(func: AnyRef) => return matchFunction(func, args) case _ => return None 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..c1d43eede6 --- /dev/null +++ b/rxjava-core/src/main/java/rx/util/functions/Action.java @@ -0,0 +1,10 @@ +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/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..42af15cf17 100644 --- a/rxjava-core/src/main/java/rx/util/functions/Functions.java +++ b/rxjava-core/src/main/java/rx/util/functions/Functions.java @@ -15,207 +15,11 @@ */ 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" }) - public static FuncN from(final Object function) { - if (function == null) { - throw new RuntimeException("function is null. Can't send arguments to null 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 - } - - // 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 +45,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..d6cc324181 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,4 +4,5 @@ include 'rxjava-core', \ 'language-adaptors:rxjava-jruby', \ 'language-adaptors:rxjava-clojure', \ 'language-adaptors:rxjava-scala', \ +'language-adaptors:codegen', \ 'rxjava-contrib:rxjava-swing' From bbedef284e27adfc91526deff109aec2f8998a4c Mon Sep 17 00:00:00 2001 From: Matt Jacobs Date: Wed, 3 Jul 2013 09:22:21 -0700 Subject: [PATCH 3/9] Clean up rxjava-groovy Gradle build --- build.gradle | 57 ++++++++++++--- language-adaptors/codegen/build.gradle | 13 +--- .../main/java/rx/codegen/CodeGenerator.java | 5 -- language-adaptors/rxjava-groovy/build.gradle | 69 +++++-------------- 4 files changed, 66 insertions(+), 78 deletions(-) diff --git a/build.gradle b/build.gradle index 3e8a9cfde7..85d83ea12d 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,22 +15,55 @@ 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') - -ext.coreJarDir = new File(rootDir, "/rxjava-core/build/libs").getCanonicalPath() - subprojects { + apply plugin: 'java' + apply plugin: 'eclipse' + apply plugin: 'idea' + apply plugin: 'osgi' group = "com.netflix.${githubProjectName}" - sourceSets.test.java.srcDir 'src/main/java' + ext.coreJarDir = new File(rootDir, "/rxjava-core/build/libs").getCanonicalPath() + ext.outputDir = 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/language-adaptors/codegen/build.gradle b/language-adaptors/codegen/build.gradle index f97f16ae72..7967131270 100644 --- a/language-adaptors/codegen/build.gradle +++ b/language-adaptors/codegen/build.gradle @@ -9,19 +9,8 @@ dependencies { compile 'org.javassist:javassist:3.17.1-GA' provided 'junit:junit:4.10' - provided 'org.mockito:mockito-core:1.8.5' } -//task createDynamicallyAdaptedObservable(type: JavaExec) { -// main = 'rx.lang.utils.LanguageAdaptorCodeGenerator' -// classpath = sourceSets.main.runtimeClasspath -// args dynamicClassDir - -// FileTree coreTree = fileTree('../../rxjava-core/src/main').include('**/*.java') -// FileTree adaptorTree = fileTree('src/main').include("**/*.java") -// inputs.files (coreTree + adaptorTree) -//} - eclipse { classpath { // include 'provided' dependencies on the classpath @@ -41,7 +30,7 @@ idea { jar { manifest { - name = 'rxjava-language-adaptor-utils' + name = 'rxjava-codegen' instruction 'Bundle-Vendor', 'Netflix' instruction 'Bundle-DocURL', 'https://github.com/Netflix/RxJava' instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' diff --git a/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java b/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java index a67bff1714..02d17d793d 100644 --- a/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java +++ b/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java @@ -61,11 +61,6 @@ private static void addSupportFor(Class observableClass, FunctionLanguageAdap } try { rewriteMethodsWithRxArgs(clazz, adaptor); - - for (CtMethod cm: clazz.getMethods()) { - System.out.println(cm.getName() + " : " + cm.getSignature() + " : " + cm.getDeclaringClass().getName()); - } - writeClassFile(clazz, file); } catch (Exception e) { e.printStackTrace(); diff --git a/language-adaptors/rxjava-groovy/build.gradle b/language-adaptors/rxjava-groovy/build.gradle index 5164254586..fedb8bf395 100644 --- a/language-adaptors/rxjava-groovy/build.gradle +++ b/language-adaptors/rxjava-groovy/build.gradle @@ -1,10 +1,7 @@ -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.+' @@ -12,65 +9,33 @@ dependencies { 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", outputDir] -// make 'examples' use the same classpath -configurations { - examplesCompile.extendsFrom compile - examplesRuntime.extendsFrom runtime + inputs.files(sourceSets.main.runtimeClasspath) + outputs.dir(outputDir) } -// include 'examples' in build task -build.dependsOn examplesClasses -test.dependsOn jar +tasks.test { + dependsOn(createAdaptedObservable) -task createAdaptedObservable(type: JavaExec) { - main = 'rx.codegen.ClassPathBasedRunner' - classpath = sourceSets.main.runtimeClasspath - args = ["Groovy", sourceSets.main.output.classesDir] + //Reorders the classpath so that the newly-create Observables win + classpath = createAdaptedObservable.outputs.files + sourceSets.test.runtimeClasspath } -task jar(overwrite: true, type: Jar, dependsOn: "createAdaptedObservable") { - description = 'Copies the RxJava core JAR and replaces Observable with Groovy-friendly versions.' - destinationDir = jar.archivePath.getParentFile() - archiveName = baseName + "-" + version + "." + extension +tasks.jar { + dependsOn(createAdaptedObservable) - from (zipTree(coreJarDir + "/rxjava-core-" + version + ".jar")) { + from (zipTree(configurations.core.singleFile)) { exclude "rx/Observable.class" exclude "rx/observables/BlockingObservable.class" - } - from (sourceSets.main.output.classesDir) { - include "rx/Observable.class" - include "rx/observables/BlockingObservable.class" } + from(outputDir) - /* manifest { - name = 'rxjava-core' - attributes('Bundle-Vendor': 'Netflix', 'Bundle-DocURL': 'https://github.com/Netflix/RxJava', 'Import-Package': '!org.junit,!junit.framework,!org.mockito.*,*') - }*/ -} - -eclipse { - classpath { - // include 'provided' dependencies on the classpath - plusConfigurations += configurations.provided - - downloadSources = true - downloadJavadoc = true - } -} + exclude('**/*$UnitTest*') -idea { - module { - // include 'provided' dependencies on the classpath - scopes.PROVIDED.plus += configurations.provided - } -} - -/*jar { manifest { name = 'rxjava-groovy' instruction 'Bundle-Vendor', 'Netflix' @@ -78,4 +43,4 @@ idea { instruction 'Import-Package', '!org.junit,!junit.framework,!org.mockito.*,*' instruction 'Fragment-Host', 'com.netflix.rxjava.core' } -}*/ \ No newline at end of file +} From 698508f39e7c65192bd0fbac98363a7796c1133f Mon Sep 17 00:00:00 2001 From: Matt Jacobs Date: Wed, 3 Jul 2013 16:04:35 -0700 Subject: [PATCH 4/9] Get rxjava-clojure build working in Gradle --- language-adaptors/rxjava-clojure/build.gradle | 58 +++++++++---------- .../java/rx/lang/clojure/ClojureAdaptor.java | 9 +++ 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/language-adaptors/rxjava-clojure/build.gradle b/language-adaptors/rxjava-clojure/build.gradle index 7b2c8275c4..78cc056b41 100644 --- a/language-adaptors/rxjava-clojure/build.gradle +++ b/language-adaptors/rxjava-clojure/build.gradle @@ -1,17 +1,13 @@ -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,47 +22,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", outputDir] + + inputs.files(sourceSets.main.runtimeClasspath) + outputs.dir(outputDir) } +tasks.test { + dependsOn(createAdaptedObservable) -// include /src/examples folder -sourceSets { - examples + //Reorders the classpath so that the newly-create Observables win + classpath = createAdaptedObservable.outputs.files + sourceSets.test.runtimeClasspath } -// make 'examples' use the same classpath -configurations { - examplesCompile.extendsFrom compile - examplesRuntime.extendsFrom runtime -} +tasks.jar { + dependsOn(createAdaptedObservable) -// include 'examples' in build task -build.dependsOn examplesClasses + from (zipTree(configurations.core.singleFile)) { + exclude "rx/Observable.class" + exclude "rx/observables/BlockingObservable.class" + } + from(outputDir) + + exclude('**/*$UnitTest*') -jar { manifest { name = 'rxjava-clojure' instruction 'Bundle-Vendor', 'Netflix' @@ -74,4 +68,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/ClojureAdaptor.java b/language-adaptors/rxjava-clojure/src/main/java/rx/lang/clojure/ClojureAdaptor.java index 594ee51802..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 @@ -16,7 +16,9 @@ package rx.lang.clojure; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.junit.Before; import org.junit.Test; @@ -46,6 +48,13 @@ public Map, Class> getActionClassRewritingMap() { return m; } + @Override + public Set> getAllClassesToRewrite() { + Set> classes = new HashSet>(); + classes.add(IFn.class); + return classes; + } + public static class UnitTest { @Mock From 5ac401dedd9ba1402179ae3e47adaa647033d33a Mon Sep 17 00:00:00 2001 From: Matt Jacobs Date: Wed, 3 Jul 2013 16:19:03 -0700 Subject: [PATCH 5/9] Get rxjava-jruby build working in Gradle --- language-adaptors/rxjava-jruby/build.gradle | 44 +++++++++++-------- .../main/java/rx/lang/jruby/JRubyAdaptor.java | 9 ++++ 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/language-adaptors/rxjava-jruby/build.gradle b/language-adaptors/rxjava-jruby/build.gradle index cf7d9533e2..f4aaf194cf 100644 --- a/language-adaptors/rxjava-jruby/build.gradle +++ b/language-adaptors/rxjava-jruby/build.gradle @@ -1,33 +1,39 @@ -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", outputDir] - downloadSources = true - downloadJavadoc = true - } + inputs.files(sourceSets.main.runtimeClasspath) + outputs.dir(outputDir) } -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(outputDir) + + exclude('**/*$UnitTest*') + manifest { name = 'rxjava-jruby' instruction 'Bundle-Vendor', 'Netflix' 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 1b6b71abe0..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 @@ -20,7 +20,9 @@ import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.jruby.RubyProc; import org.jruby.embed.ScriptingContainer; @@ -52,6 +54,13 @@ public Map, Class> getActionClassRewritingMap() { return m; } + @Override + public Set> getAllClassesToRewrite() { + Set> classes = new HashSet>(); + classes.add(RubyProc.class); + return classes; + } + public static class UnitTest { @Mock From d4efc294aff86d8752fdaef63d4afd52e3d50088 Mon Sep 17 00:00:00 2001 From: Matt Jacobs Date: Wed, 3 Jul 2013 16:37:20 -0700 Subject: [PATCH 6/9] Added rxjava-dynamic language-adaptor * Adds an Object overload to Observable methods via code generation --- language-adaptors/rxjava-dynamic/build.gradle | 43 ++++++++++++++ .../rx/lang/dynamic/DynamicActionWrapper.java | 38 +++++++++++++ .../java/rx/lang/dynamic/DynamicAdaptor.java | 48 ++++++++++++++++ .../lang/dynamic/DynamicFunctionWrapper.java | 57 +++++++++++++++++++ .../java/rx/util/functions/Functions.java | 16 ++++++ settings.gradle | 1 + 6 files changed, 203 insertions(+) create mode 100644 language-adaptors/rxjava-dynamic/build.gradle create mode 100644 language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicActionWrapper.java create mode 100644 language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicAdaptor.java create mode 100644 language-adaptors/rxjava-dynamic/src/main/java/rx/lang/dynamic/DynamicFunctionWrapper.java diff --git a/language-adaptors/rxjava-dynamic/build.gradle b/language-adaptors/rxjava-dynamic/build.gradle new file mode 100644 index 0000000000..570142943f --- /dev/null +++ b/language-adaptors/rxjava-dynamic/build.gradle @@ -0,0 +1,43 @@ +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", outputDir] + + inputs.files(sourceSets.main.runtimeClasspath) + outputs.dir(outputDir) +} + +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(outputDir) + + 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/rxjava-core/src/main/java/rx/util/functions/Functions.java b/rxjava-core/src/main/java/rx/util/functions/Functions.java index 42af15cf17..0581e46e13 100644 --- a/rxjava-core/src/main/java/rx/util/functions/Functions.java +++ b/rxjava-core/src/main/java/rx/util/functions/Functions.java @@ -20,6 +20,22 @@ */ public class Functions { + @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."); + } + + /* check for typed Rx Function implementation first */ + if (function instanceof Function) { + return fromFunction((Function) function); + } else if (function instanceof Action) { + return fromAction((Action) function); + } + // no support found + throw new RuntimeException("Unsupported closure type: " + function.getClass().getSimpleName()); + } + @SuppressWarnings({ "unchecked", "rawtypes" }) private static FuncN fromFunction(Function function) { // check Func* classes diff --git a/settings.gradle b/settings.gradle index d6cc324181..93c3e179ed 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,5 +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' From 4d45c10357277cc879eb323c2b0481b6d0ceca56 Mon Sep 17 00:00:00 2001 From: Matt Jacobs Date: Wed, 3 Jul 2013 17:20:44 -0700 Subject: [PATCH 7/9] Reworked Scala adaptor to use implicits in RxImplicits, rather than code generation --- language-adaptors/rxjava-scala/build.gradle | 46 +- .../scala/rx/lang/scala/RxImplicits.scala | 592 ++++++++++++++++++ .../scala/rx/lang/scala/ScalaAdaptor.scala | 197 ------ 3 files changed, 609 insertions(+), 226 deletions(-) create mode 100644 language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/RxImplicits.scala delete mode 100644 language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/ScalaAdaptor.scala diff --git a/language-adaptors/rxjava-scala/build.gradle b/language-adaptors/rxjava-scala/build.gradle index 43704248d6..527766691e 100644 --- a/language-adaptors/rxjava-scala/build.gradle +++ b/language-adaptors/rxjava-scala/build.gradle @@ -1,11 +1,9 @@ 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 +11,36 @@ 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 d2d2138976..0000000000 --- a/language-adaptors/rxjava-scala/src/main/scala/rx/lang/scala/ScalaAdaptor.scala +++ /dev/null @@ -1,197 +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]) - } - - 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) - } -} From 5d10dbfb52c4128d025c21707ded252e9f8f988d Mon Sep 17 00:00:00 2001 From: Matt Jacobs Date: Wed, 3 Jul 2013 23:02:15 -0700 Subject: [PATCH 8/9] Added license to files I touched and moved Gradle config around --- build.gradle | 4 +--- language-adaptors/codegen/build.gradle | 19 ++-------------- .../java/rx/codegen/ClassPathBasedRunner.java | 16 ++++++++++++++ .../main/java/rx/codegen/CodeGenerator.java | 19 ++++++++++++++-- language-adaptors/rxjava-clojure/build.gradle | 7 +++--- language-adaptors/rxjava-dynamic/build.gradle | 8 ++++--- language-adaptors/rxjava-groovy/build.gradle | 7 +++--- language-adaptors/rxjava-jruby/build.gradle | 8 ++++--- language-adaptors/rxjava-scala/build.gradle | 2 +- rxjava-contrib/rxjava-swing/build.gradle | 22 ++----------------- .../java/rx/observables/SwingObservable.java | 2 ++ rxjava-core/build.gradle | 20 ----------------- .../main/java/rx/util/functions/Action.java | 16 ++++++++++++++ .../main/java/rx/util/functions/Function.java | 18 ++++++++++++++- 14 files changed, 92 insertions(+), 76 deletions(-) diff --git a/build.gradle b/build.gradle index 85d83ea12d..29b55f5c1a 100644 --- a/build.gradle +++ b/build.gradle @@ -19,12 +19,10 @@ subprojects { apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' - apply plugin: 'osgi' group = "com.netflix.${githubProjectName}" - ext.coreJarDir = new File(rootDir, "/rxjava-core/build/libs").getCanonicalPath() - ext.outputDir = file("build/rewritten_classes") + ext.codeGenOutputDir = file("build/rewritten_classes") // make 'examples' use the same classpath configurations { diff --git a/language-adaptors/codegen/build.gradle b/language-adaptors/codegen/build.gradle index 7967131270..1541b10429 100644 --- a/language-adaptors/codegen/build.gradle +++ b/language-adaptors/codegen/build.gradle @@ -11,24 +11,9 @@ dependencies { provided 'junit:junit:4.10' } -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 { + exclude('**/*$UnitTest*') + manifest { name = 'rxjava-codegen' instruction 'Bundle-Vendor', 'Netflix' diff --git a/language-adaptors/codegen/src/main/java/rx/codegen/ClassPathBasedRunner.java b/language-adaptors/codegen/src/main/java/rx/codegen/ClassPathBasedRunner.java index 5630724abd..ace0a316d2 100644 --- a/language-adaptors/codegen/src/main/java/rx/codegen/ClassPathBasedRunner.java +++ b/language-adaptors/codegen/src/main/java/rx/codegen/ClassPathBasedRunner.java @@ -1,3 +1,19 @@ +/** + * 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; diff --git a/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java b/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java index 02d17d793d..8acfd1759f 100644 --- a/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java +++ b/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java @@ -1,3 +1,18 @@ +/** + * 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; @@ -174,8 +189,8 @@ private static List getRewrittenMethods(CtClass clazz, CtMethod method newBody.append(makeArgList(argumentList)); newBody.append(")"); newBody.append(";}"); - System.out.println(method.getReturnType().getName() + " " + method.getName() + "(" + initialArgString + ") --> " + newMethod.getReturnType().getName() + " " + newMethod.getName() + "(" + finalArgString + ")"); - System.out.println(" " + newBody.toString()); + //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); } diff --git a/language-adaptors/rxjava-clojure/build.gradle b/language-adaptors/rxjava-clojure/build.gradle index 78cc056b41..6fb4ea8c30 100644 --- a/language-adaptors/rxjava-clojure/build.gradle +++ b/language-adaptors/rxjava-clojure/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'clojure' +apply plugin: 'osgi' dependencies { core project(':rxjava-core') @@ -37,10 +38,10 @@ eclipse { task createAdaptedObservable(type: JavaExec) { main = 'rx.codegen.ClassPathBasedRunner' classpath = sourceSets.main.runtimeClasspath - args = ["Clojure", outputDir] + args = ["Clojure", codeGenOutputDir] inputs.files(sourceSets.main.runtimeClasspath) - outputs.dir(outputDir) + outputs.dir(codeGenOutputDir) } tasks.test { @@ -57,7 +58,7 @@ tasks.jar { exclude "rx/Observable.class" exclude "rx/observables/BlockingObservable.class" } - from(outputDir) + from(codeGenOutputDir) exclude('**/*$UnitTest*') diff --git a/language-adaptors/rxjava-dynamic/build.gradle b/language-adaptors/rxjava-dynamic/build.gradle index 570142943f..18d03a8d9c 100644 --- a/language-adaptors/rxjava-dynamic/build.gradle +++ b/language-adaptors/rxjava-dynamic/build.gradle @@ -1,3 +1,5 @@ +apply plugin: 'osgi' + dependencies { core project(':rxjava-core') compile project(':rxjava-core') @@ -9,10 +11,10 @@ dependencies { task createAdaptedObservable(type: JavaExec) { main = 'rx.codegen.ClassPathBasedRunner' classpath = sourceSets.main.runtimeClasspath - args = ["Dynamic", outputDir] + args = ["Dynamic", codeGenOutputDir] inputs.files(sourceSets.main.runtimeClasspath) - outputs.dir(outputDir) + outputs.dir(codeGenOutputDir) } tasks.test { @@ -29,7 +31,7 @@ tasks.jar { exclude "rx/Observable.class" exclude "rx/observables/BlockingObservable.class" } - from(outputDir) + from(codeGenOutputDir) exclude('**/*$UnitTest*') diff --git a/language-adaptors/rxjava-groovy/build.gradle b/language-adaptors/rxjava-groovy/build.gradle index fedb8bf395..edb9cb30ea 100644 --- a/language-adaptors/rxjava-groovy/build.gradle +++ b/language-adaptors/rxjava-groovy/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'groovy' +apply plugin: 'osgi' dependencies { core project(':rxjava-core') @@ -12,10 +13,10 @@ dependencies { task createAdaptedObservable(type: JavaExec) { main = 'rx.codegen.ClassPathBasedRunner' classpath = sourceSets.main.runtimeClasspath - args = ["Groovy", outputDir] + args = ["Groovy", codeGenOutputDir] inputs.files(sourceSets.main.runtimeClasspath) - outputs.dir(outputDir) + outputs.dir(codeGenOutputDir) } tasks.test { @@ -32,7 +33,7 @@ tasks.jar { exclude "rx/Observable.class" exclude "rx/observables/BlockingObservable.class" } - from(outputDir) + from(codeGenOutputDir) exclude('**/*$UnitTest*') diff --git a/language-adaptors/rxjava-jruby/build.gradle b/language-adaptors/rxjava-jruby/build.gradle index f4aaf194cf..d7a0d82d39 100644 --- a/language-adaptors/rxjava-jruby/build.gradle +++ b/language-adaptors/rxjava-jruby/build.gradle @@ -1,3 +1,5 @@ +apply plugin: 'osgi' + dependencies { core project(':rxjava-core') compile project(':rxjava-core') @@ -10,10 +12,10 @@ dependencies { task createAdaptedObservable(type: JavaExec) { main = 'rx.codegen.ClassPathBasedRunner' classpath = sourceSets.main.runtimeClasspath - args = ["JRuby", outputDir] + args = ["JRuby", codeGenOutputDir] inputs.files(sourceSets.main.runtimeClasspath) - outputs.dir(outputDir) + outputs.dir(codeGenOutputDir) } tasks.test { @@ -30,7 +32,7 @@ tasks.jar { exclude "rx/Observable.class" exclude "rx/observables/BlockingObservable.class" } - from(outputDir) + from(codeGenOutputDir) exclude('**/*$UnitTest*') diff --git a/language-adaptors/rxjava-scala/build.gradle b/language-adaptors/rxjava-scala/build.gradle index 527766691e..be61f1d846 100644 --- a/language-adaptors/rxjava-scala/build.gradle +++ b/language-adaptors/rxjava-scala/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'scala' +apply plugin: 'osgi' tasks.withType(ScalaCompile) { scalaCompileOptions.fork = true @@ -11,7 +12,6 @@ tasks.withType(ScalaCompile) { } } - sourceSets { test { scala { 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-contrib/rxjava-swing/src/main/java/rx/observables/SwingObservable.java b/rxjava-contrib/rxjava-swing/src/main/java/rx/observables/SwingObservable.java index a2facde800..fa9ecd3095 100644 --- a/rxjava-contrib/rxjava-swing/src/main/java/rx/observables/SwingObservable.java +++ b/rxjava-contrib/rxjava-swing/src/main/java/rx/observables/SwingObservable.java @@ -15,6 +15,8 @@ */ package rx.observables; +import static rx.Observable.filter; + import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; 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/util/functions/Action.java b/rxjava-core/src/main/java/rx/util/functions/Action.java index c1d43eede6..95b3176971 100644 --- a/rxjava-core/src/main/java/rx/util/functions/Action.java +++ b/rxjava-core/src/main/java/rx/util/functions/Action.java @@ -1,3 +1,19 @@ +/** + * 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; /** 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 { From 73c863143911fde6e8d074cb4f439461a940a182 Mon Sep 17 00:00:00 2001 From: Matt Jacobs Date: Wed, 3 Jul 2013 23:22:40 -0700 Subject: [PATCH 9/9] Bugfix to codegeneration - explicitly call a static/instance method in body --- .../codegen/src/main/java/rx/codegen/CodeGenerator.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java b/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java index 8acfd1759f..ed737e4999 100644 --- a/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java +++ b/language-adaptors/codegen/src/main/java/rx/codegen/CodeGenerator.java @@ -23,7 +23,9 @@ 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; @@ -174,6 +176,11 @@ private static List getRewrittenMethods(CtClass clazz, CtMethod method 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++) { @@ -189,6 +196,7 @@ private static List getRewrittenMethods(CtClass clazz, CtMethod method 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());