/*
 * Copyright 2010 Google 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 com.google.gwt.editor.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.adapters.EditorSource;
import com.google.gwt.editor.client.adapters.ListEditor;
import com.google.gwt.editor.client.adapters.OptionalFieldEditor;
import com.google.gwt.editor.client.adapters.SimpleEditor;
import com.google.gwt.junit.client.GWTTestCase;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Uses the SimpleBeanEditorTest to test core Editor behaviors as generated by
 * AbstractEditorDriverGenerator.
 */
public class SimpleBeanEditorTest extends GWTTestCase {
  class AddressCoEditorView extends LeafAddressEditor implements IsEditor<LeafAddressEditor> {
    private LeafAddressEditor addressEditor = new LeafAddressEditor();

    public LeafAddressEditor asEditor() {
      return addressEditor;
    }
  }

  class AddressEditorPartOne implements Editor<Address> {
    SimpleEditor<String> city = SimpleEditor.of(UNINITIALIZED);
  }

  class AddressEditorPartTwo implements Editor<Address> {
    SimpleEditor<String> street = SimpleEditor.of(UNINITIALIZED);
  }

  class AddressEditorView implements IsEditor<LeafAddressEditor> {
    LeafAddressEditor addressEditor = new LeafAddressEditor();

    public LeafAddressEditor asEditor() {
      return addressEditor;
    }
  }

  /**
   * See <a
   * href="http://code.google.com/p/google-web-toolkit/issues/detail?id=6016"
   * >issue 6016</a>
   */
  static class EditorWithGenericSubEditors implements Editor<Department> {

    PersonGenericEditor<Manager> manager = new PersonGenericEditor<Manager>();

    PersonGenericEditor<Intern> intern = new PersonGenericEditor<Intern>();
  }

  interface EditorWithGenericSubEditorsDriver extends
      SimpleBeanEditorDriver<Department, EditorWithGenericSubEditors> {
  }

  class LeafAddressEditor extends AddressEditor implements LeafValueEditor<Address> {
    /*
     * These two fields are used to ensure that getValue() and setValue() aren't
     * called excessively.
     */
    int getValueCalled;
    int setValueCalled;
    Address value;

    public Address getValue() {
      getValueCalled++;
      return value;
    }

    public void setValue(Address value) {
      setValueCalled++;
      value = new Address();
    }
  }

  interface ListEditorDriver extends
      SimpleBeanEditorDriver<List<String>, ListEditor<String, SimpleEditor<String>>> {
  }

  class PersonEditorWithAddressEditorView implements Editor<Person> {
    AddressEditorView addressEditor = new AddressEditorView();
    SimpleEditor<String> name = SimpleEditor.of(UNINITIALIZED);
  }

  interface PersonEditorWithAddressEditorViewDriver extends
      SimpleBeanEditorDriver<Person, PersonEditorWithAddressEditorView> {
  }

  /**
   * A test for assigning the object associated with an editor to an immediate
   * child editors.
   */
  class PersonEditorWithAliasedSubEditors implements Editor<Person> {
    @Path("")
    PersonEditor e1 = new PersonEditor();

    @Path("")
    PersonEditor e2 = new PersonEditor();
  }

  interface PersonEditorWithAliasedSubEditorsDriver extends
      SimpleBeanEditorDriver<Person, PersonEditorWithAliasedSubEditors> {
  }

  class PersonEditorWithCoAddressEditorView implements Editor<Person> {
    AddressCoEditorView addressEditor = new AddressCoEditorView();
    SimpleEditor<String> name = SimpleEditor.of(UNINITIALIZED);
  }

  interface PersonEditorWithCoAddressEditorViewDriver extends
      SimpleBeanEditorDriver<Person, PersonEditorWithCoAddressEditorView> {
  }

  static class PersonEditorWithDelegate extends PersonEditor implements HasEditorDelegate<Person> {
    EditorDelegate<Person> delegate;

    public void setDelegate(EditorDelegate<Person> delegate) {
      this.delegate = delegate;
    }
  }

  interface PersonEditorWithDelegateDriver extends
      SimpleBeanEditorDriver<Person, PersonEditorWithDelegate> {
  }

