/**
   * Checks equality and hash codes for PlantComposites. All child components from two composites
   * should be compared.
   */
  @Test
  public void checkEquality() {

    // Initialize objects for testing.
    PlantComposite object = new PlantComposite();
    PlantComposite equalObject = new PlantComposite();

    // Set up the two objects.
    object.addPlantComponent(new PlantComponent("optimus"));
    equalObject.addPlantComponent(new PlantComponent("optimus"));

    // Make sure the references are different but the objects are equal.
    assertFalse(object == equalObject);
    assertTrue(object.equals(equalObject));
    assertTrue(equalObject.equals(object));

    // Check the hash codes.
    assertEquals(object.hashCode(), equalObject.hashCode());

    // ---- Check inequality. ---- //
    // Create an unequal object.
    PlantComposite unequalObject = equalObject;
    unequalObject.getComponents().get(0).setName("megatron");

    // Make sure the references are different and the objects unequal.
    assertFalse(object == equalObject);
    assertFalse(object.equals(unequalObject));
    assertFalse(unequalObject.equals(object));

    // Check the hash codes.
    assertFalse(object.hashCode() == unequalObject.hashCode());

    // Try other invalid objects.
    assertFalse(object == null);
    assertFalse("starscream".equals(object));

    return;
  }
  /** Checks the copy and clone methods for PlantComposites. */
  @Test
  public void checkCopying() {

    // Initialize objects for testing.
    PlantComposite object = new PlantComposite();
    PlantComposite copy = new PlantComposite();
    PlantComposite clone = null;

    // Set up the object.
    object.addPlantComponent(new PlantComponent("bumblebee"));

    // Make sure the objects are not equal before copying.
    assertFalse(object == copy);
    assertFalse(object.equals(copy));

    // Copy the object.
    copy.copy(object);

    // Make sure the references are different but contents the same.
    assertFalse(object == copy);
    assertTrue(object.equals(copy));

    // Do the same for the clone operation.

    // Make sure the objects are not equal before copying.
    assertFalse(object == clone);
    assertFalse(object.equals(clone));

    // Clone the object.
    clone = (PlantComposite) object.clone();

    // Make sure the references are different but contents the same.
    assertFalse(object == clone);
    assertTrue(object.equals(clone));
    assertFalse(copy == clone);
    assertTrue(copy.equals(clone));

    return;
  }
  /** Checks the ability to add PlantComponents to the Composite. */
  @Test
  public void checkCompositeImplementation() {

    // Create a PlantComposite for testing.
    PlantComposite composite = new PlantComposite();

    // Create a PlantComponent for adding to the composite.
    PlantComponent component = new PlantComponent("snake eyes");

    // ---- addComponent should do nothing. ---- //
    composite.addComponent(component);

    // None of the lists should contain components.
    assertEquals(0, composite.getNumberOfComponents());
    assertNotNull(composite.getComponents());
    assertTrue(composite.getComponents().isEmpty());
    assertNotNull(composite.getPlantComponents());
    assertTrue(composite.getPlantComponents().isEmpty());

    // ---- addPlantComponent should add a PlantComponent. ---- //
    composite.addPlantComponent(component);

    // There should be one component.
    assertEquals(1, composite.getNumberOfComponents());
    assertNotNull(composite.getComponents());
    assertEquals(1, composite.getComponents().size());
    assertNotNull(composite.getPlantComponents());
    assertEquals(1, composite.getPlantComponents().size());

    // We should be able to get the same component out.
    assertSame(component, composite.getComponent(component.getId()));
    assertSame(component, composite.getPlantComponent(component.getId()));

    // Adding a duplicate component should make no difference.
    composite.addPlantComponent(component);

    // There should be one component.
    assertEquals(1, composite.getNumberOfComponents());
    assertNotNull(composite.getComponents());
    assertEquals(1, composite.getComponents().size());
    assertNotNull(composite.getPlantComponents());
    assertEquals(1, composite.getPlantComponents().size());

    // We should be able to get the same component out.
    assertSame(component, composite.getComponent(component.getId()));
    assertSame(component, composite.getPlantComponent(component.getId()));

    // Adding a different component with the same ID should not work.
    composite.addPlantComponent(new PlantComponent("stormshadow"));

    // There should be one component.
    assertEquals(1, composite.getNumberOfComponents());
    assertNotNull(composite.getComponents());
    assertEquals(1, composite.getComponents().size());
    assertNotNull(composite.getPlantComponents());
    assertEquals(1, composite.getPlantComponents().size());

    // We should be able to get the same component out.
    assertSame(component, composite.getComponent(component.getId()));
    assertSame(component, composite.getPlantComponent(component.getId()));

    // ---- removeComponent should remove a PlantComponent. ---- //
    composite.removeComponent(component.getId());

    // None of the lists should contain components.
    assertEquals(0, composite.getNumberOfComponents());
    assertNotNull(composite.getComponents());
    assertTrue(composite.getComponents().isEmpty());
    assertNotNull(composite.getPlantComponents());
    assertTrue(composite.getPlantComponents().isEmpty());

    // We should no longer be able to get the same component out.
    assertNull(composite.getComponent(component.getId()));
    assertNull(composite.getPlantComponent(component.getId()));

    return;
  }
  /**
   * Checks that registered IPlantCompositeListeners are notified correctly when PlantComponents are
   * added or removed from the PlantComposite.
   */
  @Test
  public void checkCompositeListeners() {

    // Create a PlantComposite for testing.
    PlantComposite composite = new PlantComposite();

    // Create a listener for testing the IPlantCompositeListener interface.
    TestPlantCompositeListener listener = new TestPlantCompositeListener();
    composite.registerPlantCompositeListener(listener);

    // Create a PlantComponent for adding to the composite.
    PlantComponent component = new PlantComponent("roadblock");

    // ---- addComponent should do nothing. ---- //
    composite.addComponent(component);

    // None of the lists should contain components.
    assertEquals(0, composite.getNumberOfComponents());
    assertNotNull(composite.getComponents());
    assertTrue(composite.getComponents().isEmpty());
    assertNotNull(composite.getPlantComponents());
    assertTrue(composite.getPlantComponents().isEmpty());

    // ---- addPlantComponent should add a PlantComponent. ---- //
    composite.addPlantComponent(component);

    // There should be one component.
    assertEquals(1, composite.getNumberOfComponents());
    assertNotNull(composite.getComponents());
    assertEquals(1, composite.getComponents().size());
    assertNotNull(composite.getPlantComponents());
    assertEquals(1, composite.getPlantComponents().size());

    // We should be able to get the same component out.
    assertSame(component, composite.getComponent(component.getId()));
    assertSame(component, composite.getPlantComponent(component.getId()));

    // The listener should have been notified of the added component.
    assertTrue(listener.wasNotified());
    assertSame(component, listener.getAddedComponents().get(0));
    listener.reset();

    // Adding a duplicate component should make no difference.
    composite.addPlantComponent(component);

    // There should still be one component.
    assertEquals(1, composite.getNumberOfComponents());
    assertNotNull(composite.getComponents());
    assertEquals(1, composite.getComponents().size());
    assertNotNull(composite.getPlantComponents());
    assertEquals(1, composite.getPlantComponents().size());

    // We should be able to get the same component out.
    assertSame(component, composite.getComponent(component.getId()));
    assertSame(component, composite.getPlantComponent(component.getId()));

    // The listener should not have been notified.
    assertFalse(listener.wasNotified());
    listener.reset();

    // Adding a different component with the same ID should not work.
    composite.addPlantComponent(new PlantComponent("stormshadow"));

    // There should be one component.
    assertEquals(1, composite.getNumberOfComponents());
    assertNotNull(composite.getComponents());
    assertEquals(1, composite.getComponents().size());
    assertNotNull(composite.getPlantComponents());
    assertEquals(1, composite.getPlantComponents().size());

    // We should be able to get the same component out.
    assertSame(component, composite.getComponent(component.getId()));
    assertSame(component, composite.getPlantComponent(component.getId()));

    // ---- removeComponent should remove a PlantComponent. ---- //
    composite.removeComponent(component.getId());

    // None of the lists should contain components.
    assertEquals(0, composite.getNumberOfComponents());
    assertNotNull(composite.getComponents());
    assertTrue(composite.getComponents().isEmpty());
    assertNotNull(composite.getPlantComponents());
    assertTrue(composite.getPlantComponents().isEmpty());

    // We should no longer be able to get the same component out.
    assertNull(composite.getComponent(component.getId()));
    assertNull(composite.getPlantComponent(component.getId()));

    // The listener should have been notified of the removed component.
    assertTrue(listener.wasNotified());
    assertSame(component, listener.getRemovedComponents().get(0));
    listener.reset();

    return;
  }