public void testDisposeMasterDisposesDetail() {
    IObservableValue master = new WritableValue();
    WritableListFactory factory = new WritableListFactory();
    master.setValue("");

    IObservableList detailObservable = MasterDetailObservables.detailList(master, factory, null);
    DisposeEventTracker tracker = DisposeEventTracker.observe(detailObservable);

    master.dispose();

    assertEquals(1, tracker.count);
    assertTrue(detailObservable.isDisposed());
  }
  public void testDisposeWhileFiringEvents() {
    IObservableValue master = new WritableValue();
    WritableListFactory factory = new WritableListFactory();
    master.setValue("");

    final IObservableList[] detailObservable = new IObservableList[1];

    master.addValueChangeListener(
        new IValueChangeListener() {
          @Override
          public void handleValueChange(ValueChangeEvent event) {
            detailObservable[0].dispose();
          }
        });

    detailObservable[0] = MasterDetailObservables.detailList(master, factory, null);

    master.setValue("New Value");
  }
 /**
  * Helper method for <code>MasterDetailObservables.detailValue(master,
  * mapEntryValueFactory(map, valueType), valueType)</code>.
  *
  * @param map the observable map whose entry will be tracked.
  * @param master the observable value that identifies which map entry to track.
  * @param valueType the type of the value. May be <code>null</code>, meaning the value is untyped.
  * @return an observable value tracking the current value of the specified key in the given map an
  *     observable value that tracks the current value of the named property for the current value
  *     of the master observable value
  * @since 1.1
  */
 public static IObservableValue observeDetailMapEntry(
     IObservableMap map, IObservableValue master, Object valueType) {
   return MasterDetailObservables.detailValue(
       master, mapEntryValueFactory(map, valueType), valueType);
 }