  class PersonEditorWithLeafAddressEditor implements Editor<Person> {
    LeafAddressEditor addressEditor = new LeafAddressEditor();
    SimpleEditor<String> name = SimpleEditor.of(UNINITIALIZED);
    @Path("manager.name")
    SimpleEditor<String> managerName = SimpleEditor.of(UNINITIALIZED);
  }

  interface PersonEditorWithLeafAddressEditorDriver extends
      SimpleBeanEditorDriver<Person, PersonEditorWithLeafAddressEditor> {
  }

  class PersonEditorWithManagerNameWithDelegate implements Editor<Person> {
    @Path("manager.name")
    SimpleEditorWithDelegate<String> managerName = new SimpleEditorWithDelegate<String>(
        UNINITIALIZED);
  }

  interface PersonEditorWithManagerNameWithDelegateDriver extends
      SimpleBeanEditorDriver<Person, PersonEditorWithManagerNameWithDelegate> {
  }

  class PersonEditorWithMultipleBindings implements Editor<Person> {
    @Editor.Path("address")
    AddressEditorPartOne one = new AddressEditorPartOne();

    @Editor.Path("address")
    AddressEditorPartTwo two = new AddressEditorPartTwo();
  }

  interface PersonEditorWithMultipleBindingsDriver extends
      SimpleBeanEditorDriver<Person, PersonEditorWithMultipleBindings> {
  }

  interface PersonEditorWithOptionalAddressDriver extends
      SimpleBeanEditorDriver<Person, PersonEditorWithOptionalAddressEditor> {
  }

  static class PersonEditorWithOptionalAddressEditor implements Editor<Person> {
    OptionalFieldEditor<Address, AddressEditor> address;
    SimpleEditor<String> name = SimpleEditor.of(UNINITIALIZED);

    public PersonEditorWithOptionalAddressEditor(AddressEditor delegate) {
      address = OptionalFieldEditor.of(delegate);
    }
  }

  class PersonEditorWithValueAwareAddressEditor implements Editor<Person> {
    ValueAwareAddressEditor addressEditor = new ValueAwareAddressEditor();
    SimpleEditor<String> name = SimpleEditor.of(UNINITIALIZED);
    @Path("manager.name")
    SimpleEditor<String> managerName = SimpleEditor.of(UNINITIALIZED);
  }

  interface PersonEditorWithValueAwareAddressEditorDriver extends
      SimpleBeanEditorDriver<Person, PersonEditorWithValueAwareAddressEditor> {
  }

  class PersonEditorWithValueAwareLeafAddressEditor implements Editor<Person> {
    ValueAwareLeafAddressEditor addressEditor = new ValueAwareLeafAddressEditor();
    SimpleEditor<String> name = SimpleEditor.of(UNINITIALIZED);
    @Path("manager.name")
    SimpleEditor<String> managerName = SimpleEditor.of(UNINITIALIZED);
  }

  interface PersonEditorWithValueAwareLeafAddressEditorDriver extends
      SimpleBeanEditorDriver<Person, PersonEditorWithValueAwareLeafAddressEditor> {
  }

  static class PersonGenericEditor<T extends Person> implements Editor<T> {
    SimpleEditor<String> name = SimpleEditor.of(UNINITIALIZED);
  }

  class PersonWithList {
    String name = "PersonWithList";
    List<Address> addresses = new ArrayList<Address>();

    public List<Address> getAddresses() {
      return addresses;
    }

    public String getName() {
      return name;
    }
  }

  class PersonWithListEditor implements Editor<PersonWithList> {
    SimpleEditor<String> nameEditor = SimpleEditor.of(UNINITIALIZED);
    ListEditor<Address, ValueAwareAddressEditor> addressesEditor = ListEditor
        .of(new EditorSource<ValueAwareAddressEditor>() {
          @Override
          public ValueAwareAddressEditor create(int index) {
            return new ValueAwareAddressEditor();
          }
        });
  }

  interface PersonWithListEditorDriver extends
      SimpleBeanEditorDriver<PersonWithList, PersonWithListEditor> {
  }

  class SimpleEditorWithDelegate<T> extends SimpleEditor<T> implements HasEditorDelegate<T> {
    EditorDelegate<T> delegate;

    public SimpleEditorWithDelegate(T value) {
      super(value);
    }

    public void setDelegate(EditorDelegate<T> delegate) {
      this.delegate = delegate;
    }
  }

  class ValueAwareAddressEditor extends AddressEditor implements ValueAwareEditor<Address> {
    int flushCalled;
    int setDelegateCalled;
    int setValueCalled;
    Address value;

    public void flush() {
      flushCalled++;
    }

    public void onPropertyChange(String... paths) {
    }

    public void setDelegate(EditorDelegate<Address> delegate) {
      setDelegateCalled++;
    }

    public void setValue(Address value) {
      setValueCalled++;
      this.value = value;
    }
  }

  /**
   * All the mix-ins. Not that this seems like a good idea...
   */
  class ValueAwareLeafAddressEditor extends LeafAddressEditor implements ValueAwareEditor<Address> {
    int flushCalled;
    int setDelegateCalled;

    public void flush() {
      flushCalled++;
    }

    public void onPropertyChange(String... paths) {
    }

    public void setDelegate(EditorDelegate<Address> delegate) {
      setDelegateCalled++;
    }
  }

  Person person;
  Address personAddress;
  Person manager;
  long now;

  static final String UNINITIALIZED = "uninitialized";

  @Override
  public String getModuleName() {
    return "com.google.gwt.editor.Editor";
  }

  public void test() {
    PersonEditorDriver driver = GWT.create(PersonEditorDriver.class);
    PersonEditor editor = new PersonEditor();
    driver.initialize(editor);
    driver.edit(person);
    assertEquals(now, editor.localTime.getValue().longValue());
    assertEquals("Alice", editor.name.getValue());
    assertEquals("City", editor.addressEditor.city.getValue());
    assertEquals("Street", editor.addressEditor.street.getValue());
    assertEquals("Bill", editor.managerName.getValue());

    editor.localTime.setValue(now + 1);
    editor.name.setValue("Charles");
    editor.addressEditor.city.setValue("Wootville");
    editor.addressEditor.street.setValue("12345");
    editor.managerName.setValue("David");

    driver.flush();
    assertEquals(now + 1, person.localTime);
    assertEquals("Charles", person.name);
    assertEquals("Wootville", person.address.city);
    assertEquals("12345", person.address.street);
    assertEquals("David", person.manager.name);
  }

  public void testAliasedEditors() {
    PersonEditorWithAliasedSubEditors editor = new PersonEditorWithAliasedSubEditors();
    PersonEditorWithAliasedSubEditorsDriver driver =
        GWT.create(PersonEditorWithAliasedSubEditorsDriver.class);
    driver.initialize(editor);
    driver.edit(person);

    assertEquals("Alice", editor.e1.name.getValue());
    assertEquals("Alice", editor.e2.name.getValue());

    /*
     * Expecting that aliased editors will be editing disjoint sets of
     * properties, but we want to at least have a predictable behavior if two
     * editors are assigned to the same property.
     */
    editor.e1.name.setValue("Should not see this");
    driver.flush();
    assertEquals("Alice", person.getName());

    editor.e2.name.setValue("Should see this");
    driver.flush();
    assertEquals("Should see this", person.getName());
  }

  public void testDelegatePath() {
    PersonEditorWithManagerNameWithDelegate editor = new PersonEditorWithManagerNameWithDelegate();
    PersonEditorWithManagerNameWithDelegateDriver driver =
        GWT.create(PersonEditorWithManagerNameWithDelegateDriver.class);
    driver.initialize(editor);
    driver.edit(person);

    assertEquals("manager.name", editor.managerName.delegate.getPath());
  }

  /**
   * See <a
   * href="http://code.google.com/p/google-web-toolkit/issues/detail?id=6016"
   * >issue 6016</a>
   */
  public void testEditorWithGenericSubEditors() {
    EditorWithGenericSubEditorsDriver driver = GWT.create(EditorWithGenericSubEditorsDriver.class);
    // Issue 6016 would make the above line fail (when generating the editor
    // driver), but let's try editing an object too, it doesn't cost much.
    driver.initialize(new EditorWithGenericSubEditors());
    driver.edit(new Department());
  }

