All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rx.operators.OperationConcat Maven / Gradle / Ivy

There is a newer version: 0.20.7
Show newest version
/**
 * Copyright 2014 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.operators;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

import rx.Observable;
import rx.Observable.OnSubscribeFunc;
import rx.Observer;
import rx.Subscription;
import rx.functions.Action0;
import rx.subscriptions.Subscriptions;

/**
 * Returns an Observable that emits the items emitted by two or more Observables, one after the
 * other.
 * 

* */ public final class OperationConcat { /** * Combine the observable sequences from the list of Observables into one * observable sequence without any transformation. If either the outer * observable or an inner observable calls onError, we will call onError. *

* * @param sequences * An observable sequence of elements to project. * @return An observable sequence whose elements are the result of combining the output from the list of Observables. */ public static OnSubscribeFunc concat(final Observable... sequences) { return concat(Observable.from(sequences)); } public static OnSubscribeFunc concat(final Iterable> sequences) { return concat(Observable.from(sequences)); } public static OnSubscribeFunc concat(final Observable> sequences) { return new OnSubscribeFunc() { @Override public Subscription onSubscribe(Observer t1) { return new Concat(sequences).onSubscribe(t1); } }; } private static class Concat implements OnSubscribeFunc { private Observable> sequences; private SafeObservableSubscription innerSubscription = null; public Concat(Observable> sequences) { this.sequences = sequences; } public Subscription onSubscribe(final Observer observer) { final AtomicBoolean completedOrErred = new AtomicBoolean(false); final AtomicBoolean allSequencesReceived = new AtomicBoolean(false); final Queue> nextSequences = new ConcurrentLinkedQueue>(); final SafeObservableSubscription outerSubscription = new SafeObservableSubscription(); final Observer reusableObserver = new Observer() { @Override public void onNext(T item) { observer.onNext(item); } @Override public void onError(Throwable e) { if (completedOrErred.compareAndSet(false, true)) { outerSubscription.unsubscribe(); observer.onError(e); } } @Override public void onCompleted() { synchronized (nextSequences) { if (nextSequences.isEmpty()) { // No new sequences available at the moment innerSubscription = null; if (allSequencesReceived.get()) { // No new sequences are coming, we are finished if (completedOrErred.compareAndSet(false, true)) { observer.onCompleted(); } } } else { // Continue on to the next sequence innerSubscription = new SafeObservableSubscription(); innerSubscription.wrap(nextSequences.poll().subscribe(this)); } } } }; outerSubscription.wrap(sequences.subscribe(new Observer>() { @Override public void onNext(Observable nextSequence) { synchronized (nextSequences) { if (innerSubscription == null) { // We are currently not subscribed to any sequence innerSubscription = new SafeObservableSubscription(); innerSubscription.wrap(nextSequence.subscribe(reusableObserver)); } else { // Put this sequence at the end of the queue nextSequences.add(nextSequence); } } } @Override public void onError(Throwable e) { if (completedOrErred.compareAndSet(false, true)) { Subscription q; synchronized (nextSequences) { q = innerSubscription; } if (q != null) { q.unsubscribe(); } observer.onError(e); } } @Override public void onCompleted() { allSequencesReceived.set(true); Subscription q; synchronized (nextSequences) { q = innerSubscription; } if (q == null) { // We are not subscribed to any sequence, and none are coming anymore if (completedOrErred.compareAndSet(false, true)) { observer.onCompleted(); } } } })); return Subscriptions.create(new Action0() { @Override public void call() { Subscription q; synchronized (nextSequences) { q = innerSubscription; } if (q != null) { q.unsubscribe(); } outerSubscription.unsubscribe(); } }); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy