<T> Observable<T> errorWhenLoggedIn(Throwable throwable) {
   if (throwable instanceof AuthException) {
     return userDataSource.getCurrentUser().flatMap(user -> Observable.error(throwable));
   } else {
     return Observable.error(throwable);
   }
 }
Esempio n. 2
0
  @SuppressWarnings({"unchecked", "RedundantCast"})
  private static Observable<Object> invokeWithRetry(
      Api api, Method method, Object[] args, Predicate<Throwable> shouldRetryTest, int retryCount)
      throws IllegalAccessException, InvocationTargetException {

    Observable<Object> result = (Observable<Object>) method.invoke(api, args);
    for (int i = 0; i < retryCount; i++) {
      result =
          result.onErrorResumeNext(
              err -> {
                if (shouldRetryTest.apply(err)) {
                  try {
                    // give the server a small grace period before trying again.
                    Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);

                    logger.warn("perform retry, calling method {} again", method);
                    return (Observable<Object>) method.invoke(api, args);
                  } catch (Exception error) {
                    return Observable.error(error);
                  }
                } else {
                  // forward error if it is not a network problem
                  return Observable.error(err);
                }
              });
    }

    return result;
  }
Esempio n. 3
0
 /**
  * Creates a credential request to get a CK
  *
  * @param _applicationKey the OVH API application key
  * @param _applicationSecret the OVH API application secret
  * @param _rules the list of rules to be granted by the CK
  * @param _redirection the redirection url for after-connection
  * @return an Observable CredentialRequest
  */
 public static Observable<CredentialRequest> build(
     String _applicationKey, String _applicationSecret, AccessRules _rules, String _redirection) {
   return new RequestBuilder("/auth/credential", Method.POST, _applicationKey)
       .body(
           new JSONObject()
               .put("redirection", _redirection)
               .put("accessRules", _rules.toJson())
               .toString())
       .build()
       .flatMap(
           (SafeResponse t1) -> {
             if (t1.getStatus() < 200
                 || t1.getStatus() >= 300
                 || t1.getBody() == null
                 || t1.getBody().isArray()) {
               return Observable.error(
                   new RequestException(
                       t1.getStatus(),
                       t1.getStatusText(),
                       (t1.getBody() == null) ? null : t1.getBody().toString()));
             }
             JSONObject token = t1.getBody().getObject();
             return Observable.just(
                 new CredentialRequest(
                     _applicationKey,
                     _applicationSecret,
                     token.getString("consumerKey"),
                     token.getString("validationUrl")));
           });
 }
Esempio n. 4
0
  @Test
  public void testFlatMapTransformsException() {
    Observable<Integer> onNext = Observable.from(Arrays.asList(1, 2, 3));
    Observable<Integer> onCompleted = Observable.from(Arrays.asList(4));
    Observable<Integer> onError = Observable.from(Arrays.asList(5));

    Observable<Integer> source =
        Observable.concat(
            Observable.from(Arrays.asList(10, 20, 30)),
            Observable.<Integer>error(new RuntimeException("Forced failure!")));

    @SuppressWarnings("unchecked")
    Observer<Object> o = mock(Observer.class);

    source.flatMap(just(onNext), just(onError), just0(onCompleted)).subscribe(o);

    verify(o, times(3)).onNext(1);
    verify(o, times(3)).onNext(2);
    verify(o, times(3)).onNext(3);
    verify(o).onNext(5);
    verify(o).onCompleted();
    verify(o, never()).onNext(4);

    verify(o, never()).onError(any(Throwable.class));
  }