  public void testEditorWithNullSubEditor() {
    PersonEditor editor = new PersonEditor();
    editor.addressEditor = null;
    PersonEditorDriver driver = GWT.create(PersonEditorDriver.class);
    driver.initialize(editor);
    driver.edit(person);

    assertEquals("Alice", editor.name.getValue());
    editor.name.setValue("New name");
    driver.flush();
    assertEquals("New name", person.getName());

    /*
     * Verify that changing the editor structure without re-initializing is a
     * no-op.
     */
    editor.name.setValue("Should see this");
    editor.addressEditor = new AddressEditor();
    editor.addressEditor.city.setValue("Should not see this");
    driver.flush();
    assertEquals("Should see this", person.getName());
    assertEquals("City", person.getAddress().getCity());

    // Re-initialize and check that flushing works again
    driver.initialize(editor);
    driver.edit(person);
    editor.addressEditor.city.setValue("Should see this");
    driver.flush();
    assertEquals("Should see this", person.getAddress().getCity());
  }

  /**
   * Test the use of the IsEditor interface that allows a view object to
   * encapsulate its Editor.
   */
  public void testIsEditorView() {
    PersonEditorWithAddressEditorView personEditor = new PersonEditorWithAddressEditorView();
    PersonEditorWithAddressEditorViewDriver driver =
        GWT.create(PersonEditorWithAddressEditorViewDriver.class);
    testLeafAddressEditor(driver, personEditor, personEditor.addressEditor.asEditor(), true);
  }

  /**
   * Test the use of the IsEditor interface that allows a view object to
   * encapsulate its Editor as well as be an editor itself.
   */
  public void testIsEditorViewWithCoEditorA() {
    PersonEditorWithCoAddressEditorView personEditor = new PersonEditorWithCoAddressEditorView();
    PersonEditorWithCoAddressEditorViewDriver driver =
        GWT.create(PersonEditorWithCoAddressEditorViewDriver.class);
    testLeafAddressEditor(driver, personEditor, personEditor.addressEditor, true);
  }

  /**
   * Test the use of the IsEditor interface that allows a view object to
   * encapsulate its Editor as well as be an editor itself.
   */
  public void testIsEditorViewWithCoEditorB() {
    PersonEditorWithCoAddressEditorView personEditor = new PersonEditorWithCoAddressEditorView();
    PersonEditorWithCoAddressEditorViewDriver driver =
        GWT.create(PersonEditorWithCoAddressEditorViewDriver.class);
    testLeafAddressEditor(driver, personEditor, personEditor.addressEditor.asEditor(), true);
  }

  /**
   * We want to verify that the sub-editors of a LeafValueEditor are not
   * initialized. Additonally, we want to ensure that the instance returned from
   * the LVE is assigned into the owner type.
   */
  public void testLeafValueEditorDeclaredInSlot() {
    PersonEditorWithLeafAddressEditor personEditor = new PersonEditorWithLeafAddressEditor();
    PersonEditorWithLeafAddressEditorDriver driver =
        GWT.create(PersonEditorWithLeafAddressEditorDriver.class);
    LeafAddressEditor addressEditor = personEditor.addressEditor;

    testLeafAddressEditor(driver, personEditor, addressEditor, true);
  }

  /**
   * This tests a weird case where the user has put a LeafValueEditor into a
   * plain Editor field. Because the Editor system relies heavily on static type
   * information at compile time, this is not a supported configuration.
   */
  public void testLeafValueEditorInPlainEditorSlot() {
    PersonEditorDriver driver = GWT.create(PersonEditorDriver.class);

    PersonEditor personEditor = new PersonEditor();
    LeafAddressEditor addressEditor = new LeafAddressEditor();

    // Runtime assignment of unexpected LeafValueEditor
    personEditor.addressEditor = addressEditor;

    testLeafAddressEditor(driver, personEditor, addressEditor, true);
  }

