Skip to content

Commit 5f5ee64

Browse files
author
Simon Tennant
committed
Merge pull request #306 from lloydwatkin/replies-from-time-past
Implement RSM <before/> for item replies retrieval Nice one!
2 parents c6a9a1d + 48e4675 commit 5f5ee64

File tree

10 files changed

+103
-22
lines changed

10 files changed

+103
-22
lines changed

src/main/java/org/buddycloud/channelserver/channel/ChannelManagerImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ public CloseableIterator<NodeItem> getNodeItems(String nodeId) throws NodeStoreE
125125

126126
@Override
127127
public ClosableIteratorImpl<NodeItem> getNodeItemReplies(String nodeId, String itemId,
128-
String afterItemId, int limit) throws NodeStoreException {
129-
return nodeStore.getNodeItemReplies(nodeId, itemId, afterItemId, limit);
128+
String afterItemId, boolean after, int limit) throws NodeStoreException {
129+
return nodeStore.getNodeItemReplies(nodeId, itemId, afterItemId, after, limit);
130130
}
131131

132132
@Override

src/main/java/org/buddycloud/channelserver/db/NodeStore.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ ResultSet<NodeMembershipWithConfiguration> getUserMembershipsWithConfiguration(J
268268
* @return
269269
* @throws NodeStoreException
270270
*/
271-
ClosableIteratorImpl<NodeItem> getNodeItemReplies(String nodeId, String itemId, String afterItemId, int limit) throws NodeStoreException;
271+
ClosableIteratorImpl<NodeItem> getNodeItemReplies(String nodeId, String itemId, String rsmItemId, boolean after, int limit) throws NodeStoreException;
272272

273273
/**
274274
* Get a count of the number of replies to an item

src/main/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStore.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,16 +1167,23 @@ public CloseableIterator<NodeItem> getNodeItems(String nodeId) throws NodeStoreE
11671167
}
11681168

11691169
@Override
1170-
public ClosableIteratorImpl<NodeItem> getNodeItemReplies(String nodeId, String itemId, String afterItemId, int limit) throws NodeStoreException {
1170+
public ClosableIteratorImpl<NodeItem> getNodeItemReplies(String nodeId, String itemId, String rsmItem, boolean after, int limit) throws NodeStoreException {
11711171
PreparedStatement stmt = null;
11721172

11731173
try {
1174-
Date since = new Date(0);
1175-
if (null != afterItemId) {
1176-
since = getNodeItem(nodeId, afterItemId).getUpdated();
1174+
Date since = new Date();
1175+
String afterReplacement = "<";
1176+
if (after) {
1177+
since = new Date(0);
1178+
afterReplacement = ">";
11771179
}
1178-
1179-
String query = dialect.selectItemReplies();
1180+
1181+
if (null != rsmItem) {
1182+
since = getNodeItem(nodeId, rsmItem).getUpdated();
1183+
}
1184+
String query = dialect.selectItemReplies()
1185+
.replace("%beforeAfter%", afterReplacement);
1186+
11801187
if (-1 != limit) {
11811188
query += " LIMIT ?";
11821189
}

src/main/java/org/buddycloud/channelserver/db/jdbc/dialect/Sql92NodeStoreDialect.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public class Sql92NodeStoreDialect implements NodeStoreSQLDialect {
133133
private static final String COUNT_ITEMS_FOR_NODE = "SELECT COUNT(*)" + " FROM \"items\" WHERE \"node\" = ? %parentOnly%;";
134134

135135
private static final String SELECT_ITEM_REPLIES = "" + "SELECT \"id\", \"node\", \"xml\", \"updated\", \"in_reply_to\", \"created\" "
136-
+ "FROM \"items\" WHERE \"node\" = ? AND \"in_reply_to\" LIKE ? " + "AND \"updated\" > ? ORDER BY \"updated\" DESC";
136+
+ "FROM \"items\" WHERE \"node\" = ? AND \"in_reply_to\" LIKE ? " + "AND \"updated\" %beforeAfter% ? ORDER BY \"updated\" DESC";
137137

138138
private static final String SELECT_ITEM_THREAD = "" + "SELECT \"id\", \"node\", \"xml\", \"updated\", \"in_reply_to\", \"created\" "
139139
+ "FROM \"items\" WHERE \"node\" = ? " + "AND (\"in_reply_to\" LIKE ? OR \"id\" = ?) " + "AND \"updated\" > ? ORDER BY \"updated\" DESC";

src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/PubSubElementProcessorAbstract.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public abstract class PubSubElementProcessorAbstract implements PubSubElementPro
4747
// RSM details
4848
protected int maxResults = -1;
4949
protected String afterItemId = null;
50+
protected String beforeItemId;
5051

5152
protected Element resultSetManagement;
5253
protected String firstItem;
@@ -267,9 +268,13 @@ protected boolean parseRsmElement() throws NodeStoreException {
267268
maxResults = Integer.parseInt(max.getTextTrim());
268269
}
269270
Element after;
271+
Element before;
270272
if (null != (after = rsmElement.element("after"))) {
271273
afterItemId = after.getTextTrim();
272274
}
275+
if (null != (before = rsmElement.element("before"))) {
276+
beforeItemId = before.getTextTrim();
277+
}
273278

274279
return true;
275280
};

src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RepliesGet.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,14 @@ protected void addRsmElement() throws NodeStoreException {
100100

101101
private void addReplies() throws NodeStoreException {
102102

103-
CloseableIterator<NodeItem> items = channelManager.getNodeItemReplies(node, parentId, afterItemId, maxResults);
103+
String rsmItem = afterItemId;
104+
boolean after = true;
105+
if (null != beforeItemId) {
106+
rsmItem = beforeItemId;
107+
after = false;
108+
}
109+
110+
CloseableIterator<NodeItem> items = channelManager.getNodeItemReplies(node, parentId, rsmItem, after, maxResults);
104111
NodeItem item;
105112
Element entry;
106113
Element itemElement;

src/main/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/ItemDelete.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ private void deleteReplies() throws NodeStoreException {
9595
if (null != nodeItem.getInReplyTo()) {
9696
return;
9797
}
98-
ClosableIteratorImpl<NodeItem> replies = channelManager.getNodeItemReplies(node, itemId.getItemID(), null, -1);
98+
ClosableIteratorImpl<NodeItem> replies = channelManager.getNodeItemReplies(node, itemId.getItemID(), null, true, -1);
9999
NodeItem reply = null;
100100
while (replies.hasNext()) {
101101
reply = replies.next();

src/test/java/org/buddycloud/channelserver/db/jdbc/JDBCNodeStoreTest.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ public void canGetItemReplies() throws Exception {
391391
store.addNodeItem(testItem);
392392

393393
ClosableIteratorImpl<NodeItem> items = store.getNodeItemReplies(
394-
TEST_SERVER1_NODE1_ID, "a5", null, -1);
394+
TEST_SERVER1_NODE1_ID, "a5", null, true, -1);
395395

396396
int count = 0;
397397
NodeItem item = null;
@@ -421,7 +421,7 @@ public void canGetItemRepliesWithResultSetManagement() throws Exception {
421421
store.addNodeItem(testItem4);
422422

423423
ClosableIteratorImpl<NodeItem> items = store.getNodeItemReplies(
424-
TEST_SERVER1_NODE1_ID, "a5", "a7", 2);
424+
TEST_SERVER1_NODE1_ID, "a5", "a7", true, 2);
425425

426426
int count = 0;
427427
ArrayList<NodeItem> itemsResult = new ArrayList<NodeItem>();
@@ -435,6 +435,41 @@ public void canGetItemRepliesWithResultSetManagement() throws Exception {
435435
assertSameNodeItem(itemsResult.get(1), testItem1);
436436
}
437437

438+
@Test
439+
public void canGetItemRepliesWithResultSetManagementPagingBackwards() throws Exception {
440+
441+
dbTester.loadData("node_1");
442+
NodeItem testItem1 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a6",
443+
new Date(), "<entry>payload</entry>", "a5", new Date());
444+
Thread.sleep(100);
445+
NodeItem testItem2 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a7",
446+
new Date(), "<entry>payload</entry>", "a5", new Date());
447+
Thread.sleep(100);
448+
NodeItem testItem3 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a8",
449+
new Date(), "<entry>payload</entry>", "a5", new Date());
450+
Thread.sleep(100);
451+
NodeItem testItem4 = new NodeItemImpl(TEST_SERVER1_NODE1_ID, "a9",
452+
new Date(), "<entry>payload</entry>", "/full-node-item-id-ref/a5", new Date());
453+
store.addNodeItem(testItem1);
454+
store.addNodeItem(testItem2);
455+
store.addNodeItem(testItem3);
456+
store.addNodeItem(testItem4);
457+
458+
ClosableIteratorImpl<NodeItem> items = store.getNodeItemReplies(
459+
TEST_SERVER1_NODE1_ID, "a5", "a8", false, 4);
460+
461+
int count = 0;
462+
ArrayList<NodeItem> itemsResult = new ArrayList<NodeItem>();
463+
while (items.hasNext()) {
464+
++count;
465+
itemsResult.add(items.next());
466+
467+
}
468+
assertEquals(2, count);
469+
assertSameNodeItem(itemsResult.get(0), testItem1);
470+
assertSameNodeItem(itemsResult.get(1), testItem2);
471+
}
472+
438473
@Test
439474
public void canGetCountOfItemReplies() throws Exception {
440475
dbTester.loadData("node_1");

src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/get/RepliesGetTest.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public void testIfItemDoesNotExistErrorStanzaIsReturned() throws Exception {
160160
@Test
161161
public void testNoRepliesReturnsEmptyStanza() throws Exception {
162162

163-
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt())).thenReturn(
163+
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.eq(true), Mockito.anyInt())).thenReturn(
164164
new ClosableIteratorImpl<NodeItem>(new ArrayList<NodeItem>().iterator()));
165165

166166
repliesGet.process(element, jid, request, null);
@@ -178,7 +178,7 @@ public void testOutgoingStanzaFormattedAsExpected() throws Exception {
178178
expectedResults.add(new NodeItemImpl(TEST_NODE, "1", new Date(), "<entry>value1</entry>"));
179179
expectedResults.add(new NodeItemImpl(TEST_NODE, "2", new Date(), "<entry>value2</entry>"));
180180

181-
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt())).thenReturn(
181+
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.eq(true), Mockito.anyInt())).thenReturn(
182182
new ClosableIteratorImpl<NodeItem>(expectedResults.iterator()));
183183

184184
repliesGet.process(element, jid, request, null);
@@ -198,7 +198,7 @@ public void testUnparsableItemEntriesAreSimplyIgnored() throws Exception {
198198
expectedResults.add(new NodeItemImpl(TEST_NODE, "1", new Date(), "<entry>value1</entry>"));
199199
expectedResults.add(new NodeItemImpl(TEST_NODE, "2", new Date(), "<entry>value2"));
200200

201-
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyInt())).thenReturn(
201+
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.eq(true), Mockito.anyInt())).thenReturn(
202202
new ClosableIteratorImpl<NodeItem>(expectedResults.iterator()));
203203

204204
repliesGet.process(element, jid, request, null);
@@ -225,7 +225,7 @@ public void testRsmElementIsAddedCorrectly() throws Exception {
225225
expectedResults.add(new NodeItemImpl(TEST_NODE, "3", new Date(), "<entry>value3</entry>"));
226226
expectedResults.add(new NodeItemImpl(TEST_NODE, "4", new Date(), "<entry>value4</entry>"));
227227

228-
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.eq("1"), Mockito.eq(4))).thenReturn(
228+
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.eq("1"), Mockito.eq(true), Mockito.eq(4))).thenReturn(
229229
new ClosableIteratorImpl<NodeItem>(expectedResults.iterator()));
230230

231231
repliesGet.process(element, jid, request, null);
@@ -241,7 +241,7 @@ public void testRsmElementIsAddedCorrectly() throws Exception {
241241
Assert.assertEquals("4", rsmResult.elementText("last"));
242242
Assert.assertEquals(String.valueOf(TOTAL_RESULTS), rsmResult.elementText("count"));
243243
}
244-
244+
245245
@Test
246246
public void rsmStillAddedWhenThereAreNoResults() throws Exception {
247247

@@ -251,7 +251,7 @@ public void rsmStillAddedWhenThereAreNoResults() throws Exception {
251251
rsm.addElement("after").setText("1");
252252

253253
ArrayList<NodeItem> expectedResults = new ArrayList<NodeItem>();
254-
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.eq("1"), Mockito.eq(4))).thenReturn(
254+
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.eq("1"), Mockito.eq(true), Mockito.eq(4))).thenReturn(
255255
new ClosableIteratorImpl<NodeItem>(expectedResults.iterator()));
256256

257257
Mockito.when(channelManager.getCountNodeItemReplies(Mockito.anyString(), Mockito.anyString())).thenReturn(0);
@@ -269,4 +269,31 @@ public void rsmStillAddedWhenThereAreNoResults() throws Exception {
269269
Assert.assertNull(rsmResult.elementText("last"));
270270
Assert.assertEquals("0", rsmResult.elementText("count"));
271271
}
272+
273+
@Test
274+
public void providingBeforeValueInRsmElementInvokesPastItemLookup() throws Exception {
275+
276+
Element rsm = request.getChildElement().addElement("set");
277+
rsm.addNamespace("", RepliesGet.NS_RSM);
278+
rsm.addElement("max").setText("4");
279+
rsm.addElement("after").setText("1");
280+
rsm.addElement("before").setText("2");
281+
282+
ArrayList<NodeItem> expectedResults = new ArrayList<NodeItem>();
283+
expectedResults.add(new NodeItemImpl(TEST_NODE, "1", new Date(), "<entry>value1</entry>"));
284+
expectedResults.add(new NodeItemImpl(TEST_NODE, "2", new Date(), "<entry>value2</entry>"));
285+
expectedResults.add(new NodeItemImpl(TEST_NODE, "3", new Date(), "<entry>value3</entry>"));
286+
expectedResults.add(new NodeItemImpl(TEST_NODE, "4", new Date(), "<entry>value4</entry>"));
287+
288+
Mockito.when(channelManager.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(), Mockito.eq("2"), Mockito.eq(false), Mockito.eq(4))).thenReturn(
289+
new ClosableIteratorImpl<NodeItem>(expectedResults.iterator()));
290+
291+
repliesGet.process(element, jid, request, null);
292+
Packet response = queue.poll();
293+
294+
Element items = response.getElement().element("pubsub").element("items");
295+
296+
Assert.assertEquals(4, items.elements("item").size());
297+
}
298+
272299
}

src/test/java/org/buddycloud/channelserver/packetprocessor/iq/namespace/pubsub/set/ItemDeleteTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ public void doesNotRequestThreadWhenDealingWithReply() throws Exception {
396396
Mockito.doThrow(Exception.class)
397397
.when(channelManager)
398398
.getNodeItemReplies(Mockito.anyString(), Mockito.anyString(),
399-
Mockito.anyString(), Mockito.anyInt());
399+
Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyInt());
400400

401401
Mockito.doReturn(new ResultSetImpl<NodeSubscription>(subscriptions))
402402
.when(channelManager).getNodeSubscriptionListeners(node);
@@ -431,7 +431,7 @@ public void requestsThreadWhenDeletingParentPost() throws Exception {
431431
Mockito.when(channelManager.getNodeItem(node, "item-id")).thenReturn(
432432
nodeItem);
433433
Mockito.when(channelManager.getNodeItemReplies(Mockito.eq(node), Mockito.eq("item-id"),
434-
Mockito.anyString(), Mockito.eq(-1))).thenReturn(new ClosableIteratorImpl<NodeItem>(replies
434+
Mockito.anyString(), Mockito.anyBoolean(), Mockito.eq(-1))).thenReturn(new ClosableIteratorImpl<NodeItem>(replies
435435
.iterator()));
436436

437437
Mockito.doReturn(new ResultSetImpl<NodeSubscription>(subscriptions))

0 commit comments

Comments
 (0)