Esempio n. 5
0
  /**
   * Executes the interceptor chain for the passed request and response.
   *
   * @param request Request to be executed.
   * @param response Response to be populated.
   * @param keyEvaluationContext The context for {@link InterceptorKey} evaluation.
   * @return The final result of execution after executing all the inbound and outbound interceptors
   *     and the router.
   */
  public Observable<Void> execute(final I request, final O response, C keyEvaluationContext) {
    final ExecutionContext context = new ExecutionContext(request, keyEvaluationContext);
    InboundInterceptor<I, O> nextIn = context.nextIn(request);
    Observable<Void> startingPoint;

    if (null != nextIn) {
      startingPoint = nextIn.in(request, response);
    } else if (context.invokeRouter()) {
      startingPoint = router.handle(request, response);
    } else {
      return Observable.error(
          new IllegalStateException("No router defined.")); // No router defined.
    }

    return startingPoint.lift(
        new Observable.Operator<Void, Void>() {
          @Override
          public Subscriber<? super Void> call(Subscriber<? super Void> child) {
            SerialSubscription subscription = new SerialSubscription();
            ChainSubscriber chainSubscriber =
                new ChainSubscriber(subscription, context, request, response, child);
            subscription.set(chainSubscriber);
            child.add(subscription);
            return chainSubscriber;
          }
        });
  }
Esempio n. 6
0
 @Test
 public void testAssertError() {
   RuntimeException e = new RuntimeException("Oops");
   TestSubscriber<Object> subscriber = new TestSubscriber<Object>();
   Observable.error(e).subscribe(subscriber);
   subscriber.assertError(e);
 }
  public Observable<List<TwitterUser>> searchUsers(String prefix) {
    if (ThreadLocalRandom.current().nextDouble() < failureProbability) {
      return Observable.error(new IOException("Broken pipe"));
    }

    return Observable.from(users).skip(1).toList().subscribeOn(Schedulers.newThread());
  }
    @Override
    public Observable<ByteBuf> get(final String key, Map<String, Object> requestProperties) {
      if (key.equals(id)) {
        return Observable.just(Unpooled.buffer().writeBytes(id.getBytes(Charset.defaultCharset())));

      } else {
        return Observable.error(new IllegalArgumentException());
      }
    };
  @Test
  public void loadRepoEventsObservableThrowsError() {
    when(repo.getModificationId()).thenReturn("modif id");

    when(repo.getEventsSubscribedOnProperScheduler()).thenReturn(Observable.error(new Throwable()));
    sut.loadEvents(false, callback);

    verify(callback).onEventsLoadingStarted("modif id");
    verify(callback).onEventsLoadingCancelled("modif id");
  }
 public Observable<List<Item>> getEmulateResponse(int offset, int limit) {
   if (offset == OFFSET_WHEN_FAKE_ERROR && fakeErrorCount < MAX_FAKE_ERROR_COUNT) {
     // emulate fake error in response
     fakeErrorCount++;
     return Observable.error(new RuntimeException("fake error"));
   } else {
     return Observable.defer(() -> Observable.just(getFakeItemList(offset, limit)))
         .delaySubscription(FAKE_RESPONSE_TIME_IN_MS, TimeUnit.MILLISECONDS);
   }
 }
 public void loadTeam(int teamNumber) {
   getMvpView().clearCurrentTeamLocations();
   mRxTeamLocationsCacheHelper.cache(
       mDataManager
           .getTeamLocationRecordsFromServer(teamNumber)
           .flatMap(
               listResponse ->
                   listResponse.code() == HttpStatus.NOT_FOUND
                       ? Observable.error(new TeamNotFoundException(listResponse))
                       : Observable.just(listResponse))
           .flatMap(HttpStatus::requireOk)
           .compose(RxUtil.applyIoSchedulers()));
   continueCachedTeamLocationsRequest();
 }
  @Test
  @SuppressWarnings("unchecked")
  public void testDematerialize3() {
    Exception exception = new Exception("test");
    Observable<Integer> observable = Observable.error(exception);
    Observable<Integer> dematerialize = Observable.create(dematerialize(observable.materialize()));

    Observer<Integer> observer = mock(Observer.class);
    dematerialize.subscribe(observer);

    verify(observer, times(1)).onError(exception);
    verify(observer, times(0)).onCompleted();
    verify(observer, times(0)).onNext(any(Integer.class));
  }
  @Test
  public void signInFailsWithGeneralError() {
    main.launchActivity(SignInActivity.getStartIntent(component.getContext(), false));
    stubAccountPickerIntent();

    // Stub an error when calling sign in
    doReturn(Observable.error(new RuntimeException("Error")))
        .when(component.getMockDataManager())
        .signIn(mSelectedAccount);

    onView(withId(R.id.button_sign_in)).perform(click());
    allowPermissionsIfNeeded();

    onView(withText(R.string.error_sign_in)).check(matches(isDisplayed()));
  }