  public void testLifecycle() {
    PersonEditorDriver driver = GWT.create(PersonEditorDriver.class);
    try {
      driver.edit(person);
      fail("Should have thrown execption");
    } catch (IllegalStateException expected) {
    }
    driver.initialize(new PersonEditor());
    try {
      driver.flush();
      fail("Should have thrown exception");
    } catch (IllegalStateException expected) {
    }
    driver.edit(person);
    driver.flush();
  }

  /**
   * Test a top-level ListEditor.
   */
  public void testListEditor() {
    final SortedMap<Integer, SimpleEditor<String>> positionMap =
        new TreeMap<Integer, SimpleEditor<String>>();
    @SuppressWarnings("unchecked")
    final SimpleEditor<String>[] disposed = new SimpleEditor[1];
    class StringSource extends EditorSource<SimpleEditor<String>> {
      public SimpleEditor<String> create(int index) {
        SimpleEditor<String> editor = SimpleEditor.of();
        positionMap.put(index, editor);
        return editor;
      }

      public void dispose(SimpleEditor<String> editor) {
        disposed[0] = editor;
        positionMap.values().remove(editor);
      }

      public void setIndex(SimpleEditor<String> editor, int index) {
        positionMap.values().remove(editor);
        positionMap.put(index, editor);
      }
    };

    ListEditorDriver driver = GWT.create(ListEditorDriver.class);
    ListEditor<String, SimpleEditor<String>> editor = ListEditor.of(new StringSource());

    driver.initialize(editor);

    List<String> rawData = new ArrayList<String>(Arrays.asList("foo", "bar", "baz"));
    driver.edit(rawData);

    List<SimpleEditor<String>> editors = editor.getEditors();
    assertEquals(rawData.size(), editors.size());
    assertEquals(rawData, Arrays.asList(editors.get(0).getValue(), editors.get(1).getValue(),
        editors.get(2).getValue()));
    assertEquals(editors, new ArrayList<SimpleEditor<String>>(positionMap.values()));

    List<String> mutableList = editor.getList();
    assertEquals(rawData, mutableList);

    // Test through wrapped list
    mutableList.set(1, "Hello");
    assertEquals("Hello", editors.get(1).getValue());

    // Test using editor
    editors.get(2).setValue("World");
    assertEquals("baz", rawData.get(2));
    driver.flush();
    assertEquals("World", rawData.get(2));

    // Change list size
    mutableList.add("quux");
    assertEquals(4, editors.size());
    assertEquals("quux", editors.get(3).getValue());
    assertEquals(editors, new ArrayList<SimpleEditor<String>>(positionMap.values()));

    // Delete an element
    SimpleEditor<String> expectedDisposed = editors.get(0);
    mutableList.remove(0);
    assertSame(expectedDisposed, disposed[0]);
    assertEquals(3, editors.size());
    assertEquals("quux", editors.get(2).getValue());
    assertEquals(editors, new ArrayList<SimpleEditor<String>>(positionMap.values()));

    // Change list outside editor: shouldn't impact editors
    rawData.clear();
    rawData.addAll(Arrays.asList("able", "baker"));
    List<String> expectedList = Arrays.asList("Hello", "World", "quux");
    assertEquals(expectedList, editor.getList());
    assertEquals(expectedList.size(), editors.size());
    assertEquals(expectedList, Arrays.asList(editors.get(0).getValue(), editors.get(1).getValue(),
        editors.get(2).getValue()));
    assertEquals(editors, new ArrayList<SimpleEditor<String>>(positionMap.values()));

    // Edit again: should reuse sub-editors and dispose unneeded ones
    disposed[0] = null;
    expectedDisposed = editors.get(2);
    @SuppressWarnings("unchecked")
    List<SimpleEditor<String>> expectedEditors = Arrays.asList(editors.get(0), editors.get(1));
    driver.edit(rawData);
    assertEquals(expectedEditors, editors);
    assertEquals(expectedEditors, editor.getEditors());
    assertEquals(rawData, editor.getList());
    assertEquals(rawData.size(), editors.size());
    assertEquals(rawData, Arrays.asList(editors.get(0).getValue(), editors.get(1).getValue()));
    assertEquals(editors, new ArrayList<SimpleEditor<String>>(positionMap.values()));
    assertEquals(expectedDisposed, disposed[0]);
  }

