/**
   * Appends the given deltas to the deltas already stored. Updates the latest snapshot and latest
   * version as well. This method will make a copy of the snapshot.
   *
   * @param updatedSnapshot the snapshot after deltas have been applied
   * @param newDeltas the deltas that have been applied since the last call to appendDeltas.
   */
  public void appendDeltas(ReadableWaveletData updatedSnapshot, DeltaSequence newDeltas) {
    HashedVersion newEndVersion = newDeltas.getEndVersion();
    Preconditions.checkArgument(
        !newDeltas.isEmpty(), "There were no new deltas passed to appendDeltas");
    Preconditions.checkArgument(
        updatedSnapshot.getVersion() == newEndVersion.getVersion(),
        String.format(
            "Version of snapshot %s doesn't match the HashedVersion %s",
            updatedSnapshot.getVersion(), newEndVersion));
    Preconditions.checkArgument(
        areContiguousToCurrentVersion(newDeltas),
        String.format(
            "Deltas are not contiguous to the current version(%s) %s",
            getVersionAfterDeltas(), deltas));
    WaveletName updatedWaveletName = WaveletDataUtil.waveletNameOf(updatedSnapshot);
    Preconditions.checkArgument(
        updatedWaveletName.equals(waveletName),
        String.format(
            "Updated wavelet doesn't have the same name as with which this class has been "
                + "instantiated. %s != %s",
            updatedWaveletName, waveletName));

    // TODO(ljvderijk): This should actually be applying the deltas, however
    // they do not contain a timestamp at this time.
    snapshotAfterDeltas = WaveletDataUtil.copyWavelet(updatedSnapshot);
    deltas = DeltaSequence.join(deltas, newDeltas);
  }
 public void testBuildWaveletFromOneDelta() throws Exception {
   WaveletData wavelet = build(delta(addParticipant(CREATOR, 1093L, HashedVersion.unsigned(1))));
   assertEquals(WAVELET_NAME, WaveletDataUtil.waveletNameOf(wavelet));
   assertEquals(CREATOR, wavelet.getCreator());
   assertEquals(1093L, wavelet.getCreationTime());
   assertEquals(1093L, wavelet.getLastModifiedTime());
   assertEquals(HashedVersion.unsigned(1), wavelet.getHashedVersion());
   assertEquals(ImmutableSet.of(), wavelet.getDocumentIds());
   assertEquals(ImmutableSet.of(CREATOR), wavelet.getParticipants());
 }
 public void testBuildWaveletFromThreeDeltas() throws Exception {
   WaveletData wavelet =
       build(
           delta(addParticipant(CREATOR, 1093L, HashedVersion.unsigned(1))),
           delta(addParticipant(JOE, 1492L, HashedVersion.unsigned(2))),
           delta(addBlip("blipid", 2010L, HashedVersion.unsigned(3))));
   assertEquals(WAVELET_NAME, WaveletDataUtil.waveletNameOf(wavelet));
   assertEquals(CREATOR, wavelet.getCreator());
   assertEquals(1093L, wavelet.getCreationTime());
   assertEquals(2010L, wavelet.getLastModifiedTime());
   assertEquals(HashedVersion.unsigned(3), wavelet.getHashedVersion());
   assertEquals(ImmutableSet.of("blipid"), wavelet.getDocumentIds());
   assertEquals(ImmutableSet.of(CREATOR, JOE), wavelet.getParticipants());
 }
  /**
   * Constructs a {@link WaveletAndDeltas} from wavelet data and a tail of the sequence of
   * transformed deltas leading to that snapshot. Takes a copy of the WaveletData so that operations
   * can happily applied to it.
   *
   * <p>The resulting version of the last delta must match the snapshot's version.
   *
   * @param snapshot the state of the wavelet after the deltas have been applied.
   * @param deltas the deltas in the order they have been applied to the wavelet.
   * @throws OperationException if the operations can not be rolled back to create a snapshot before
   *     the deltas have been applied.
   */
  public static WaveletAndDeltas create(ReadableWaveletData snapshot, DeltaSequence deltas)
      throws OperationException {
    HashedVersion endVersion =
        deltas.isEmpty() ? snapshot.getHashedVersion() : deltas.getEndVersion();
    Preconditions.checkArgument(
        snapshot.getVersion() == endVersion.getVersion(),
        String.format(
            "Version of snapshot %s doesn't match the end version %s",
            snapshot.getVersion(), endVersion));

    ObservableWaveletData preDeltaWavelet = WaveletDataUtil.copyWavelet(snapshot);
    rollback(preDeltaWavelet, deltas);
    ObservableWaveletData postDeltaWavelet = WaveletDataUtil.copyWavelet(snapshot);
    return new WaveletAndDeltas(preDeltaWavelet, postDeltaWavelet, deltas);
  }
  public void testDeltasAccesssibleByEndVersion() throws Exception {
    appendDeltas(d1, d2, d3);
    for (WaveletDeltaRecord d : Arrays.asList(d1, d2, d3)) {
      assertEquals(d.transformed, target.getTransformedDeltaByEndVersion(d.getResultingVersion()));
      assertEquals(d.applied, target.getAppliedDeltaByEndVersion(d.getResultingVersion()));
    }

    // Wrong hashes return null.
    assertNull(
        target.getTransformedDeltaByEndVersion(
            HashedVersion.unsigned(d1.getResultingVersion().getVersion())));
    assertNull(
        target.getAppliedDeltaByEndVersion(
            HashedVersion.unsigned(d1.getResultingVersion().getVersion())));
  }
  public void testDeltasAccessibleByBeginVersion() throws Exception {
    appendDeltas(d1, d2, d3);
    assertEquals(d1.transformed, target.getTransformedDelta(V0));
    assertEquals(d1.applied, target.getAppliedDelta(V0));

    assertEquals(d2.transformed, target.getTransformedDelta(d1.getResultingVersion()));
    assertEquals(d2.applied, target.getAppliedDelta(d1.getResultingVersion()));

    assertEquals(d3.transformed, target.getTransformedDelta(d2.getResultingVersion()));
    assertEquals(d3.applied, target.getAppliedDelta(d2.getResultingVersion()));

    // Wrong hashes return null.
    assertNull(target.getTransformedDelta(HashedVersion.unsigned(0)));
    assertNull(target.getAppliedDelta(HashedVersion.unsigned(0)));
  }
  public void testDeltaHistoryRequiresCorrectHash() throws Exception {
    appendDeltas(d1);

    // Wrong start hash.
    assertNull(
        target.getTransformedDeltaHistory(HashedVersion.unsigned(0), d1.getResultingVersion()));
    assertNull(target.getAppliedDeltaHistory(HashedVersion.unsigned(0), d1.getResultingVersion()));

    // Wrong end hash.
    assertNull(
        target.getTransformedDeltaHistory(
            V0, HashedVersion.unsigned(d1.getResultingVersion().getVersion())));
    assertNull(
        target.getAppliedDeltaHistory(
            V0, HashedVersion.unsigned(d1.getResultingVersion().getVersion())));
  }
 private HashedVersion getHashedVersion() {
   return HashedVersion.unsigned(3L);
 }