Esempio n. 14
0
 @Test
 public void testPropogateErrorInTheMiddleOfMultibyte() {
   Observable<byte[]> src = Observable.from(new byte[] {(byte) 0xc2});
   Observable<byte[]> err = Observable.error(new IOException());
   CharsetDecoder charsetDecoder = Charset.forName("UTF-8").newDecoder();
   try {
     StringObservable.decode(Observable.concat(src, err), charsetDecoder)
         .toList()
         .toBlockingObservable()
         .single();
     fail();
   } catch (RuntimeException e) {
     assertEquals(MalformedInputException.class, e.getCause().getClass());
   }
 }
Esempio n. 15
0
 // Save image on disk
 private Observable<Page> downloadImage(
     Page page, Source source, File directory, String filename) {
   page.setStatus(Page.DOWNLOAD_IMAGE);
   return source
       .getImageProgressResponse(page)
       .flatMap(
           resp -> {
             try {
               DiskUtils.saveBufferedSourceToDirectory(resp.body().source(), directory, filename);
             } catch (Exception e) {
               Timber.e(e.getCause(), e.getMessage());
               return Observable.error(e);
             }
             return Observable.just(page);
           })
       .retry(2);
 }
Esempio n. 16
0
  @Test
  public void testFlatMapTransformsMergeException() {
    Observable<Integer> onNext = Observable.error(new TestException());
    Observable<Integer> onCompleted = Observable.from(Arrays.asList(4));
    Observable<Integer> onError = Observable.from(Arrays.asList(5));

    Observable<Integer> source = Observable.from(Arrays.asList(10, 20, 30));

    @SuppressWarnings("unchecked")
    Observer<Object> o = mock(Observer.class);

    source.flatMap(just(onNext), just(onError), funcThrow0(onCompleted)).subscribe(o);

    verify(o).onError(any(TestException.class));
    verify(o, never()).onNext(any());
    verify(o, never()).onCompleted();
  }