  /**
   * Ensure that a ListEditor deeper in the chain is properly flushed.
   */
  public void testListEditorChainFlush() {
    PersonWithListEditorDriver driver = GWT.create(PersonWithListEditorDriver.class);
    PersonWithList person = new PersonWithList();
    Address a1 = new Address();
    a1.city = "a1City";
    a1.street = "a1Street";
    Address a2 = new Address();
    a2.city = "a2City";
    a2.street = "a2Street";

    person.addresses.add(a1);
    person.addresses.add(a2);

    PersonWithListEditor personEditor = new PersonWithListEditor();
    // Initialize
    driver.initialize(personEditor);
    // Address editors aren't created until edit() is called
    assertEquals(Collections.emptyList(), personEditor.addressesEditor.getEditors());

    // Edit
    driver.edit(person);
    ValueAwareAddressEditor addressEditor = personEditor.addressesEditor.getEditors().get(1);
    // Check that setValue is only called once on sub-editors (issue 7038)
    assertEquals(1, addressEditor.setValueCalled);

    assertEquals("a2City", addressEditor.city.getValue());
    addressEditor.city.setValue("edited");

    // Flush
    driver.flush();
    assertEquals("edited", person.addresses.get(1).getCity());

    // Verify that setting the same list reuses sub-editors
    addressEditor.setValueCalled = 0;
    driver.edit(person);
    assertSame(addressEditor, personEditor.addressesEditor.getEditors().get(1));
    // Check that setValue has correctly been called on the sub-editor anyway
    assertEquals(1, addressEditor.setValueCalled);

    // Edit with a null list
    person.addresses = null;
    driver.edit(person);
    assertNull(personEditor.addressesEditor.getList());
    assertEquals(Collections.emptyList(), personEditor.addressesEditor.getEditors());
    // Flushing should not throw:
    driver.flush();
    assertNull(person.addresses);
  }

  public void testMultipleBinding() {
    PersonEditorWithMultipleBindingsDriver driver =
        GWT.create(PersonEditorWithMultipleBindingsDriver.class);
    PersonEditorWithMultipleBindings editor = new PersonEditorWithMultipleBindings();

    driver.initialize(editor);
    driver.edit(person);
    assertEquals("City", editor.one.city.getValue());
    assertEquals("Street", editor.two.street.getValue());

    editor.one.city.setValue("Foo");
    editor.two.street.setValue("Bar");
    driver.flush();

    assertEquals("Foo", person.getAddress().getCity());
    assertEquals("Bar", person.getAddress().getStreet());
  }

  public void testOptionalField() {
    PersonEditorWithOptionalAddressDriver driver =
        GWT.create(PersonEditorWithOptionalAddressDriver.class);
    person.address = null;

    AddressEditor delegate = new AddressEditor();
    PersonEditorWithOptionalAddressEditor editor =
        new PersonEditorWithOptionalAddressEditor(delegate);
    driver.initialize(editor);

    // Make sure we don't blow up with the null field
    driver.edit(person);
    editor.address.setValue(personAddress);
    assertEquals("City", delegate.city.getValue());
    delegate.city.setValue("Hello");
    driver.flush();
    assertNotNull(person.address);
    assertSame(personAddress, person.address);
    assertEquals("Hello", personAddress.city);

    editor.address.setValue(null);
    driver.flush();
    assertNull(person.address);
  }

  public void testValueAwareEditorInDeclaredSlot() {
    PersonEditorWithValueAwareAddressEditorDriver driver =
        GWT.create(PersonEditorWithValueAwareAddressEditorDriver.class);
    PersonEditorWithValueAwareAddressEditor personEditor =
        new PersonEditorWithValueAwareAddressEditor();
    ValueAwareAddressEditor addressEditor = personEditor.addressEditor;

    testValueAwareAddressEditor(driver, personEditor, addressEditor);
  }

