/**
   * Creates a new checkpoint for {@link AbstractModel#revert()} to revert to, if called, and clears
   * the dirty state (including that of added inner {@link AbstractModel}-s).
   */
  public void checkpoint() {
    provider.checkpoint();

    for (AbstractModel<?> model : models) {
      model.checkpoint();
    }
  }
  /**
   * Reverts this {@link AbstractModel} to the value it was originally provided with (via {@link
   * AbstractModel#setValue(Object)}) or the value when {@link AbstractModel#checkpoint()} was last
   * called.
   */
  public void revert() {
    provider.revert();

    // revert inner models before checkpoint()-ing, otherwise the inner
    // models will revert to the checkpoint we just made (and not their
    // "original" value, which would have been overwritten by the
    // checkpoint).
    for (AbstractModel<?> model : models) {
      model.revert();
    }

    checkpoint();
  }