Esempio n. 17
0
  private Api newProxyWrapper() {
    Api backend = newRestAdapter();
    // proxy to add the nonce if not provided
    return Reflection.newProxy(
        Api.class,
        (proxy, method, args) -> {
          Class<?>[] params = method.getParameterTypes();
          if (params.length > 0 && params[0] == Api.Nonce.class) {
            if (args.length > 0 && args[0] == null) {

              // inform about failure.
              try {
                args = Arrays.copyOf(args, args.length);
                args[0] = cookieHandler.getNonce();

              } catch (Throwable error) {
                AndroidUtility.logToCrashlytics(error);

                if (method.getReturnType() == Observable.class) {
                  // don't fail here, but fail in the resulting observable.
                  return Observable.error(error);

                } else {
                  throw error;
                }
              }
            }
          }

          if (method.getReturnType() == Observable.class) {
            // check if this is a get for retry.
            int retryCount = 2;
            if (method.getAnnotation(GET.class) != null) {
              return invokeWithRetry(backend, method, args, ApiProvider::isHttpError, retryCount);
            } else {
              return invokeWithRetry(backend, method, args, ApiProvider::isHttpError, retryCount);
            }
          }

          try {
            return method.invoke(backend, args);
          } catch (InvocationTargetException targetError) {
            throw targetError.getCause();
          }
        });
  }
  @Test
  public void testBottomLetterPressedWithCorrectAnswerAndErrorOccurs() {
    when(mockRepository.getRandomWord()).thenReturn(Observable.<Word>error(new Exception()));
    when(mockStore.state())
        .thenReturn(createState("test", toListOfLetters("test"), singletonList("test"), 0, 1L));

    actionCreator.bottomLetterPressed();

    ArgumentCaptor<Action> actionCaptor = ArgumentCaptor.forClass(Action.class);
    verify(mockStore, times(3)).dispatch(actionCaptor.capture());

    List<Action> capturedActions = actionCaptor.getAllValues();

    assertEquals(capturedActions.get(0), Action.BottomPressed.INSTANCE);
    assertEquals(capturedActions.get(1), Action.Back.INSTANCE);
    assertEquals(capturedActions.get(2), Action.LoadWordError.INSTANCE);
  }
  @Test
  public void signInFailsWithProfileNotFound() {
    main.launchActivity(SignInActivity.getStartIntent(component.getContext(), false));
    stubAccountPickerIntent();

    // Stub with http 403 error
    HttpException http403Exception = new HttpException(Response.error(403, null));
    doReturn(Observable.error(http403Exception))
        .when(component.getMockDataManager())
        .signIn(mSelectedAccount);

    onView(withId(R.id.button_sign_in)).perform(click());
    allowPermissionsIfNeeded();

    String expectedWelcome =
        main.getActivity().getString(R.string.error_ribot_profile_not_found, mSelectedAccount.name);
    onView(withText(expectedWelcome)).check(matches(isDisplayed()));
  }
  @Test
  public void testInitiateGameError() {
    when(mockRepository.getRandomWord()).thenReturn(Observable.<Word>error(new Exception()));

    actionCreator.initiateGame();

    ArgumentCaptor<Action> actionCaptor = ArgumentCaptor.forClass(Action.class);
    verify(mockStore, times(3)).dispatch(actionCaptor.capture());

    List<Action> capturedActions = actionCaptor.getAllValues();

    Action.Navigate firstAction = (Action.Navigate) capturedActions.get(0);
    assertEquals(firstAction.getPage().getLayoutId(), R.layout.loading);
    assertEquals(firstAction.getAddToBackStack(), true);

    assertEquals(capturedActions.get(1), Action.Back.INSTANCE);
    assertEquals(capturedActions.get(2), Action.LoadWordError.INSTANCE);
  }
Esempio n. 21
0
  // Download the entire chapter
  private Observable<Download> downloadChapter(Download download) {
    try {
      DiskUtils.createDirectory(download.directory);
    } catch (IOException e) {
      return Observable.error(e);
    }

    Observable<List<Page>> pageListObservable =
        download.pages == null
            ?
            // Pull page list from network and add them to download object
            download
                .source
                .pullPageListFromNetwork(download.chapter.url)
                .doOnNext(pages -> download.pages = pages)
                .doOnNext(pages -> savePageList(download))
            :
            // Or if the page list already exists, start from the file
            Observable.just(download.pages);

    return pageListObservable
        .subscribeOn(Schedulers.io())
        .doOnNext(
            pages -> {
              download.downloadedImages = 0;
              download.setStatus(Download.DOWNLOADING);
            })
        // Get all the URLs to the source images, fetch pages if necessary
        .flatMap(download.source::getAllImageUrlsFromPageList)
        // Start downloading images, consider we can have downloaded images already
        .concatMap(page -> getOrDownloadImage(page, download))
        // Do after download completes
        .doOnCompleted(() -> onDownloadCompleted(download))
        .toList()
        .map(pages -> download)
        // If the page list threw, it will resume here
        .onErrorResumeNext(
            error -> {
              download.setStatus(Download.ERROR);
              return Observable.just(download);
            });
  }