  /**
   * This is another instance of a LeafValueEditor found in a plain slot.
   */
  public void testValueAwareEditorInPlainSlot() {
    PersonEditorDriver driver = GWT.create(PersonEditorDriver.class);

    PersonEditor personEditor = new PersonEditor();
    ValueAwareAddressEditor addressEditor = new ValueAwareAddressEditor();

    // Runtime assignment of unexpected LeafValueEditor
    personEditor.addressEditor = addressEditor;

    testValueAwareAddressEditor(driver, personEditor, addressEditor);
  }

  public void testValueAwareLeafValueEditorInDeclaredSlot() {
    PersonEditorWithValueAwareLeafAddressEditor personEditor =
        new PersonEditorWithValueAwareLeafAddressEditor();
    PersonEditorWithValueAwareLeafAddressEditorDriver driver =
        GWT.create(PersonEditorWithValueAwareLeafAddressEditorDriver.class);
    ValueAwareLeafAddressEditor addressEditor = personEditor.addressEditor;

    testLeafAddressEditor(driver, personEditor, addressEditor, true);
    assertEquals(1, addressEditor.flushCalled);
    assertEquals(1, addressEditor.setDelegateCalled);
  }

  public void testValueAwareLeafValueEditorInPlainEditorSlot() {
    PersonEditorDriver driver = GWT.create(PersonEditorDriver.class);

    PersonEditor personEditor = new PersonEditor();
    ValueAwareLeafAddressEditor addressEditor = new ValueAwareLeafAddressEditor();

    // Runtime assignment of unexpected LeafValueEditor
    personEditor.addressEditor = addressEditor;

    testLeafAddressEditor(driver, personEditor, addressEditor, true);
    assertEquals(1, addressEditor.flushCalled);
    assertEquals(1, addressEditor.setDelegateCalled);
  }

  @Override
  protected void gwtSetUp() throws Exception {
    personAddress = new Address();
    personAddress.city = "City";
    personAddress.street = "Street";

    manager = new Person();
    manager.name = "Bill";

    person = new Person();
    person.address = personAddress;
    person.name = "Alice";
    person.manager = manager;
    person.localTime = now = System.currentTimeMillis();
  }

  private <T extends Editor<Person>> void testLeafAddressEditor(
      SimpleBeanEditorDriver<Person, T> driver, T personEditor, LeafAddressEditor addressEditor,
      boolean declaredAsLeaf) {
    Address oldAddress = person.address;
    // Initialize
    driver.initialize(personEditor);
    assertEquals(0, addressEditor.setValueCalled);
    assertEquals(0, addressEditor.getValueCalled);

    // Edit
    driver.edit(person);
    assertEquals(1, addressEditor.setValueCalled);
    // The DirtCollector will interrogate the leaf editors
    assertEquals(1, addressEditor.getValueCalled);

    // Flush
    driver.flush();
    assertEquals(1, addressEditor.setValueCalled);
    assertEquals(2, addressEditor.getValueCalled);
    assertNotSame(oldAddress, person.address);
    assertSame(person.address, addressEditor.value);
  }

  private <T extends Editor<Person>> void testValueAwareAddressEditor(
      SimpleBeanEditorDriver<Person, T> driver, T personEditor,
      ValueAwareAddressEditor addressEditor) {
    Address oldAddress = person.address;
    // Initialize
    driver.initialize(personEditor);
    assertEquals(0, addressEditor.setValueCalled);
    assertEquals(0, addressEditor.setDelegateCalled);
    assertEquals(0, addressEditor.flushCalled);

    // Edit
    driver.edit(person);
    assertEquals(1, addressEditor.setValueCalled);
    assertEquals(1, addressEditor.setDelegateCalled);
    assertEquals(0, addressEditor.flushCalled);
    assertEquals("City", addressEditor.city.getValue());

    // Flush
    driver.flush();
    assertEquals(1, addressEditor.setValueCalled);
    assertEquals(1, addressEditor.setDelegateCalled);
    assertEquals(1, addressEditor.flushCalled);
    assertSame(oldAddress, person.address);
    assertSame(person.address, addressEditor.value);
  }
}
