/** * Test that a conversation can be created on a manifest that contains blips * that are not backed by the wavelet. */ public void testBlipMissingFromWavelet() { WaveletBasedConversation empty = target; WaveletBasedConversation nonEmpty = makeConversation(); nonEmpty.getRootThread().appendBlip(); WaveletBasedConversation conversation = WaveletBasedConversation.create(conversationView, empty.getWavelet(), nonEmpty.getManifest(), idGenerator); assertNull(conversation.getRootThread().getFirstBlip()); assertEquals(Collections.emptyList(), getBlipList(conversation.getRootThread())); }
/** * Builds an anchor if the wave has a specific wavelet and blip, else returns * null. */ private Anchor maybeMakeAnchor(WaveletId waveletId, String blipId) { Anchor anchor = null; if (isValidAnchor(waveletId, blipId)) { WaveletBasedConversation anchorConversation = wave.getConversation(waveletId); ConversationBlip anchorBlip = anchorConversation.getBlip(blipId); anchor = new Anchor(anchorConversation, anchorBlip); } return anchor; }
@Override protected WaveletBasedConversation mirrorConversation(ObservableConversation toMirror) { WaveletBasedConversation backer = (WaveletBasedConversation) toMirror; ObservableDocument backerManifestDoc = WaveletBasedConversation.getManifestDocument( backer.getWavelet()); ObservableManifest manifest = backerManifestDoc.with( new ObservableMutableDocument.Method<ObservableManifest>() { @Override public <N, E extends N, T extends N> ObservableManifest exec( ObservableMutableDocument<N, E, T> doc) { E top = DocHelper.expectAndGetFirstTopLevelElement(doc, DocumentBasedManifest.MANIFEST_TOP_TAG); return DocumentBasedManifest.createOnExisting(DefaultDocumentEventRouter.create(doc), top); } }); return WaveletBasedConversation.create(conversationView, backer.getWavelet(), manifest, idGenerator); }
@Override public String getId() { return idFor(getWaveletId()); }
@Override public void onValueChanged(DocumentBasedManifest oldValue, DocumentBasedManifest newValue) { if (oldValue != null) { assert conversation != null; conversations.remove(wavelet); conversation.destroy(); triggerOnConversationRemoved(conversation); conversation = null; } if (newValue != null) { assert conversation == null; conversation = WaveletBasedConversation.create(WaveBasedConversationView.this, wavelet, newValue, idGenerator); conversations.put(wavelet, conversation); triggerOnConversationAdded(conversation); } } }
@Override public long getVersion(WaveletId id) { Conversation c = view.getConversation(WaveletBasedConversation.idFor(id)); return c != null ? // TODO(user): Once bug 2820511 is fixed, get rid of the cast. ((WaveletBasedConversation) c).getWavelet().getVersion() : PrimitiveSupplement.NO_VERSION; }
public void testParticipantReadStateWithBlip() { WaveletBasedConversation c = setUpWithWaveModel(); ObservableConversationThread t = c.getRootThread(); ConversationBlip b = t.appendBlip(); supplement.markParticipantAsRead(c.getWavelet()); }
@Override public boolean isRoot() { return parentThread == getConversation().getRootThread() && this == parentThread.getFirstBlip(); }
/** * Tests that setting an anchor updates the conversation manifest correctly. */ public void testSetAnchorUpdatesManifest() { // Anchor target(wavelet1) in alternate (wavelet2). WaveletBasedConversation conversation2 = makeConversation(); populate(conversation2); ConversationBlip firstBlip = getFirstBlip(conversation2); Anchor anchor = conversation2.createAnchor(firstBlip); target.setAnchor(anchor); assertEquals(WaveletBasedConversation.idFor(conversation2.getWavelet().getId()), getManifestAttribute(manifestDoc, "anchorWavelet")); assertEquals(firstBlip.getId(), getManifestAttribute(manifestDoc, "anchorBlip")); }
@Override public void onConversationRemoved(ObservableConversation conversation) { // TODO(user): Once bug 2820511 is fixed, stop listening to the wavelet. ((WaveletBasedConversation) conversation).getWavelet().removeListener(waveletListener); } };
public void testConcurrentDeletionOfFinalThreadsLeavesEmptyBlip() { WaveletBasedConversationBlip first = target.getRootThread().appendBlip(); WaveletBasedConversationThread t1 = first.addReplyThread(); WaveletBasedConversationBlip t1b = t1.appendBlip(); WaveletBasedConversationThread t2 = first.addReplyThread(); WaveletBasedConversationBlip t2b = t2.appendBlip(); // Locally delete t1, remotely delete t2. t1b.delete(); first.addListener(blipListener); t2.addListener(threadListener); target.addListener(convListener); remoteRemoveBlip(t2b); remoteRemoveThread(t2); // Expect thread t2 deletion events and it to be invalid. verify(threadListener).onDeleted(); verify(convListener).onBlipDeleted(t2b); verify(convListener).onThreadDeleted(t2); assertBlipInvalid(t2b); assertThreadInvalid(t2); assertBlipValid(first); assertNotNull(target.getRootThread().getFirstBlip()); // The manifest now has an empty blip. assertEquals(0, first.getManifestBlip().numReplies()); // Still there after next write. WaveletBasedConversationBlip second = target.getRootThread().appendBlip(); assertBlipValid(first); verify(convListener).onBlipAdded(second); verifyNoMoreInteractions(blipListener, threadListener, convListener); }
@Override protected void setUp() throws Exception { idGenerator = FakeIdGenerator.create(); waveView = ConversationTestUtils.createWaveView(idGenerator); conversationView = WaveBasedConversationView.create(waveView, idGenerator); target = makeConversation(); manifestDoc = WaveletBasedConversation.getManifestDocument(target.getWavelet()); blipListener = mock(WaveletBasedConversationBlip.Listener.class); threadListener = mock(WaveletBasedConversationThread.Listener.class); super.setUp(); }
/** * Tests that makeWaveletConversational does so. */ public void testHackMakeWaveletConversationalMakesConversation() { Wavelet wavelet = waveView.createWavelet(); WaveletBasedConversation.makeWaveletConversational(wavelet); assertTrue(WaveletBasedConversation.waveletHasConversation(wavelet)); }
public void testGetBlipRetrievesBlip() { WaveletBasedConversationBlip blip = target.getRootThread().appendBlip(); WaveletBasedConversationThread reply = blip.addReplyThread(); WaveletBasedConversationBlip replyBlip = reply.appendBlip(); assertSame(blip, target.getBlip(blip.getId())); assertSame(replyBlip, target.getBlip(replyBlip.getId())); assertNull(target.getBlip("foobar")); }
/** * Tests that a wavelet with an initialised manifest is recognised as having * conversation structure. */ public void testWaveletWithManifestHasConversation() { assertTrue(WaveletBasedConversation.waveletHasConversation(target.getWavelet())); }
/** * Creates a new conversation model on a wavelet. * * @param wavelet wavelet with which to back the conversation * @return a conversation */ private WaveletBasedConversation createNewConversation(ObservableWavelet wavelet) { assert IdUtil.isConversationalId(wavelet.getId()); // Add conversation structure to the wavelet, then get the conversation // which may be constructed in the waiter. WaveletBasedConversation.makeWaveletConversational(wavelet); // The container will have created the conversation. assert conversations.containsKey(wavelet); return conversations.get(wavelet); }
/** * Checks whether a wavelet has conversation structure. */ public static boolean waveletHasConversation(Wavelet wavelet) { return DocumentBasedManifest.documentHasManifest(getManifestDocument(wavelet)); }
@Override public void delete() { getRootThread().deleteBlips(); DocumentBasedManifest.delete(getManifestDocument(wavelet)); Preconditions.checkState(!isUsable, "Conversation still usable after delete"); }
/** * Tests that an empty wavelet is recognised as having no conversation * structure. */ public void testNewWaveletHasNoConversation() { Wavelet wavelet = waveView.createWavelet(); assertFalse(WaveletBasedConversation.waveletHasConversation(wavelet)); }
private ObservableConversationBlip getBlip(WaveletId wid, String bid) { String conversationId = WaveletBasedConversation.idFor(wid); ObservableConversation c = conversationView.getConversation(conversationId); return c != null ? c.getBlip(bid) : null; }