Esempio n. 22
0
  //    @RxLogObservable(RxLogObservable.Scope.NOTHING)
  @RxLogObservable
  public static Observable<List<HeroAndAdvantages>> getObservable(
      List<String> heroesInPhoto,
      boolean networkAvailable,
      final Pair<List<String>, List<HeroAndAdvantages>> lastAdvantageData) {
    if (networkAvailable == false) {
      // There's no network connection so we might as well give up now
      return Observable.error(new Throwable("No network available"));
    }

    RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint(SERVICE_ENDPOINT).build();

    AdvantagesApi advantagesApi = restAdapter.create(AdvantagesApi.class);

    if (heroesInPhoto.size() != 5) {
      throw new RuntimeException("Wrong number of heroes. Need 5");
    }

    if (lastAdvantageData != null) {
      final int differencePos = findSingleDifference(heroesInPhoto, lastAdvantageData.first);
      if (differencePos == NO_DIFFERENCES_FOUND) {
        // If the heroes are the same as those we processed last time then we can just send
        // back the same results as last time
        Log.d(TAG, "No differences found.");
        return Observable.just(lastAdvantageData.second);
      }
      if (differencePos != MULTIPLE_DIFFERENCES_FOUND) {
        // If there is only one hero which has changed then we only need to ask the server
        // to give us data on that hero (this makes it easier, and quicker, for the server)
        return getSingleHeroChangedObservable(
            lastAdvantageData.second, heroesInPhoto, differencePos, advantagesApi);
      }
    }

    List<String> testList = Arrays.asList("", "", "", "", "");
    int singleHeroPos = findSingleDifference(heroesInPhoto, testList);
    if (singleHeroPos != NO_DIFFERENCES_FOUND && singleHeroPos != MULTIPLE_DIFFERENCES_FOUND) {
      return getSingleNewHeroObservable(advantagesApi, singleHeroPos, heroesInPhoto);
    }

    return getFullObservable(advantagesApi, heroesInPhoto);
  }
Esempio n. 23
0
  @Test
  public void testDelayedErrorDeliveryWhenSafeSubscriberUnsubscribes() {
    TestScheduler testScheduler = new TestScheduler();

    Observable<Integer> source =
        Observable.concat(Observable.<Integer>error(new TestException()), Observable.just(1));

    @SuppressWarnings("unchecked")
    Observer<Integer> o = mock(Observer.class);
    InOrder inOrder = inOrder(o);

    source.observeOn(testScheduler).subscribe(o);

    inOrder.verify(o, never()).onError(any(TestException.class));

    testScheduler.advanceTimeBy(1, TimeUnit.SECONDS);

    inOrder.verify(o).onError(any(TestException.class));
    inOrder.verify(o, never()).onNext(anyInt());
    inOrder.verify(o, never()).onCompleted();
  }
