/** * Builds a conversation model. * * @param view view containing this conversation * @param wavelet wavelet on which to build the conversation * @param manifest manifest describing the conversation structure * @param idGenerator generator for new identifiers * @return a new conversation model */ static WaveletBasedConversation create(WaveBasedConversationView view, ObservableWavelet wavelet, ObservableManifest manifest, IdGenerator idGenerator) { WaveletBasedConversation conversation = new WaveletBasedConversation(view, wavelet, manifest, idGenerator); wavelet.addListener(conversation.waveletListener); manifest.addListener(conversation.manifestListener); conversation.observe(conversation.rootThread); return conversation; }
private String getAnchorBlipId() { return manifest.getAnchor().getBlipId(); }
@Override public void setAnchor(Anchor newAnchor) { checkIsUsable(); if (newAnchor != null) { Preconditions.checkArgument(newAnchor.getConversation().getClass() == getClass(), "Anchor must not refer to a different conversation class"); Preconditions.checkArgument(newAnchor.getConversation() != this, "Anchor must not refer to a different anchored conversation"); WaveletBasedConversation conv = (WaveletBasedConversation) newAnchor.getConversation(); String blipId = newAnchor.getBlip().getId(); manifest.setAnchor(new AnchorData(idFor(conv.getWaveletId()), blipId)); } else { manifest.setAnchor(new AnchorData(null, null)); } }
/** * Constructs a new conversation backed by a wavelet. */ WaveletBasedConversation(WaveBasedConversationView wave, ObservableWavelet wavelet, ObservableManifest manifest, IdGenerator idGenerator) { Preconditions.checkNotNull(wavelet, "Null wavelet"); Preconditions.checkNotNull(manifest, "Null conversation manifest"); this.wave = wave; this.wavelet = wavelet; this.manifest = manifest; this.idGenerator = idGenerator; try { this.rootThread = WaveletBasedConversationThread.create(manifest.getRootThread(), null, new ComponentHelper()); } catch (RuntimeException e) { throw new IllegalArgumentException("Failed to create conversation on wavelet " + wavelet.getWaveId() + " " + wavelet.getId(), e); } }
/** * Destroys this conversation and detaches listeners. The conversation may * still be inspected but may not be mutated and will not generate any further * events. */ void destroy() { checkIsUsable(); wavelet.removeListener(waveletListener); manifest.removeListener(manifestListener); listeners.clear(); anchorListeners.clear(); rootThread.destroy(); isUsable = false; }
public void testObsoleteThreadThenRestoreRemoveBlipDoesntDie() { WaveletBasedConversationBlip first = target.getRootThread().appendBlip(); WaveletBasedConversationThread willBecomeEmpty = first.addReplyThread(); ConversationBlip toggleBlip = willBecomeEmpty.appendBlip(); String toggleBlipId = toggleBlip.getId(); // Make the thread empty by remotely removing its blip. ManifestBlip manifestRootBlip = target.getManifest().getRootThread().getBlip(0); ManifestThread manifestReply = manifestRootBlip.getReply(0); manifestReply.removeBlip(manifestReply.getBlip(0)); assertThreadValid(willBecomeEmpty); // Re-add then remove the blip, as can happen in playback. manifestReply.appendBlip(toggleBlipId); manifestReply.removeBlip(manifestReply.getBlip(0)); }
public void testObsoleteThreadThenRestoreRemoveBlipDoesntDie() { WaveletBasedConversationBlip first = target.getRootThread().appendBlip(); WaveletBasedConversationThread willBecomeEmpty = first.addReplyThread(); ConversationBlip toggleBlip = willBecomeEmpty.appendBlip(); String toggleBlipId = toggleBlip.getId(); // Make the thread empty by remotely removing its blip. ManifestBlip manifestRootBlip = target.getManifest().getRootThread().getBlip(0); ManifestThread manifestReply = manifestRootBlip.getReply(0); manifestReply.removeBlip(manifestReply.getBlip(0)); assertThreadValid(willBecomeEmpty); // Re-add then remove the blip, as can happen in playback. manifestReply.appendBlip(toggleBlipId); manifestReply.removeBlip(manifestReply.getBlip(0)); }
private WaveletId getAnchorWaveletId() { // may be null String anchorWaveletId = manifest.getAnchor().getConversationId(); return widFor(anchorWaveletId); }
public void testRemoveRestoreThreadAfterObsoleteThreadDoesntDie() { WaveletBasedConversationBlip first = target.getRootThread().appendBlip(); WaveletBasedConversationThread reply11 = first.addReplyThread(); ConversationBlip blip1 = reply11.appendBlip(); String blip1Id = blip1.getId(); WaveletBasedConversationThread reply2 = first.addReplyThread(); // Make first thread empty by removing its blip. ManifestBlip manifestRootBlip = target.getManifest().getRootThread().getBlip(0); ManifestThread manifestReply1 = manifestRootBlip.getReply(0); manifestReply1.removeBlip(manifestReply1.getBlip(0)); assertThreadValid(reply11); // Remove and re-add second thread, as can happen in playback. String thread2Id = reply2.getId(); ManifestThread manifestReply2 = manifestRootBlip.getReply(1); manifestRootBlip.removeReply(manifestReply2); manifestRootBlip.appendReply(thread2Id, false); assertThreadInvalid(reply2); }
public void testRemoveRestoreThreadAfterObsoleteThreadDoesntDie() { WaveletBasedConversationBlip first = target.getRootThread().appendBlip(); WaveletBasedConversationThread reply11 = first.addReplyThread(); ConversationBlip blip1 = reply11.appendBlip(); String blip1Id = blip1.getId(); WaveletBasedConversationThread reply2 = first.addReplyThread(); // Make first thread empty by removing its blip. ManifestBlip manifestRootBlip = target.getManifest().getRootThread().getBlip(0); ManifestThread manifestReply1 = manifestRootBlip.getReply(0); manifestReply1.removeBlip(manifestReply1.getBlip(0)); assertThreadValid(reply11); // Remove and re-add second thread, as can happen in playback. String thread2Id = reply2.getId(); ManifestThread manifestReply2 = manifestRootBlip.getReply(1); manifestRootBlip.removeReply(manifestReply2); manifestRootBlip.appendReply(thread2Id, false); assertThreadInvalid(reply2); }