/*
 * 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++;
    }
  }

  class TaggedItemAddressEditor implements Editor<TaggedItem<Address>> {
    @Path("item.city") SimpleEditor<String> itemCityEditor = SimpleEditor.of(UNINITIALIZED);   
    @Path("item.street") SimpleEditor<String> itemStreetEditor = SimpleEditor.of(UNINITIALIZED);   
    @Path("tag") SimpleEditor<String> tagEditor = SimpleEditor.of(UNINITIALIZED);   
  }

  interface TaggedItemAddressEditorDriver extends
      SimpleBeanEditorDriver<TaggedItem<Address>, TaggedItemAddressEditor> {
  }

  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);
  }

  public void testEditorWithParameterizedModel() {
    TaggedItemAddressEditorDriver driver = GWT.create(TaggedItemAddressEditorDriver.class);
    TaggedItemAddressEditor editor = new TaggedItemAddressEditor();
    driver.initialize(editor);

    TaggedItem<Address> taggedAddress = new TaggedItem<Address>();
    taggedAddress.setTag("tag1");
    taggedAddress.setItem(personAddress);
    driver.edit(taggedAddress);

    assertEquals("tag1", editor.tagEditor.getValue());
    assertEquals("City", editor.itemCityEditor.getValue());
    assertEquals("Street", editor.itemStreetEditor.getValue());

    editor.tagEditor.setValue("tag2");
    editor.itemCityEditor.setValue("Town");
    editor.itemStreetEditor.setValue("Road");
    driver.flush();

    assertEquals("tag2", taggedAddress.getTag());
    assertEquals("Town", taggedAddress.getItem().getCity());
    assertEquals("Road", taggedAddress.getItem().getStreet());
  }

  @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);
  }
}