Esempio n. 24
0
 static Observable<File> unTar(
     File archiveFile,
     Collection collection,
     String lastModified,
     IonConfig config,
     Context context) {
   return Observable.just(null)
       .flatMap(
           o -> {
             try {
               return Observable.from(
                       performUnTar(archiveFile, config, collection, lastModified, context))
                   // write cache index entries
                   .doOnNext(
                       fileWithType ->
                           saveCacheIndex(fileWithType, collection, lastModified, config, context))
                   .map(fileWithType -> fileWithType.file);
             } catch (IOException | ArchiveException e) {
               return Observable.error(e);
             }
           });
 }
  public static Observable<Tuple2<Integer, Bundle>> startActivityForObservable(
      String tag, Activity activity, Intent intent) {
    final ResultData resultData = savedInstanceStateMap.get(tag);
    if (resultData == null)
      return Observable.error(new RuntimeException("Do not have this Activity state: tag=" + tag));

    return Observable.create(
        new Observable.OnSubscribe<Tuple2<Integer, Bundle>>() {
          @Override
          public void call(final Subscriber<? super Tuple2<Integer, Bundle>> sub) {
            final int requestCode = random.nextInt() & 0x0000ffff;
            activity.startActivityForResult(intent, requestCode);
            resultData
                .getOnResultSubject()
                .subscribe(
                    tuple -> {
                      if (requestCode == tuple.getData1())
                        sub.onNext(Tuple2.of(tuple.getData2(), tuple.getData3()));
                      sub.onCompleted();
                    },
                    sub::onError);
          }
        });
  }
 @HystrixCommand
 public Observable<Void> observableCommandShouldRaiseHystrixRuntimeException()
     throws SpecificException {
   return Observable.error(
       new SpecificException("from 'observableCommandShouldRaiseHystrixRuntimeException'"));
 }
  @NonNull
  @Override
  public Observable<Void> write(
      @NonNull final GattPeripheral.WriteType writeType,
      @NonNull final byte[] payload,
      @NonNull final OperationTimeout timeout) {
    if (payload.length > PACKET_LENGTH) {
      return Observable.error(
          new IllegalArgumentException(
              "Payload length " + payload.length + " greater than " + PACKET_LENGTH));
    }

    return peripheral.createObservable(
        new Observable.OnSubscribe<Void>() {
          @Override
          public void call(final Subscriber<? super Void> subscriber) {
            if (peripheral.getConnectionStatus() != GattPeripheral.STATUS_CONNECTED
                || peripheral.gatt == null) {
              subscriber.onError(new ConnectionStateException());
              return;
            }

            final Runnable onDisconnect =
                peripheral.addTimeoutDisconnectListener(subscriber, timeout);
            peripheral.setupTimeout(
                Operation.ENABLE_NOTIFICATION, timeout, subscriber, onDisconnect);

            gattDispatcher.characteristicWrite =
                new CharacteristicWriteListener() {
                  @Override
                  public void onCharacteristicWrite(
                      @NonNull BluetoothGatt gatt,
                      @NonNull BluetoothGattCharacteristic characteristic,
                      int status) {
                    timeout.unschedule();

                    if (status != BluetoothGatt.GATT_SUCCESS) {
                      logger.error(
                          GattPeripheral.LOG_TAG,
                          "Could not write command "
                              + getUuid()
                              + ", "
                              + GattException.statusToString(status),
                          null);
                      subscriber.onError(new GattException(status, Operation.WRITE_COMMAND));
                    } else {
                      subscriber.onNext(null);
                      subscriber.onCompleted();
                    }

                    peripheral.removeDisconnectListener(onDisconnect);
                    gattDispatcher.characteristicWrite = null;
                  }
                };

            final BluetoothGattCharacteristic characteristic =
                service.wrappedService.getCharacteristic(getUuid());
            // Looks like write type might need to be specified for some phones. See
            // <http://stackoverflow.com/questions/25888817/android-bluetooth-status-133-in-oncharacteristicwrite>
            characteristic.setWriteType(writeType.value);
            characteristic.setValue(payload);
            if (peripheral.gatt.writeCharacteristic(characteristic)) {
              timeout.schedule();
            } else {
              peripheral.removeDisconnectListener(onDisconnect);
              gattDispatcher.characteristicWrite = null;

              subscriber.onError(
                  new GattException(
                      BluetoothGatt.GATT_WRITE_NOT_PERMITTED, Operation.WRITE_COMMAND));
            }
          }
        });
  }
Esempio n. 28
0
  private Observable<Navajo> processNavajoEvent(
      NavajoStreamEvent n, Subscriber<? super Navajo> subscriber) {
    switch (n.type()) {
      case NAVAJO_STARTED:
        createHeader((NavajoHead) n.body());
        return Observable.<Navajo>empty();

      case MESSAGE_STARTED:
        Message prMessage = null;
        if (!messageStack.isEmpty()) {
          prMessage = messageStack.peek();
        }
        String mode = (String) n.attribute("mode");

        Message msg =
            NavajoFactory.getInstance().createMessage(assemble, n.path(), Message.MSG_TYPE_SIMPLE);
        msg.setMode(mode);
        if (prMessage == null) {
          assemble.addMessage(msg);
        } else {
          prMessage.addMessage(msg);
        }
        messageStack.push(msg);
        tagStack.push(n.path());
        return Observable.<Navajo>empty();
      case MESSAGE:
        Message msgParent = messageStack.pop();
        tagStack.pop();
        Msg mm = (Msg) n.body();
        List<Prop> msgProps = mm.properties();
        for (Prop e : msgProps) {
          msgParent.addProperty(createTmlProperty(e));
        }
        for (Entry<String, Binary> e : pushBinaries.entrySet()) {
          msgParent.addProperty(createBinaryProperty(e.getKey(), e.getValue()));
        }
        pushBinaries.clear();
        return Observable.<Navajo>empty();
      case ARRAY_STARTED:
        tagStack.push(n.path());
        String path = currentPath();
        AtomicInteger cnt = arrayCounts.get(path);
        if (cnt == null) {
          cnt = new AtomicInteger();
          arrayCounts.put(path, cnt);
        }
        //			cnt.incrementAndGet();
        Message parentMessage = null;
        if (!messageStack.isEmpty()) {
          parentMessage = messageStack.peek();
        }

        Message arr =
            NavajoFactory.getInstance().createMessage(assemble, n.path(), Message.MSG_TYPE_ARRAY);
        if (parentMessage == null) {
          assemble.addMessage(arr);
        } else {
          parentMessage.addMessage(arr);
        }
        messageStack.push(arr);
        return Observable.<Navajo>empty();
      case ARRAY_DONE:
        String apath = currentPath();
        arrayCounts.remove(apath);
        this.messageStack.pop();
        return Observable.<Navajo>empty();
      case ARRAY_ELEMENT_STARTED:
        String arrayElementName = tagStack.peek();
        String arrayPath = currentPath();
        AtomicInteger currentCount = arrayCounts.get(arrayPath);
        String ind = "@" + currentCount.getAndIncrement();
        tagStack.push(ind);
        arrayPath = currentPath();
        Message newElt =
            NavajoFactory.getInstance()
                .createMessage(assemble, arrayElementName, Message.MSG_TYPE_ARRAY_ELEMENT);
        Message arrParent = messageStack.peek();
        arrParent.addElement(newElt);
        messageStack.push(newElt);
        return Observable.<Navajo>empty();
      case ARRAY_ELEMENT:
        tagStack.pop();
        Message elementParent = messageStack.pop();
        Msg msgElement = (Msg) n.body();
        List<Prop> elementProps = msgElement.properties();
        for (Prop e : elementProps) {
          elementParent.addProperty(createTmlProperty(e));
        }
        for (Entry<String, Binary> e : pushBinaries.entrySet()) {
          elementParent.addProperty(createBinaryProperty(e.getKey(), e.getValue()));
        }
        pushBinaries.clear();

        return Observable.<Navajo>empty();

      case MESSAGE_DEFINITION_STARTED:
        // TODO
        return Observable.<Navajo>empty();
      case MESSAGE_DEFINITION:
        // TODO
        //			tagStack.push(n.path());
        //			deferredMessages.get(stripIndex(n.path())).setDefinitionMessage((Message) n.body());
        return Observable.<Navajo>empty();
      case NAVAJO_DONE:
        if (subscriber != null) {
          subscriber.onNext(assemble);
        }
        return Observable.<Navajo>just(assemble);

      case BINARY_STARTED:
        try {
          String name = n.path();
          this.currentBinary = new Binary();
          this.currentBinary.startPushRead();
          this.pushBinaries.put(name, currentBinary);
          return Observable.<Navajo>empty();
        } catch (IOException e1) {
          return Observable.error(e1);
        }

      case BINARY_CONTENT:
        try {
          if (this.currentBinary == null) {
            // whoops;
          }
          this.currentBinary.pushContent((String) n.body());
          return Observable.<Navajo>empty();
        } catch (IOException e1) {
          return Observable.error(e1);
        }

      case BINARY_DONE:
        try {
          this.currentBinary.finishPushContent();
          return Observable.<Navajo>empty();
        } catch (IOException e1) {
          return Observable.error(e1);
        }
      default:
        return Observable.<Navajo>empty();
    }
  }