/* * #%L * Alfresco Repository * %% * Copyright (C) 2005 - 2016 Alfresco Software Limited * %% * This file is part of the Alfresco software. * If the software was purchased under a paid Alfresco license, the terms of * the paid license agreement will prevail. Otherwise, the software is * provided under the following open source license terms: * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * #L% */ package org.alfresco.repo.discussion; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import org.alfresco.model.ContentModel; import org.alfresco.model.ForumModel; import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingResults; import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.site.SiteModel; import org.alfresco.repo.tenant.TenantAdminService; import org.alfresco.repo.tenant.TenantContextHolder; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.discussion.DiscussionService; import org.alfresco.service.cmr.discussion.PostInfo; import org.alfresco.service.cmr.discussion.PostWithReplies; import org.alfresco.service.cmr.discussion.TopicInfo; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.cmr.site.SiteVisibility; import org.alfresco.service.cmr.tagging.TaggingService; import org.alfresco.service.namespace.QName; import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.Pair; import org.alfresco.util.PropertyMap; import org.alfresco.util.testing.category.LuceneTests; import org.alfresco.util.testing.category.RedundantTests; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.context.ApplicationContext; /** * Test cases for {@link DiscussionServiceImpl}. * * @author Nick Burch * @since 4.0 */ @Category(LuceneTests.class) @RunWith(MockitoJUnitRunner.class) public class DiscussionServiceImplTest { private static final String TEST_SITE_PREFIX = "DiscussionsSiteTest"; private static final long ONE_DAY_MS = 24*60*60*1000; private static ApplicationContext testContext; // injected services private static MutableAuthenticationService AUTHENTICATION_SERVICE; private static BehaviourFilter BEHAVIOUR_FILTER; private static DiscussionService DISCUSSION_SERVICE; private static NodeService NODE_SERVICE; private static NodeService PUBLIC_NODE_SERVICE; private static PersonService PERSON_SERVICE; private static RetryingTransactionHelper TRANSACTION_HELPER; private static PermissionService PERMISSION_SERVICE; private static SiteService SITE_SERVICE; @Mock private static TaggingService TAGGING_SERVICE; private static TenantAdminService TENANT_ADMIN_SERVICE; private static final String TENANT_DOMAIN = (DiscussionServiceImplTest.class.getSimpleName() + "Tenant").toLowerCase(); private static final String TEST_USER = DiscussionServiceImplTest.class.getSimpleName() + "_testuser@" + TENANT_DOMAIN; private static String ADMIN_USER; private static SiteInfo DISCUSSION_SITE; private static SiteInfo ALTERNATE_DISCUSSION_SITE; private static NodeRef FORUM_NODE; /** * Temporary test nodes (created during a test method) that need deletion after the test method. */ private List<NodeRef> testNodesToTidy = new ArrayList<NodeRef>(); /** * Temporary test nodes (created BeforeClass) that need deletion after this test class. */ private static List<NodeRef> CLASS_TEST_NODES_TO_TIDY = new ArrayList<NodeRef>(); @BeforeClass public static void initTestsContext() throws Exception { testContext = ApplicationContextHelper.getApplicationContext(); AUTHENTICATION_SERVICE = (MutableAuthenticationService)testContext.getBean("authenticationService"); BEHAVIOUR_FILTER = (BehaviourFilter)testContext.getBean("policyBehaviourFilter"); DISCUSSION_SERVICE = (DiscussionService)testContext.getBean("DiscussionService"); NODE_SERVICE = (NodeService)testContext.getBean("nodeService"); PUBLIC_NODE_SERVICE = (NodeService)testContext.getBean("NodeService"); PERSON_SERVICE = (PersonService)testContext.getBean("personService"); TRANSACTION_HELPER = (RetryingTransactionHelper)testContext.getBean("retryingTransactionHelper"); PERMISSION_SERVICE = (PermissionService)testContext.getBean("permissionService"); SITE_SERVICE = (SiteService)testContext.getBean("SiteService"); TENANT_ADMIN_SERVICE = testContext.getBean("tenantAdminService", TenantAdminService.class); ADMIN_USER = AuthenticationUtil.getAdminUserName() + "@" + TENANT_DOMAIN; createTenant(); // Do the setup as admin AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); TenantContextHolder.setTenantDomain(TENANT_DOMAIN); createUser(TEST_USER); // We need to create the test site as the test user so that they can contribute content to it in tests below. AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); TenantContextHolder.setTenantDomain(TENANT_DOMAIN); createTestSites(); } @Before public void before() { // Inject a mock to a real service instead of tagging service ((DiscussionServiceImpl) testContext.getBean("discussionService")).setTaggingService(TAGGING_SERVICE); when(TAGGING_SERVICE.isTagScope(Matchers.any(NodeRef.class))).thenReturn(true); } @Test public void createNewTopic() throws Exception { TopicInfo siteTopic; TopicInfo nodeTopic; // Nothing to start with PagingResults<TopicInfo> results = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, new PagingRequest(10)); assertEquals(0, results.getPage().size()); results = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, new PagingRequest(10)); assertEquals(0, results.getPage().size()); // Get with an arbitrary name gives nothing siteTopic = DISCUSSION_SERVICE.getTopic(DISCUSSION_SITE.getShortName(), "madeUp"); assertEquals(null, siteTopic); siteTopic = DISCUSSION_SERVICE.getTopic(DISCUSSION_SITE.getShortName(), "madeUp2"); assertEquals(null, siteTopic); siteTopic = DISCUSSION_SERVICE.getTopic(FORUM_NODE, "madeUp"); assertEquals(null, siteTopic); siteTopic = DISCUSSION_SERVICE.getTopic(FORUM_NODE, "madeUp2"); assertEquals(null, siteTopic); // Create a topic on the site siteTopic = DISCUSSION_SERVICE.createTopic(DISCUSSION_SITE.getShortName(), "Site Title"); // Ensure it got a noderef, and the correct site assertNotNull(siteTopic.getNodeRef()); assertNotNull(siteTopic.getSystemName()); NodeRef container = PUBLIC_NODE_SERVICE.getPrimaryParent(siteTopic.getNodeRef()).getParentRef(); NodeRef site = PUBLIC_NODE_SERVICE.getPrimaryParent(container).getParentRef(); assertEquals(DISCUSSION_SITE.getNodeRef(), site); // Check the details on the object assertEquals("Site Title", siteTopic.getTitle()); assertEquals(ADMIN_USER, siteTopic.getCreator()); assertEquals(0, siteTopic.getTags().size()); // Fetch it, and check the details siteTopic = DISCUSSION_SERVICE.getTopic(DISCUSSION_SITE.getShortName(), siteTopic.getSystemName()); assertEquals("Site Title", siteTopic.getTitle()); assertEquals(ADMIN_USER, siteTopic.getCreator()); assertEquals(0, siteTopic.getTags().size()); // Now create one with on the forum nodeTopic = DISCUSSION_SERVICE.createTopic(FORUM_NODE, "Node Title"); assertNotNull(nodeTopic.getNodeRef()); assertNotNull(nodeTopic.getSystemName()); // Check it went in the right place assertEquals(FORUM_NODE, PUBLIC_NODE_SERVICE.getPrimaryParent(nodeTopic.getNodeRef()).getParentRef()); // Check the details assertEquals("Node Title", nodeTopic.getTitle()); assertEquals(ADMIN_USER, nodeTopic.getCreator()); assertEquals(0, siteTopic.getTags().size()); // Fetch and re-check nodeTopic = DISCUSSION_SERVICE.getTopic(FORUM_NODE, nodeTopic.getSystemName()); assertEquals("Node Title", nodeTopic.getTitle()); assertEquals(ADMIN_USER, nodeTopic.getCreator()); assertEquals(0, siteTopic.getTags().size()); // Mark them as done with testNodesToTidy.add(siteTopic.getNodeRef()); testNodesToTidy.add(nodeTopic.getNodeRef()); } @Test public void createNewTopicAndPostAndReply() throws Exception { TopicInfo siteTopic; TopicInfo nodeTopic; PostInfo post; PostInfo reply1; PostInfo reply2; Pair<TopicInfo,PostInfo> objects; // Nothing to start with PagingResults<TopicInfo> results = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, new PagingRequest(10)); assertEquals(0, results.getPage().size()); results = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, new PagingRequest(10)); assertEquals(0, results.getPage().size()); // Create two topics, one node and one site based siteTopic = DISCUSSION_SERVICE.createTopic(DISCUSSION_SITE.getShortName(), "Site Title"); nodeTopic = DISCUSSION_SERVICE.createTopic(FORUM_NODE, "Node Title"); testNodesToTidy.add(siteTopic.getNodeRef()); testNodesToTidy.add(nodeTopic.getNodeRef()); // Check these actions in turn for (TopicInfo topic : new TopicInfo[] {siteTopic, nodeTopic}) { AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); TenantContextHolder.setTenantDomain(TENANT_DOMAIN); // There are no posts to start with PagingResults<PostInfo> posts = DISCUSSION_SERVICE.listPosts(topic, new PagingRequest(10)); assertEquals(0, posts.getPage().size()); // The topic has no primary post assertEquals(null, DISCUSSION_SERVICE.getPrimaryPost(topic)); // Which means no recent post assertEquals(null, DISCUSSION_SERVICE.getMostRecentPost(topic)); // Get with an arbitrary name gives nothing post = DISCUSSION_SERVICE.getPost(topic, "madeUp"); assertEquals(null, post); post = DISCUSSION_SERVICE.getPost(topic, "madeUp2"); assertEquals(null, post); // Create the first post String contents = "This Is Some Content"; post = DISCUSSION_SERVICE.createPost(topic, contents); // Ensure it got a NodeRef, a Name and the Topic assertNotNull(post.getNodeRef()); assertNotNull(post.getSystemName()); assertEquals(topic, post.getTopic()); // Ensure it shares a name with the topic assertEquals(topic.getSystemName(), post.getSystemName()); // As this is the primary post, it'll share the topic title assertEquals(topic.getTitle(), post.getTitle()); // It will have contents and a creator assertEquals(contents, post.getContents()); assertEquals(ADMIN_USER, post.getCreator()); // Fetch and check post = DISCUSSION_SERVICE.getPost(topic, post.getSystemName()); assertNotNull(post.getNodeRef()); assertNotNull(post.getSystemName()); assertEquals(topic, post.getTopic()); assertEquals(topic.getTitle(), post.getTitle()); assertEquals(contents, post.getContents()); assertEquals(ADMIN_USER, post.getCreator()); // Topic will now have a primary post assertNotNull(DISCUSSION_SERVICE.getPrimaryPost(topic)); assertEquals(post.getNodeRef(), DISCUSSION_SERVICE.getPrimaryPost(topic).getNodeRef()); // The new post will be the most recent one assertNotNull(DISCUSSION_SERVICE.getMostRecentPost(topic)); assertEquals(post.getNodeRef(), DISCUSSION_SERVICE.getMostRecentPost(topic).getNodeRef()); // Topic will now have one post listed posts = DISCUSSION_SERVICE.listPosts(topic, new PagingRequest(10)); assertEquals(1, posts.getPage().size()); // Add a reply String reply1Contents = "Reply Contents"; reply1 = DISCUSSION_SERVICE.createReply(post, reply1Contents); assertNotNull(reply1.getNodeRef()); assertNotNull(reply1.getSystemName()); assertEquals(topic, reply1.getTopic()); assertEquals(null, reply1.getTitle()); // No title by default for replies assertEquals(reply1Contents, reply1.getContents()); assertEquals(ADMIN_USER, reply1.getCreator()); // Fetch and check reply1 = DISCUSSION_SERVICE.getPost(topic, reply1.getSystemName()); assertNotNull(reply1.getNodeRef()); assertNotNull(reply1.getSystemName()); assertEquals(topic, reply1.getTopic()); assertEquals(null, reply1.getTitle()); // No title by default for replies assertEquals(reply1Contents, reply1.getContents()); assertEquals(ADMIN_USER, reply1.getCreator()); // Create another reply, as a different user AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); String reply2Contents = "2Reply 2Contents"; reply2 = DISCUSSION_SERVICE.createReply(post, reply2Contents); assertNotNull(reply2.getNodeRef()); assertNotNull(reply2.getSystemName()); assertEquals(topic, reply2.getTopic()); assertEquals(null, reply2.getTitle()); // No title by default for replies assertEquals(reply2Contents, reply2.getContents()); assertEquals(TEST_USER, reply2.getCreator()); // Fetch and check reply2 = DISCUSSION_SERVICE.getPost(topic, reply2.getSystemName()); assertNotNull(reply2.getNodeRef()); assertNotNull(reply2.getSystemName()); assertEquals(topic, reply2.getTopic()); assertEquals(null, reply2.getTitle()); // No title by default for replies assertEquals(reply2Contents, reply2.getContents()); assertEquals(TEST_USER, reply2.getCreator()); // Ensure that by noderef, we get the correct things objects = DISCUSSION_SERVICE.getForNodeRef(FORUM_NODE); assertEquals(null, objects); objects = DISCUSSION_SERVICE.getForNodeRef(topic.getNodeRef()); assertNotNull(objects); assertEquals(topic.getNodeRef(), objects.getFirst().getNodeRef()); assertEquals(null, objects.getSecond()); objects = DISCUSSION_SERVICE.getForNodeRef(post.getNodeRef()); assertNotNull(objects); assertEquals(topic.getNodeRef(), objects.getFirst().getNodeRef()); assertEquals(post.getNodeRef(), objects.getSecond().getNodeRef()); objects = DISCUSSION_SERVICE.getForNodeRef(reply1.getNodeRef()); assertNotNull(objects); assertEquals(topic.getNodeRef(), objects.getFirst().getNodeRef()); assertEquals(reply1.getNodeRef(), objects.getSecond().getNodeRef()); // The primary post will be unchanged assertNotNull(DISCUSSION_SERVICE.getPrimaryPost(topic)); assertEquals(post.getNodeRef(), DISCUSSION_SERVICE.getPrimaryPost(topic).getNodeRef()); // But the most recent will be the newest reply assertNotNull(DISCUSSION_SERVICE.getMostRecentPost(topic)); assertEquals(reply2.getNodeRef(), DISCUSSION_SERVICE.getMostRecentPost(topic).getNodeRef()); // Check the overall count now posts = DISCUSSION_SERVICE.listPosts(topic, new PagingRequest(10)); assertEquals(3, posts.getPage().size()); } } @Test public void createUpdateDeleteEntries() throws Exception { TopicInfo siteTopic; TopicInfo siteTopic2; TopicInfo nodeTopic; PostInfo post; PostInfo reply; // Run as the test user instead AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); TenantContextHolder.setTenantDomain(TENANT_DOMAIN); // Create two topics siteTopic = DISCUSSION_SERVICE.createTopic(DISCUSSION_SITE.getShortName(), "Site Title"); nodeTopic = DISCUSSION_SERVICE.createTopic(FORUM_NODE, "Node Title"); testNodesToTidy.add(siteTopic.getNodeRef()); testNodesToTidy.add(nodeTopic.getNodeRef()); // Create a second object with the same topic as siteTopic to test equals. siteTopic2 = DISCUSSION_SERVICE.getForNodeRef(siteTopic.getNodeRef()).getFirst(); // Check them assertEquals("Site Title", siteTopic.getTitle()); assertEquals(TEST_USER, siteTopic.getCreator()); assertEquals(0, siteTopic.getTags().size()); assertEquals("Node Title", nodeTopic.getTitle()); assertEquals(TEST_USER, nodeTopic.getCreator()); assertEquals(0, nodeTopic.getTags().size()); // Check that the overridden equals is correct. assertEquals(siteTopic, siteTopic2); // Ensure they are not pointing to the same object. assertNotSame(siteTopic, siteTopic2); // Change them siteTopic.setTitle("Site Changed"); nodeTopic.setTitle("Node Changed"); siteTopic = DISCUSSION_SERVICE.updateTopic(siteTopic); nodeTopic = DISCUSSION_SERVICE.updateTopic(nodeTopic); // Fetch, and check siteTopic = DISCUSSION_SERVICE.getTopic(DISCUSSION_SITE.getShortName(), siteTopic.getSystemName()); nodeTopic = DISCUSSION_SERVICE.getTopic(FORUM_NODE, nodeTopic.getSystemName()); assertEquals("Site Changed", siteTopic.getTitle()); assertEquals(TEST_USER, siteTopic.getCreator()); assertEquals(0, siteTopic.getTags().size()); assertEquals("Node Changed", nodeTopic.getTitle()); assertEquals(TEST_USER, nodeTopic.getCreator()); assertEquals(0, nodeTopic.getTags().size()); // For each, create and edit some posts for (TopicInfo topic : new TopicInfo[] {siteTopic, nodeTopic}) { // Create a post and a reply String contents = "This Is Some Content"; post = DISCUSSION_SERVICE.createPost(topic, contents); String replyContents = "Reply Contents"; reply = DISCUSSION_SERVICE.createReply(post, replyContents); // Check them assertEquals(topic.getTitle(), post.getTitle()); assertEquals(contents, post.getContents()); assertEquals(null, post.getUpdatedAt()); assertEquals(null, reply.getTitle()); assertEquals(replyContents, reply.getContents()); assertEquals(null, reply.getUpdatedAt()); // Fetch and re-check post = DISCUSSION_SERVICE.getPost(topic, post.getSystemName()); reply = DISCUSSION_SERVICE.getPost(topic, reply.getSystemName()); assertEquals(topic.getTitle(), post.getTitle()); assertEquals(contents, post.getContents()); assertEquals(null, post.getUpdatedAt()); assertEquals(null, reply.getTitle()); assertEquals(replyContents, reply.getContents()); assertEquals(null, reply.getUpdatedAt()); // Edit them String pTitle = "Title on the Post"; String rTitle = "Title on the Reply"; String pContents = "Changed! Changed!"; String rContents = "Reply was changed..."; post.setTitle(pTitle); post.setContents(pContents); reply.setTitle(rTitle); reply.setContents(rContents); post = DISCUSSION_SERVICE.updatePost(post); reply = DISCUSSION_SERVICE.updatePost(reply); assertEquals(pTitle, post.getTitle()); assertEquals(pContents, post.getContents()); assertEquals(rTitle, reply.getTitle()); assertEquals(rContents, reply.getContents()); // Check that the modified and updated dates were set assertNotNull(post.getUpdatedAt()); assertNotNull(post.getModifiedAt()); assertNotNull(reply.getUpdatedAt()); assertNotNull(reply.getModifiedAt()); // Check the changes were taken post = DISCUSSION_SERVICE.getPost(topic, post.getSystemName()); reply = DISCUSSION_SERVICE.getPost(topic, reply.getSystemName()); assertEquals(pTitle, post.getTitle()); assertEquals(pContents, post.getContents()); assertEquals(rTitle, reply.getTitle()); assertEquals(rContents, reply.getContents()); // Check that the modified and updated dates were set assertNotNull(post.getUpdatedAt()); assertNotNull(post.getModifiedAt()); assertNotNull(reply.getUpdatedAt()); assertNotNull(reply.getModifiedAt()); // Remove the title from the topic manually String oldTitle = topic.getTitle(); PUBLIC_NODE_SERVICE.setProperty(topic.getNodeRef(), ContentModel.PROP_TITLE, null); // Check that we pick it up from the primary post instead // (That's the pre-swift Share fallback case) assertEquals(oldTitle, topic.getTitle()); topic = DISCUSSION_SERVICE.getTopic(topic.getContainerNodeRef(), topic.getSystemName()); assertEquals(pTitle, topic.getTitle()); // Delete the reply and the post DISCUSSION_SERVICE.deletePost(reply); DISCUSSION_SERVICE.deletePost(post); // Check they went post = DISCUSSION_SERVICE.getPost(topic, post.getSystemName()); reply = DISCUSSION_SERVICE.getPost(topic, reply.getSystemName()); assertEquals(null, post); assertEquals(null, reply); } // Delete the topics DISCUSSION_SERVICE.deleteTopic(siteTopic); DISCUSSION_SERVICE.deleteTopic(nodeTopic); // Check they went siteTopic = DISCUSSION_SERVICE.getTopic(DISCUSSION_SITE.getShortName(), siteTopic.getSystemName()); nodeTopic = DISCUSSION_SERVICE.getTopic(FORUM_NODE, nodeTopic.getSystemName()); assertEquals(null, siteTopic); assertEquals(null, nodeTopic); } /** * Tests listing of topics in a site/node, and posts in a topic */ @Test public void basicListings() throws Exception { PagingResults<TopicInfo> topics; PagingResults<PostInfo> posts; final String TAG_1 = "topic_tag_one"; final String TAG_2 = "topic_tag_two"; // To start with, there will be no topics topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, new PagingRequest(10)); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, new PagingRequest(10)); assertEquals(0, topics.getPage().size()); // Create several, some as Admin and some as the Test User TopicInfo siteT1 = DISCUSSION_SERVICE.createTopic(DISCUSSION_SITE.getShortName(), "ST1"); AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); TenantContextHolder.setTenantDomain(TENANT_DOMAIN); TopicInfo siteT2 = DISCUSSION_SERVICE.createTopic(DISCUSSION_SITE.getShortName(), "ST2"); TopicInfo nodeT1 = DISCUSSION_SERVICE.createTopic(FORUM_NODE, "NT1"); AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); TopicInfo nodeT2 = DISCUSSION_SERVICE.createTopic(FORUM_NODE, "NT2"); TopicInfo nodeT3 = DISCUSSION_SERVICE.createTopic(FORUM_NODE, "NT3"); testNodesToTidy.add(siteT1.getNodeRef()); testNodesToTidy.add(siteT2.getNodeRef()); testNodesToTidy.add(nodeT1.getNodeRef()); testNodesToTidy.add(nodeT2.getNodeRef()); testNodesToTidy.add(nodeT3.getNodeRef()); // Check now, will order by creation date topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, new PagingRequest(10)); assertEquals(2, topics.getPage().size()); assertEquals("ST1", topics.getPage().get(0).getTitle()); assertEquals("ST2", topics.getPage().get(1).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, new PagingRequest(10)); assertEquals(3, topics.getPage().size()); assertEquals("NT1", topics.getPage().get(0).getTitle()); assertEquals("NT2", topics.getPage().get(1).getTitle()); assertEquals("NT3", topics.getPage().get(2).getTitle()); // And requested newest ones first too topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), false, new PagingRequest(10)); assertEquals(2, topics.getPage().size()); assertEquals("ST2", topics.getPage().get(0).getTitle()); assertEquals("ST1", topics.getPage().get(1).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, false, new PagingRequest(10)); assertEquals(3, topics.getPage().size()); assertEquals("NT3", topics.getPage().get(0).getTitle()); assertEquals("NT2", topics.getPage().get(1).getTitle()); assertEquals("NT1", topics.getPage().get(2).getTitle()); // Check by user topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), ADMIN_USER, true, new PagingRequest(10)); assertEquals(1, topics.getPage().size()); assertEquals("ST1", topics.getPage().get(0).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, ADMIN_USER, true, new PagingRequest(10)); assertEquals(2, topics.getPage().size()); assertEquals("NT2", topics.getPage().get(0).getTitle()); assertEquals("NT3", topics.getPage().get(1).getTitle()); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), TEST_USER, true, new PagingRequest(10)); assertEquals(1, topics.getPage().size()); assertEquals("ST2", topics.getPage().get(0).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, TEST_USER, true, new PagingRequest(10)); assertEquals(1, topics.getPage().size()); assertEquals("NT1", topics.getPage().get(0).getTitle()); // Check by user, newest first topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), ADMIN_USER, false, new PagingRequest(10)); assertEquals(1, topics.getPage().size()); assertEquals("ST1", topics.getPage().get(0).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, ADMIN_USER, false, new PagingRequest(10)); assertEquals(2, topics.getPage().size()); assertEquals("NT3", topics.getPage().get(0).getTitle()); assertEquals("NT2", topics.getPage().get(1).getTitle()); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), TEST_USER, false, new PagingRequest(10)); assertEquals(1, topics.getPage().size()); assertEquals("ST2", topics.getPage().get(0).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, TEST_USER, false, new PagingRequest(10)); assertEquals(1, topics.getPage().size()); assertEquals("NT1", topics.getPage().get(0).getTitle()); // Check by created date, everything was just created Date now = new Date(); Date yesterday = new Date(now.getTime()-ONE_DAY_MS-60000); Date tomorrow = new Date(now.getTime()+ONE_DAY_MS); Date future = new Date(now.getTime()+10*ONE_DAY_MS); Date fourDaysAgo = new Date(now.getTime()-4*ONE_DAY_MS); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), yesterday, tomorrow, true, new PagingRequest(10)); assertEquals(2, topics.getPage().size()); assertEquals("ST1", topics.getPage().get(0).getTitle()); assertEquals("ST2", topics.getPage().get(1).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, yesterday, tomorrow, true, new PagingRequest(10)); assertEquals(3, topics.getPage().size()); assertEquals("NT1", topics.getPage().get(0).getTitle()); assertEquals("NT2", topics.getPage().get(1).getTitle()); assertEquals("NT3", topics.getPage().get(2).getTitle()); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, yesterday, true, new PagingRequest(10)); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, fourDaysAgo, yesterday, true, new PagingRequest(10)); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), tomorrow, future, true, new PagingRequest(10)); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, tomorrow, future, true, new PagingRequest(10)); assertEquals(0, topics.getPage().size()); // Now check by created date, newest first topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), yesterday, tomorrow, false, new PagingRequest(10)); assertEquals(2, topics.getPage().size()); assertEquals("ST2", topics.getPage().get(0).getTitle()); assertEquals("ST1", topics.getPage().get(1).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, yesterday, tomorrow, false, new PagingRequest(10)); assertEquals(3, topics.getPage().size()); assertEquals("NT3", topics.getPage().get(0).getTitle()); assertEquals("NT2", topics.getPage().get(1).getTitle()); assertEquals("NT1", topics.getPage().get(2).getTitle()); // Add tags to a few siteT2.getTags().add(TAG_1); nodeT2.getTags().add(TAG_1); nodeT2.getTags().add(TAG_2); nodeT3.getTags().add(TAG_1); DISCUSSION_SERVICE.updateTopic(siteT2); DISCUSSION_SERVICE.updateTopic(nodeT2); DISCUSSION_SERVICE.updateTopic(nodeT3); // @Category(RedundantTests.class) // // Find without tags // topics = DISCUSSION_SERVICE.findTopics(DISCUSSION_SITE.getShortName(), null, null, true, new PagingRequest(10)); // assertEquals(2, topics.getPage().size()); // assertEquals("ST1", topics.getPage().get(0).getTitle()); // assertEquals("ST2", topics.getPage().get(1).getTitle()); // // topics = DISCUSSION_SERVICE.findTopics(FORUM_NODE, null, null, true, new PagingRequest(10)); // assertEquals(3, topics.getPage().size()); // assertEquals("NT1", topics.getPage().get(0).getTitle()); // assertEquals("NT2", topics.getPage().get(1).getTitle()); // assertEquals("NT3", topics.getPage().get(2).getTitle()); // // // // Find with tags // topics = DISCUSSION_SERVICE.findTopics(DISCUSSION_SITE.getShortName(), null, TAG_1, true, new PagingRequest(10)); // assertEquals(1, topics.getPage().size()); // assertEquals("ST2", topics.getPage().get(0).getTitle()); // // topics = DISCUSSION_SERVICE.findTopics(FORUM_NODE, null, TAG_1, true, new PagingRequest(10)); // assertEquals(2, topics.getPage().size()); // assertEquals("NT2", topics.getPage().get(0).getTitle()); // assertEquals("NT3", topics.getPage().get(1).getTitle()); // // topics = DISCUSSION_SERVICE.findTopics(DISCUSSION_SITE.getShortName(), null, TAG_2, true, new PagingRequest(10)); // assertEquals(0, topics.getPage().size()); // // topics = DISCUSSION_SERVICE.findTopics(FORUM_NODE, null, TAG_2, true, new PagingRequest(10)); // assertEquals(1, topics.getPage().size()); // assertEquals("NT2", topics.getPage().get(0).getTitle()); // // // // Find by user but not by tag // topics = DISCUSSION_SERVICE.findTopics(DISCUSSION_SITE.getShortName(), ADMIN_USER, null, true, new PagingRequest(10)); // assertEquals(1, topics.getPage().size()); // assertEquals("ST1", topics.getPage().get(0).getTitle()); // // topics = DISCUSSION_SERVICE.findTopics(FORUM_NODE, ADMIN_USER, null, true, new PagingRequest(10)); // assertEquals(2, topics.getPage().size()); // assertEquals("NT2", topics.getPage().get(0).getTitle()); // assertEquals("NT3", topics.getPage().get(1).getTitle()); // // topics = DISCUSSION_SERVICE.findTopics(DISCUSSION_SITE.getShortName(), TEST_USER, null, true, new PagingRequest(10)); // assertEquals(1, topics.getPage().size()); // assertEquals("ST2", topics.getPage().get(0).getTitle()); // // topics = DISCUSSION_SERVICE.findTopics(FORUM_NODE, TEST_USER, null, true, new PagingRequest(10)); // assertEquals(1, topics.getPage().size()); // assertEquals("NT1", topics.getPage().get(0).getTitle()); // // // // Find by user and tag together // topics = DISCUSSION_SERVICE.findTopics(DISCUSSION_SITE.getShortName(), ADMIN_USER, TAG_1, true, new PagingRequest(10)); // assertEquals(0, topics.getPage().size()); // // topics = DISCUSSION_SERVICE.findTopics(DISCUSSION_SITE.getShortName(), TEST_USER, TAG_1, true, new PagingRequest(10)); // assertEquals(1, topics.getPage().size()); // assertEquals("ST2", topics.getPage().get(0).getTitle()); // // topics = DISCUSSION_SERVICE.findTopics(FORUM_NODE, ADMIN_USER, TAG_2, true, new PagingRequest(10)); // assertEquals(1, topics.getPage().size()); // assertEquals("NT2", topics.getPage().get(0).getTitle()); // // topics = DISCUSSION_SERVICE.findTopics(FORUM_NODE, TEST_USER, TAG_2, true, new PagingRequest(10)); // assertEquals(0, topics.getPage().size()); // // // // Do a find to check the ordering alters as requested // topics = DISCUSSION_SERVICE.findTopics(FORUM_NODE, ADMIN_USER, null, true, new PagingRequest(10)); // assertEquals(2, topics.getPage().size()); // assertEquals("NT2", topics.getPage().get(0).getTitle()); // assertEquals("NT3", topics.getPage().get(1).getTitle()); // // topics = DISCUSSION_SERVICE.findTopics(FORUM_NODE, ADMIN_USER, null, false, new PagingRequest(10)); // assertEquals(2, topics.getPage().size()); // assertEquals("NT3", topics.getPage().get(0).getTitle()); // assertEquals("NT2", topics.getPage().get(1).getTitle()); // Alter the creation date on a couple, see the ordering change pushAuditableDatesBack(siteT2, 2, 2); pushAuditableDatesBack(nodeT3, 3, 3); pushAuditableDatesBack(nodeT1, 1, 1); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, new PagingRequest(10)); assertEquals(2, topics.getPage().size()); assertEquals("ST2", topics.getPage().get(0).getTitle()); assertEquals("ST1", topics.getPage().get(1).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, new PagingRequest(10)); assertEquals(3, topics.getPage().size()); assertEquals("NT3", topics.getPage().get(0).getTitle()); assertEquals("NT1", topics.getPage().get(1).getTitle()); assertEquals("NT2", topics.getPage().get(2).getTitle()); // Try listing by date range // Only Site1 and Node2 are still created today, Node1 was a day ago topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), yesterday, tomorrow, true, new PagingRequest(10)); assertEquals(1, topics.getPage().size()); assertEquals("ST1", topics.getPage().get(0).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, yesterday, tomorrow, true, new PagingRequest(10)); assertEquals(2, topics.getPage().size()); assertEquals("NT1", topics.getPage().get(0).getTitle()); assertEquals("NT2", topics.getPage().get(1).getTitle()); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, yesterday, true, new PagingRequest(10)); assertEquals(1, topics.getPage().size()); assertEquals("ST2", topics.getPage().get(0).getTitle()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, fourDaysAgo, yesterday, true, new PagingRequest(10)); assertEquals(1, topics.getPage().size()); assertEquals("NT3", topics.getPage().get(0).getTitle()); // Now create a couple of check posts PostInfo siteCP1 = DISCUSSION_SERVICE.createPost(siteT2, "Check"); PostInfo nodeCP1 = DISCUSSION_SERVICE.createPost(nodeT2, "Check"); testNodesToTidy.add(siteCP1.getNodeRef()); testNodesToTidy.add(nodeCP1.getNodeRef()); // For both site and node based topics, check adding and // removing posts correctly affects counts for (TopicInfo topic : new TopicInfo[] {siteT1, nodeT1}) { // None to start with posts = DISCUSSION_SERVICE.listPosts(topic, new PagingRequest(10)); assertEquals(0, posts.getPage().size()); // Create one post PostInfo post = DISCUSSION_SERVICE.createPost(topic, "Post"); assertEquals(post.getNodeRef(), DISCUSSION_SERVICE.getPrimaryPost(topic).getNodeRef()); // Check the count posts = DISCUSSION_SERVICE.listPosts(topic, new PagingRequest(10)); assertEquals(1, posts.getPage().size()); assertEquals("Post", posts.getPage().get(0).getContents()); // Add two replies PostInfo reply1 = DISCUSSION_SERVICE.createReply(post, "R1"); PostInfo reply2 = DISCUSSION_SERVICE.createReply(post, "R2"); // Check posts = DISCUSSION_SERVICE.listPosts(topic, new PagingRequest(10)); assertEquals(3, posts.getPage().size()); assertEquals("Post", posts.getPage().get(0).getContents()); assertEquals("R1", posts.getPage().get(1).getContents()); assertEquals("R2", posts.getPage().get(2).getContents()); // Alter the date of one, order changes pushAuditableDatesBack(reply1, -1, -1); posts = DISCUSSION_SERVICE.listPosts(topic, new PagingRequest(10)); assertEquals(3, posts.getPage().size()); assertEquals("Post", posts.getPage().get(0).getContents()); assertEquals("R2", posts.getPage().get(1).getContents()); assertEquals("R1", posts.getPage().get(2).getContents()); // Delete one reply DISCUSSION_SERVICE.deletePost(reply1); posts = DISCUSSION_SERVICE.listPosts(topic, new PagingRequest(10)); assertEquals(2, posts.getPage().size()); assertEquals("Post", posts.getPage().get(0).getContents()); assertEquals("R2", posts.getPage().get(1).getContents()); // Delete the main post DISCUSSION_SERVICE.deletePost(post); posts = DISCUSSION_SERVICE.listPosts(topic, new PagingRequest(10)); assertEquals(1, posts.getPage().size()); assertEquals("R2", posts.getPage().get(0).getContents()); // Check the last reply now counts as the "primary" assertEquals(reply2.getNodeRef(), DISCUSSION_SERVICE.getPrimaryPost(topic).getNodeRef()); // Zap the last one DISCUSSION_SERVICE.deletePost(reply2); posts = DISCUSSION_SERVICE.listPosts(topic, new PagingRequest(10)); assertEquals(0, posts.getPage().size()); } } /** * Ensures that the listing / nesting of replies is correct */ @Test public void replyListing() throws Exception { // Create two sites and test TopicInfo siteT1 = DISCUSSION_SERVICE.createTopic(DISCUSSION_SITE.getShortName(), "ST1"); TopicInfo nodeT1 = DISCUSSION_SERVICE.createTopic(FORUM_NODE, "NT1"); testNodesToTidy.add(siteT1.getNodeRef()); testNodesToTidy.add(nodeT1.getNodeRef()); for (TopicInfo topic : new TopicInfo[] {siteT1, nodeT1}) { // Listing initially gives nothing PostWithReplies pr = DISCUSSION_SERVICE.listPostReplies(topic, 1); assertEquals(null, pr); // Add the first post PostInfo post = DISCUSSION_SERVICE.createPost(topic, "Post"); testNodesToTidy.add(post.getNodeRef()); // Should come back with no replies pr = DISCUSSION_SERVICE.listPostReplies(topic, 1); assertNotNull(pr); assertEquals(post.getNodeRef(), pr.getNodeRef()); assertEquals(0, pr.getReplies().size()); // Add two replies PostInfo reply1 = DISCUSSION_SERVICE.createReply(post, "R1"); PostInfo reply2 = DISCUSSION_SERVICE.createReply(post, "R2"); testNodesToTidy.add(reply1.getNodeRef()); testNodesToTidy.add(reply2.getNodeRef()); // Ask for the replies to the post pr = DISCUSSION_SERVICE.listPostReplies(topic, 1); assertNotNull(pr); assertEquals(post.getNodeRef(), pr.getNodeRef()); assertEquals(2, pr.getReplies().size()); assertEquals(reply1.getNodeRef(), pr.getReplies().get(0).getNodeRef()); assertEquals(reply2.getNodeRef(), pr.getReplies().get(1).getNodeRef()); assertEquals(0, pr.getReplies().get(0).getReplies().size()); assertEquals(0, pr.getReplies().get(1).getReplies().size()); // Check at other levels too: // Level 0 will mean no replies were fetched pr = DISCUSSION_SERVICE.listPostReplies(topic, 0); assertNotNull(pr); assertEquals(post.getNodeRef(), pr.getNodeRef()); assertEquals(0, pr.getReplies().size()); // Level 5 won't affect things, as there are only 2 pr = DISCUSSION_SERVICE.listPostReplies(topic, 5); assertNotNull(pr); assertEquals(post.getNodeRef(), pr.getNodeRef()); assertEquals(2, pr.getReplies().size()); assertEquals(reply1.getNodeRef(), pr.getReplies().get(0).getNodeRef()); assertEquals(reply2.getNodeRef(), pr.getReplies().get(1).getNodeRef()); assertEquals(0, pr.getReplies().get(0).getReplies().size()); assertEquals(0, pr.getReplies().get(1).getReplies().size()); // Add a nesting of replies on only one PostInfo reply1_1 = DISCUSSION_SERVICE.createReply(reply1, "R1_1"); PostInfo reply1_2 = DISCUSSION_SERVICE.createReply(reply1, "R1_2"); PostInfo reply1_3 = DISCUSSION_SERVICE.createReply(reply1, "R1_3"); PostInfo reply1_2_1 = DISCUSSION_SERVICE.createReply(reply1_2, "R1_2_1"); PostInfo reply1_2_2 = DISCUSSION_SERVICE.createReply(reply1_2, "R1_2_2"); PostInfo reply1_3_1 = DISCUSSION_SERVICE.createReply(reply1_3, "R1_3_1"); PostInfo reply1_3_1_1 = DISCUSSION_SERVICE.createReply(reply1_3_1, "R1_3_1_1"); PostInfo reply1_3_1_1_1 = DISCUSSION_SERVICE.createReply(reply1_3_1_1, "R1_3_1_1_1"); // Mark them for tidy testNodesToTidy.add(reply1_1.getNodeRef()); testNodesToTidy.add(reply1_2.getNodeRef()); testNodesToTidy.add(reply1_3.getNodeRef()); testNodesToTidy.add(reply1_2_1.getNodeRef()); testNodesToTidy.add(reply1_2_2.getNodeRef()); testNodesToTidy.add(reply1_3_1.getNodeRef()); testNodesToTidy.add(reply1_3_1_1.getNodeRef()); testNodesToTidy.add(reply1_3_1_1_1.getNodeRef()); // Check with various levels: // Level 0 will get the primary post but no replies pr = DISCUSSION_SERVICE.listPostReplies(topic, 0); assertNotNull(pr); assertEquals(post.getNodeRef(), pr.getNodeRef()); assertEquals(0, pr.getReplies().size()); // Level 1 will get the post, it's replies, but nothing further pr = DISCUSSION_SERVICE.listPostReplies(topic, 1); assertNotNull(pr); assertEquals(post.getNodeRef(), pr.getNodeRef()); assertEquals(2, pr.getReplies().size()); assertEquals(reply1.getNodeRef(), pr.getReplies().get(0).getNodeRef()); assertEquals(reply2.getNodeRef(), pr.getReplies().get(1).getNodeRef()); assertEquals(0, pr.getReplies().get(0).getReplies().size()); assertEquals(0, pr.getReplies().get(1).getReplies().size()); // Level 1 on the primary post is the same pr = DISCUSSION_SERVICE.listPostReplies(post, 1); assertNotNull(pr); assertEquals(post.getNodeRef(), pr.getNodeRef()); assertEquals(2, pr.getReplies().size()); assertEquals(reply1.getNodeRef(), pr.getReplies().get(0).getNodeRef()); assertEquals(reply2.getNodeRef(), pr.getReplies().get(1).getNodeRef()); assertEquals(0, pr.getReplies().get(0).getReplies().size()); assertEquals(0, pr.getReplies().get(1).getReplies().size()); // Level 2 gets the next bit // Reply 1 has 3 children, Reply 2 has none pr = DISCUSSION_SERVICE.listPostReplies(topic, 2); assertNotNull(pr); assertEquals(post.getNodeRef(), pr.getNodeRef()); assertEquals(2, pr.getReplies().size()); assertEquals(reply1.getNodeRef(), pr.getReplies().get(0).getNodeRef()); assertEquals(reply2.getNodeRef(), pr.getReplies().get(1).getNodeRef()); assertEquals(3, pr.getReplies().get(0).getReplies().size()); assertEquals(0, pr.getReplies().get(1).getReplies().size()); assertEquals(reply1_1.getNodeRef(), pr.getReplies().get(0).getReplies().get(0).getNodeRef()); assertEquals(reply1_2.getNodeRef(), pr.getReplies().get(0).getReplies().get(1).getNodeRef()); assertEquals(reply1_3.getNodeRef(), pr.getReplies().get(0).getReplies().get(2).getNodeRef()); assertEquals(0, pr.getReplies().get(0).getReplies().get(0).getReplies().size()); assertEquals(0, pr.getReplies().get(0).getReplies().get(1).getReplies().size()); assertEquals(0, pr.getReplies().get(0).getReplies().get(2).getReplies().size()); // Level 3 nests further // Reply 1 has 3 children, 1 has 0, 2 has 2, 3 has 1 but nested pr = DISCUSSION_SERVICE.listPostReplies(topic, 3); assertNotNull(pr); assertEquals(post.getNodeRef(), pr.getNodeRef()); assertEquals(2, pr.getReplies().size()); assertEquals(reply1.getNodeRef(), pr.getReplies().get(0).getNodeRef()); assertEquals(reply2.getNodeRef(), pr.getReplies().get(1).getNodeRef()); assertEquals(3, pr.getReplies().get(0).getReplies().size()); assertEquals(0, pr.getReplies().get(1).getReplies().size()); PostWithReplies pr1 = pr.getReplies().get(0); assertEquals(reply1_1.getNodeRef(), pr1.getReplies().get(0).getNodeRef()); assertEquals(reply1_2.getNodeRef(), pr1.getReplies().get(1).getNodeRef()); assertEquals(reply1_3.getNodeRef(), pr1.getReplies().get(2).getNodeRef()); assertEquals(0, pr1.getReplies().get(0).getReplies().size()); assertEquals(2, pr1.getReplies().get(1).getReplies().size()); assertEquals(1, pr1.getReplies().get(2).getReplies().size()); assertEquals(reply1_2_1.getNodeRef(), pr1.getReplies().get(1).getReplies().get(0).getNodeRef()); assertEquals(reply1_2_2.getNodeRef(), pr1.getReplies().get(1).getReplies().get(1).getNodeRef()); assertEquals(reply1_3_1.getNodeRef(), pr1.getReplies().get(2).getReplies().get(0).getNodeRef()); assertEquals(0, pr1.getReplies().get(1).getReplies().get(0).getReplies().size()); assertEquals(0, pr1.getReplies().get(2).getReplies().get(0).getReplies().size()); // Level 10 gets everything it can (there aren't 10 levels though) pr = DISCUSSION_SERVICE.listPostReplies(topic, 10); assertNotNull(pr); assertEquals(post.getNodeRef(), pr.getNodeRef()); assertEquals(2, pr.getReplies().size()); assertEquals(reply1.getNodeRef(), pr.getReplies().get(0).getNodeRef()); assertEquals(reply2.getNodeRef(), pr.getReplies().get(1).getNodeRef()); assertEquals(3, pr.getReplies().get(0).getReplies().size()); assertEquals(0, pr.getReplies().get(1).getReplies().size()); pr1 = pr.getReplies().get(0); assertEquals(reply1_1.getNodeRef(), pr1.getReplies().get(0).getNodeRef()); assertEquals(reply1_2.getNodeRef(), pr1.getReplies().get(1).getNodeRef()); assertEquals(reply1_3.getNodeRef(), pr1.getReplies().get(2).getNodeRef()); assertEquals(0, pr1.getReplies().get(0).getReplies().size()); assertEquals(2, pr1.getReplies().get(1).getReplies().size()); assertEquals(1, pr1.getReplies().get(2).getReplies().size()); assertEquals(reply1_2_1.getNodeRef(), pr1.getReplies().get(1).getReplies().get(0).getNodeRef()); assertEquals(reply1_2_2.getNodeRef(), pr1.getReplies().get(1).getReplies().get(1).getNodeRef()); assertEquals(reply1_3_1.getNodeRef(), pr1.getReplies().get(2).getReplies().get(0).getNodeRef()); assertEquals(0, pr1.getReplies().get(1).getReplies().get(0).getReplies().size()); assertEquals(1, pr1.getReplies().get(2).getReplies().get(0).getReplies().size()); PostWithReplies rp1_3_1 = pr1.getReplies().get(2).getReplies().get(0); assertEquals(reply1_3_1.getNodeRef(), rp1_3_1.getNodeRef()); assertEquals(1, rp1_3_1.getReplies().size()); assertEquals(reply1_3_1_1.getNodeRef(), rp1_3_1.getReplies().get(0).getNodeRef()); assertEquals(1, rp1_3_1.getReplies().get(0).getReplies().size()); assertEquals(reply1_3_1_1_1.getNodeRef(), rp1_3_1.getReplies().get(0).getReplies().get(0).getNodeRef()); assertEquals(0, rp1_3_1.getReplies().get(0).getReplies().get(0).getReplies().size()); // Now check for nodes part way down pr = DISCUSSION_SERVICE.listPostReplies(reply2, 10); assertNotNull(pr); assertEquals(reply2.getNodeRef(), pr.getNodeRef()); assertEquals(0, pr.getReplies().size()); pr = DISCUSSION_SERVICE.listPostReplies(reply1_3_1, 10); assertNotNull(pr); assertEquals(reply1_3_1.getNodeRef(), pr.getNodeRef()); assertEquals(1, pr.getReplies().size()); assertEquals(reply1_3_1_1.getNodeRef(), pr.getReplies().get(0).getNodeRef()); assertEquals(1, pr.getReplies().get(0).getReplies().size()); assertEquals(reply1_3_1_1_1.getNodeRef(), pr.getReplies().get(0).getReplies().get(0).getNodeRef()); assertEquals(0, pr.getReplies().get(0).getReplies().get(0).getReplies().size()); } } /** * Ensures that when we try to write an entry to the * container of a new site, it is correctly setup for us. * This test does it's own transactions */ @Test public void newContainerSetup() throws Exception { final String TEST_SITE_NAME = "DiscussionsTestNewTestSite"; TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { if (SITE_SERVICE.getSite(TEST_SITE_NAME) != null) { SITE_SERVICE.deleteSite(TEST_SITE_NAME); } SITE_SERVICE.createSite( TEST_SITE_PREFIX, TEST_SITE_NAME, "Test", "Test", SiteVisibility.PUBLIC); // Won't have the container to start with assertFalse(SITE_SERVICE.hasContainer(TEST_SITE_NAME, DiscussionServiceImpl.DISCUSSION_COMPONENT)); // Create a link DISCUSSION_SERVICE.createTopic(TEST_SITE_NAME, "Title"); // It will now exist assertTrue(SITE_SERVICE.hasContainer(TEST_SITE_NAME, DiscussionServiceImpl.DISCUSSION_COMPONENT)); // It'll be a tag scope too NodeRef container = SITE_SERVICE.getContainer(TEST_SITE_NAME, DiscussionServiceImpl.DISCUSSION_COMPONENT); assertTrue(TAGGING_SERVICE.isTagScope(container)); // Tidy up SITE_SERVICE.deleteSite(TEST_SITE_NAME); return null; } }); } @Test public void tagging() throws Exception { TopicInfo topic; final String TAG_1 = "link_tag_1"; final String TAG_2 = "link_tag_2"; final String TAG_3 = "link_tag_3"; // Create one without tagging topic = DISCUSSION_SERVICE.createTopic(DISCUSSION_SITE.getShortName(), "Title"); testNodesToTidy.add(topic.getNodeRef()); // Check when(TAGGING_SERVICE.getTags(topic.getNodeRef())).thenReturn(new ArrayList<>(10)); assertEquals(0, topic.getTags().size()); topic = DISCUSSION_SERVICE.getTopic(DISCUSSION_SITE.getShortName(), topic.getSystemName()); when(TAGGING_SERVICE.getTags(topic.getNodeRef())).thenReturn(new ArrayList<>(10)); assertEquals(0, topic.getTags().size()); // Update it to have tags topic.getTags().add(TAG_1); topic.getTags().add(TAG_2); topic.getTags().add(TAG_1); assertEquals(3, topic.getTags().size()); DISCUSSION_SERVICE.updateTopic(topic); // Check when(TAGGING_SERVICE.getTags(topic.getNodeRef())).thenReturn(new ArrayList<>(Arrays.asList(TAG_1, TAG_2))); topic = DISCUSSION_SERVICE.getTopic(DISCUSSION_SITE.getShortName(), topic.getSystemName()); assertEquals(2, topic.getTags().size()); assertEquals(true, topic.getTags().contains(TAG_1)); assertEquals(true, topic.getTags().contains(TAG_2)); assertEquals(false, topic.getTags().contains(TAG_3)); // Update it to have different tags topic.getTags().remove(TAG_2); topic.getTags().add(TAG_3); topic.getTags().add(TAG_1); DISCUSSION_SERVICE.updateTopic(topic); // Check it as-is when(TAGGING_SERVICE.getTags(topic.getNodeRef())).thenReturn(new ArrayList<>(Arrays.asList(TAG_1, TAG_3))); assertEquals(3, topic.getTags().size()); // Includes duplicate tag until re-loaded assertEquals(true, topic.getTags().contains(TAG_1)); assertEquals(false, topic.getTags().contains(TAG_2)); assertEquals(true, topic.getTags().contains(TAG_3)); // Now load and re-check when(TAGGING_SERVICE.getTags(topic.getNodeRef())).thenReturn(new ArrayList<>(Arrays.asList(TAG_1, TAG_3))); topic = DISCUSSION_SERVICE.getTopic(DISCUSSION_SITE.getShortName(), topic.getSystemName()); assertEquals(2, topic.getTags().size()); // Duplicate now gone assertEquals(true, topic.getTags().contains(TAG_1)); assertEquals(false, topic.getTags().contains(TAG_2)); assertEquals(true, topic.getTags().contains(TAG_3)); // Update it to have no tags topic.getTags().clear(); DISCUSSION_SERVICE.updateTopic(topic); // Check when(TAGGING_SERVICE.getTags(topic.getNodeRef())).thenReturn(new ArrayList<>(10)); topic = DISCUSSION_SERVICE.getTopic(DISCUSSION_SITE.getShortName(), topic.getSystemName()); assertEquals(0, topic.getTags().size()); // Update it to have tags again topic.getTags().add(TAG_1); topic.getTags().add(TAG_2); topic.getTags().add(TAG_3); DISCUSSION_SERVICE.updateTopic(topic); // Check when(TAGGING_SERVICE.getTags(topic.getNodeRef())).thenReturn(new ArrayList<>(Arrays.asList(TAG_1, TAG_2, TAG_3))); topic = DISCUSSION_SERVICE.getTopic(DISCUSSION_SITE.getShortName(), topic.getSystemName()); assertEquals(3, topic.getTags().size()); assertEquals(true, topic.getTags().contains(TAG_1)); assertEquals(true, topic.getTags().contains(TAG_2)); assertEquals(true, topic.getTags().contains(TAG_3)); // Tidy DISCUSSION_SERVICE.deleteTopic(topic); } /** * Checks we correctly identify hot topics */ @Test public void discussionsHotTopicsListing() throws Exception { PagingRequest paging = new PagingRequest(10); PagingResults<Pair<TopicInfo,Integer>> topics; Date now = new Date(); Date yesterday = new Date(now.getTime()-ONE_DAY_MS-60000); Date tomorrow = new Date(now.getTime()+ONE_DAY_MS); Date future = new Date(now.getTime()+10*ONE_DAY_MS); Date fourDaysAgo = new Date(now.getTime()-4*ONE_DAY_MS); // To start with, we have no hot topics topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, paging); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, fourDaysAgo, paging); assertEquals(0, topics.getPage().size()); // Create some topics TopicInfo topicSA = DISCUSSION_SERVICE.createTopic( DISCUSSION_SITE.getShortName(), "Title1A"); TopicInfo topicSB = DISCUSSION_SERVICE.createTopic( DISCUSSION_SITE.getShortName(), "Title1B"); testNodesToTidy.add(topicSA.getNodeRef()); testNodesToTidy.add(topicSB.getNodeRef()); TopicInfo topicNA = DISCUSSION_SERVICE.createTopic( FORUM_NODE, "TitleNA"); TopicInfo topicNB = DISCUSSION_SERVICE.createTopic( FORUM_NODE, "TitleNB"); testNodesToTidy.add(topicNA.getNodeRef()); testNodesToTidy.add(topicNB.getNodeRef()); // These won't show as hot, as they have no posts on them topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, paging); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, fourDaysAgo, paging); assertEquals(0, topics.getPage().size()); // Add primary posts, this won't help as only replies count PostInfo postSA = DISCUSSION_SERVICE.createPost(topicSA, "Test S Post"); PostInfo postSB = DISCUSSION_SERVICE.createPost(topicSB, "Test S Post"); PostInfo postNA = DISCUSSION_SERVICE.createPost(topicNA, "Test N Post"); PostInfo postNB = DISCUSSION_SERVICE.createPost(topicNB, "Test N Post"); topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, paging); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, fourDaysAgo, paging); assertEquals(0, topics.getPage().size()); // Add a few replies, topics will begin showing up PostInfo replySA1 = DISCUSSION_SERVICE.createReply(postSA, "Reply SA 1"); PostInfo replySB1 = DISCUSSION_SERVICE.createReply(postSB, "Reply SB 1"); PostInfo replySB2 = DISCUSSION_SERVICE.createReply(postSB, "Reply SB 2"); PostInfo replySB3 = DISCUSSION_SERVICE.createReply(postSB, "Reply SB 3"); PostInfo replyNA1 = DISCUSSION_SERVICE.createReply(postNA, "Reply NA 1"); PostInfo replyNB1 = DISCUSSION_SERVICE.createReply(postNB, "Reply NB 1"); PostInfo replyNB2 = DISCUSSION_SERVICE.createReply(postNB, "Reply NB 2"); PostInfo replyNB3 = DISCUSSION_SERVICE.createReply(postNB, "Reply NB 3"); PostInfo replyNB4 = DISCUSSION_SERVICE.createReply(postNB, "Reply NB 4"); // Check we now see things as expected, ordered by count topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, paging); assertEquals(2, topics.getPage().size()); assertEquals(topicSB.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(3, topics.getPage().get(0).getSecond().intValue()); assertEquals(topicSA.getTitle(), topics.getPage().get(1).getFirst().getTitle()); assertEquals(1, topics.getPage().get(1).getSecond().intValue()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, fourDaysAgo, paging); assertEquals(2, topics.getPage().size()); assertEquals(topicNB.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(4, topics.getPage().get(0).getSecond().intValue()); assertEquals(topicNA.getTitle(), topics.getPage().get(1).getFirst().getTitle()); assertEquals(1, topics.getPage().get(1).getSecond().intValue()); // Add reply to reply, counts go up PostInfo replySA1_1 = DISCUSSION_SERVICE.createReply(replySA1, "Reply to a reply"); PostInfo replyNA1_1 = DISCUSSION_SERVICE.createReply(replyNA1, "Reply to a reply"); topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, paging); assertEquals(2, topics.getPage().size()); assertEquals(topicSB.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(3, topics.getPage().get(0).getSecond().intValue()); assertEquals(topicSA.getTitle(), topics.getPage().get(1).getFirst().getTitle()); assertEquals(2, topics.getPage().get(1).getSecond().intValue()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, fourDaysAgo, paging); assertEquals(2, topics.getPage().size()); assertEquals(topicNB.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(4, topics.getPage().get(0).getSecond().intValue()); assertEquals(topicNA.getTitle(), topics.getPage().get(1).getFirst().getTitle()); assertEquals(2, topics.getPage().get(1).getSecond().intValue()); // Changing the date of the primary post or the topic makes no difference pushAuditableDatesBack(topicSA, 11, 1); pushAuditableDatesBack(topicSB, 12, 2); pushAuditableDatesBack(topicNA, 13, 3); pushAuditableDatesBack(topicNB, 14, 4); pushAuditableDatesBack(postSA, 3, 3); pushAuditableDatesBack(postNA, 3, 3); topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, paging); assertEquals(2, topics.getPage().size()); assertEquals(topicSB.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(3, topics.getPage().get(0).getSecond().intValue()); assertEquals(topicSA.getTitle(), topics.getPage().get(1).getFirst().getTitle()); assertEquals(2, topics.getPage().get(1).getSecond().intValue()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, fourDaysAgo, paging); assertEquals(2, topics.getPage().size()); assertEquals(topicNB.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(4, topics.getPage().get(0).getSecond().intValue()); assertEquals(topicNA.getTitle(), topics.getPage().get(1).getFirst().getTitle()); assertEquals(2, topics.getPage().get(1).getSecond().intValue()); // Push some replies into the past, counts go down pushAuditableDatesBack(replySA1, 6, 6); pushAuditableDatesBack(replyNA1, 6, 6); pushAuditableDatesBack(replySB1, 1, 1); // Not enough to affect it pushAuditableDatesBack(replyNB1, 1, 1); // Not enough to affect it topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, paging); assertEquals(2, topics.getPage().size()); assertEquals(topicSB.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(3, topics.getPage().get(0).getSecond().intValue()); assertEquals(topicSA.getTitle(), topics.getPage().get(1).getFirst().getTitle()); assertEquals(1, topics.getPage().get(1).getSecond().intValue()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, fourDaysAgo, paging); assertEquals(2, topics.getPage().size()); assertEquals(topicNB.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(4, topics.getPage().get(0).getSecond().intValue()); assertEquals(topicNA.getTitle(), topics.getPage().get(1).getFirst().getTitle()); assertEquals(1, topics.getPage().get(1).getSecond().intValue()); // Push most replies into the past, still shows, created date ordering matters here pushAuditableDatesBack(replySB2, 10, 10); pushAuditableDatesBack(replySB3, 10, 10); pushAuditableDatesBack(replyNB2, 10, 10); pushAuditableDatesBack(replyNB3, 10, 10); pushAuditableDatesBack(replyNB4, 10, 10); topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, paging); assertEquals(2, topics.getPage().size()); assertEquals(topicSA.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(1, topics.getPage().get(0).getSecond().intValue()); assertEquals(topicSB.getTitle(), topics.getPage().get(1).getFirst().getTitle()); assertEquals(1, topics.getPage().get(1).getSecond().intValue()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, fourDaysAgo, paging); assertEquals(2, topics.getPage().size()); assertEquals(topicNA.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(1, topics.getPage().get(0).getSecond().intValue()); assertEquals(topicNB.getTitle(), topics.getPage().get(1).getFirst().getTitle()); assertEquals(1, topics.getPage().get(1).getSecond().intValue()); // Delete the few recent replies, topics will then vanish DISCUSSION_SERVICE.deletePost(replySB1); DISCUSSION_SERVICE.deletePost(replyNB1); topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, paging); assertEquals(1, topics.getPage().size()); assertEquals(topicSA.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(1, topics.getPage().get(0).getSecond().intValue()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, fourDaysAgo, paging); assertEquals(1, topics.getPage().size()); assertEquals(topicNA.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(1, topics.getPage().get(0).getSecond().intValue()); // Exact date matching check pushAuditableDatesBack(replySA1_1, 1, 1); pushAuditableDatesBack(replyNA1_1, 1, 1); topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), fourDaysAgo, paging); assertEquals(1, topics.getPage().size()); assertEquals(topicSA.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(1, topics.getPage().get(0).getSecond().intValue()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, fourDaysAgo, paging); assertEquals(1, topics.getPage().size()); assertEquals(topicNA.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(1, topics.getPage().get(0).getSecond().intValue()); topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), yesterday, paging); assertEquals(1, topics.getPage().size()); assertEquals(topicSA.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(1, topics.getPage().get(0).getSecond().intValue()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, yesterday, paging); assertEquals(1, topics.getPage().size()); assertEquals(topicNA.getTitle(), topics.getPage().get(0).getFirst().getTitle()); assertEquals(1, topics.getPage().get(0).getSecond().intValue()); // If we ask for a date in the future, we don't get anything though topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), tomorrow, paging); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, tomorrow, paging); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listHotTopics(DISCUSSION_SITE.getShortName(), future, paging); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listHotTopics(FORUM_NODE, future, paging); assertEquals(0, topics.getPage().size()); } /** * Checks that the correct permission checking occurs on fetching * topic and post listings (which go through canned queries) */ @Test public void discussionsListingPermissionsChecking() throws Exception { PagingRequest paging = new PagingRequest(10); PagingResults<TopicInfo> topics; PagingResults<PostInfo> posts; // Nothing to start with in either site or on the node topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, paging); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(ALTERNATE_DISCUSSION_SITE.getShortName(), true, paging); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, paging); assertEquals(0, topics.getPage().size()); // Double check that we're only allowed to see the 1st site assertEquals(true, SITE_SERVICE.isMember(DISCUSSION_SITE.getShortName(), TEST_USER)); assertEquals(false, SITE_SERVICE.isMember(ALTERNATE_DISCUSSION_SITE.getShortName(), TEST_USER)); // Now become the test user AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); TenantContextHolder.setTenantDomain(TENANT_DOMAIN); // Add Topics to the two sites and the test node // Note - add the events as a different user for the site that the // test user isn't a member of! TopicInfo topicSA = DISCUSSION_SERVICE.createTopic( DISCUSSION_SITE.getShortName(), "Title1A"); TopicInfo topicSB = DISCUSSION_SERVICE.createTopic( DISCUSSION_SITE.getShortName(), "Title1B"); testNodesToTidy.add(topicSA.getNodeRef()); testNodesToTidy.add(topicSB.getNodeRef()); AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); TopicInfo topicPrivA = DISCUSSION_SERVICE.createTopic( ALTERNATE_DISCUSSION_SITE.getShortName(), "PrivTitleA"); TopicInfo topicPrivB = DISCUSSION_SERVICE.createTopic( ALTERNATE_DISCUSSION_SITE.getShortName(), "PrivTitleB"); TopicInfo topicPrivC = DISCUSSION_SERVICE.createTopic( ALTERNATE_DISCUSSION_SITE.getShortName(), "PrivTitleC"); testNodesToTidy.add(topicPrivA.getNodeRef()); testNodesToTidy.add(topicPrivB.getNodeRef()); testNodesToTidy.add(topicPrivC.getNodeRef()); AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); TopicInfo topicNA = DISCUSSION_SERVICE.createTopic( FORUM_NODE, "TitleNA"); AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); TopicInfo topicNB = DISCUSSION_SERVICE.createTopic( FORUM_NODE, "TitleNB"); AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); testNodesToTidy.add(topicNA.getNodeRef()); testNodesToTidy.add(topicNB.getNodeRef()); // Check again, as we're not in the 2nd site won't see any there topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, paging); assertEquals(2, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(ALTERNATE_DISCUSSION_SITE.getShortName(), true, paging); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, paging); assertEquals(2, topics.getPage().size()); // Join the site, now we can see both TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); SITE_SERVICE.setMembership(ALTERNATE_DISCUSSION_SITE.getShortName(), TEST_USER, SiteModel.SITE_COLLABORATOR); AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); return null; } }); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, paging); assertEquals(2, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(ALTERNATE_DISCUSSION_SITE.getShortName(), true, paging); assertEquals(3, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, paging); assertEquals(2, topics.getPage().size()); // Explicitly remove their permissions from one node on each, // check it vanishes from the list PERMISSION_SERVICE.setInheritParentPermissions(topicPrivC.getNodeRef(), false); PERMISSION_SERVICE.clearPermission(topicPrivC.getNodeRef(), TEST_USER); PERMISSION_SERVICE.setInheritParentPermissions(topicNB.getNodeRef(), false); PERMISSION_SERVICE.clearPermission(topicNB.getNodeRef(), TEST_USER); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, paging); assertEquals(2, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(ALTERNATE_DISCUSSION_SITE.getShortName(), true, paging); assertEquals(2, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, paging); assertEquals(1, topics.getPage().size()); // Create a primary post on each topic AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); DISCUSSION_SERVICE.createPost(topicSA, "Test S Post"); DISCUSSION_SERVICE.createPost(topicSB, "Test S Post"); DISCUSSION_SERVICE.createPost(topicPrivA, "Test P Post"); DISCUSSION_SERVICE.createPost(topicPrivB, "Test P Post"); DISCUSSION_SERVICE.createPost(topicPrivC, "Test P Post"); DISCUSSION_SERVICE.createPost(topicNA, "Test N Post"); DISCUSSION_SERVICE.createPost(topicNB, "Test N Post"); AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); // Check we see the primary post everywhere we can see the node posts = DISCUSSION_SERVICE.listPosts(topicSA, paging); assertEquals(1, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicSB, paging); assertEquals(1, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicPrivA, paging); assertEquals(1, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicPrivB, paging); assertEquals(1, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicPrivC, paging); assertEquals(0, posts.getPage().size()); // Topic hidden posts = DISCUSSION_SERVICE.listPosts(topicNA, paging); assertEquals(1, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicNB, paging); assertEquals(0, posts.getPage().size()); // Topic hidden // Remove permissions from some posts, check they vanish PostInfo ppSA = DISCUSSION_SERVICE.getPrimaryPost(topicSA); PERMISSION_SERVICE.setInheritParentPermissions(ppSA.getNodeRef(), false); PERMISSION_SERVICE.clearPermission(ppSA.getNodeRef(), TEST_USER); PostInfo ppPA = DISCUSSION_SERVICE.getPrimaryPost(topicPrivA); PERMISSION_SERVICE.setInheritParentPermissions(ppPA.getNodeRef(), false); PERMISSION_SERVICE.clearPermission(ppPA.getNodeRef(), TEST_USER); PostInfo ppNA = DISCUSSION_SERVICE.getPrimaryPost(topicNA); PERMISSION_SERVICE.setInheritParentPermissions(ppNA.getNodeRef(), false); PERMISSION_SERVICE.clearPermission(ppNA.getNodeRef(), TEST_USER); posts = DISCUSSION_SERVICE.listPosts(topicSA, paging); assertEquals(0, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicSB, paging); assertEquals(1, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicPrivA, paging); assertEquals(0, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicPrivB, paging); assertEquals(1, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicPrivC, paging); assertEquals(0, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicNA, paging); assertEquals(0, posts.getPage().size()); posts = DISCUSSION_SERVICE.listPosts(topicNB, paging); assertEquals(0, posts.getPage().size()); // Leave, the site, they go away again TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); SITE_SERVICE.removeMembership(ALTERNATE_DISCUSSION_SITE.getShortName(), TEST_USER); AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); return null; } }); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, paging); assertEquals(2, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(ALTERNATE_DISCUSSION_SITE.getShortName(), true, paging); assertEquals(0, topics.getPage().size()); topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, paging); assertEquals(1, topics.getPage().size()); // Tidy paging = new PagingRequest(10); AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); topics = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, paging); for (TopicInfo topic : topics.getPage()) { PUBLIC_NODE_SERVICE.deleteNode(topic.getNodeRef()); } topics = DISCUSSION_SERVICE.listTopics(ALTERNATE_DISCUSSION_SITE.getShortName(), true, paging); for (TopicInfo topic : topics.getPage()) { PUBLIC_NODE_SERVICE.deleteNode(topic.getNodeRef()); } topics = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, paging); for (TopicInfo topic : topics.getPage()) { PUBLIC_NODE_SERVICE.deleteNode(topic.getNodeRef()); } } /** * Tests that "fm:post" content is not archived. */ @Test public void alf_9460() { TopicInfo siteTopic; TopicInfo nodeTopic; PostInfo post; PostInfo reply; // Nothing to start with PagingResults<TopicInfo> results = DISCUSSION_SERVICE.listTopics(DISCUSSION_SITE.getShortName(), true, new PagingRequest(10)); assertEquals(0, results.getPage().size()); results = DISCUSSION_SERVICE.listTopics(FORUM_NODE, true, new PagingRequest(10)); assertEquals(0, results.getPage().size()); // Create two topics, one node and one site based siteTopic = DISCUSSION_SERVICE.createTopic(DISCUSSION_SITE.getShortName(), "Site Title"); nodeTopic = DISCUSSION_SERVICE.createTopic(FORUM_NODE, "Node Title"); testNodesToTidy.add(siteTopic.getNodeRef()); testNodesToTidy.add(nodeTopic.getNodeRef()); for (TopicInfo topic : new TopicInfo[] {siteTopic, nodeTopic}) { // Create the first post String contents = "This Is Some Content"; post = DISCUSSION_SERVICE.createPost(topic, contents); // Add a reply String reply1Contents = "Reply Contents"; reply = DISCUSSION_SERVICE.createReply(post, reply1Contents); List<AssociationRef> assocs = PUBLIC_NODE_SERVICE.getTargetAssocs(reply.getNodeRef(), ContentModel.ASSOC_REFERENCES); // check that reply has an association with original post assertNotNull(assocs); assertEquals(1, assocs.size()); assertEquals(post.getNodeRef(), assocs.get(0).getTargetRef()); // delete the original post DISCUSSION_SERVICE.deletePost(post); // check that post was deleted assertFalse(PUBLIC_NODE_SERVICE.exists(post.getNodeRef())); // check that associations to the original post was also deleted assocs = PUBLIC_NODE_SERVICE.getTargetAssocs(reply.getNodeRef(), ContentModel.ASSOC_REFERENCES); assertNotNull(assocs); assertEquals(0, assocs.size()); } } // -------------------------------------------------------------------------------- /** * Alters the created date on a wiki page for testing */ private void pushAuditableDatesBack(final Object thing, final int createdDaysAgo, final int modifiedDaysAgo) throws Exception { NodeRef tmpNodeRef; if (thing instanceof NodeRef) { tmpNodeRef = (NodeRef)thing; } else if (thing instanceof TopicInfo) { tmpNodeRef = ((TopicInfo)thing).getNodeRef(); } else if (thing instanceof PostInfo) { tmpNodeRef = ((PostInfo)thing).getNodeRef(); } else { throw new IllegalArgumentException("Unknown thing " + thing); } final NodeRef node = tmpNodeRef; final Date created = (Date)PUBLIC_NODE_SERVICE.getProperty(node, ContentModel.PROP_CREATED); final Date newCreated = new Date(created.getTime() - createdDaysAgo*ONE_DAY_MS); final Date modified = (Date)PUBLIC_NODE_SERVICE.getProperty(node, ContentModel.PROP_MODIFIED); final Date newModified = new Date(modified.getTime() - modifiedDaysAgo*ONE_DAY_MS); // Update the created date TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { BEHAVIOUR_FILTER.disableBehaviour(ContentModel.ASPECT_AUDITABLE); NODE_SERVICE.setProperty(node, ContentModel.PROP_CREATED, newCreated); NODE_SERVICE.setProperty(node, ContentModel.PROP_MODIFIED, newModified); return null; } }, false, true); // Change something else too in the public nodeservice, to force a re-index TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { BEHAVIOUR_FILTER.disableBehaviour(ContentModel.ASPECT_AUDITABLE); PUBLIC_NODE_SERVICE.setProperty(node, ContentModel.PROP_CREATED, newCreated); PUBLIC_NODE_SERVICE.setProperty(node, ContentModel.PROP_MODIFIED, newModified); PUBLIC_NODE_SERVICE.setProperty(node, ContentModel.PROP_DESCRIPTION, "Forced Change"); return null; } }, false, true); // Check it was taken TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { assertEquals(newCreated, NODE_SERVICE.getProperty(node, ContentModel.PROP_CREATED)); assertEquals(newCreated, PUBLIC_NODE_SERVICE.getProperty(node, ContentModel.PROP_CREATED)); assertEquals(newModified, NODE_SERVICE.getProperty(node, ContentModel.PROP_MODIFIED)); assertEquals(newModified, PUBLIC_NODE_SERVICE.getProperty(node, ContentModel.PROP_MODIFIED)); return null; } }, false, true); // Update the object itself if (thing instanceof TopicInfo) { ((TopicInfoImpl)thing).setCreatedAt(newCreated); ((TopicInfoImpl)thing).setModifiedAt(newModified); } if (thing instanceof PostInfo) { ((PostInfoImpl)thing).setCreatedAt(newCreated); ((PostInfoImpl)thing).setModifiedAt(newModified); } } private static void createTestSites() throws Exception { final DiscussionServiceImpl privateDiscussionService = (DiscussionServiceImpl)testContext.getBean("discussionService"); DISCUSSION_SITE = TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<SiteInfo>() { @Override public SiteInfo execute() throws Throwable { SiteInfo site = SITE_SERVICE.createSite( TEST_SITE_PREFIX, DiscussionServiceImplTest.class.getSimpleName() + "_testSite" + System.currentTimeMillis(), "test site title", "test site description", SiteVisibility.PUBLIC); privateDiscussionService.getSiteDiscussionsContainer(site.getShortName(), true); CLASS_TEST_NODES_TO_TIDY.add(site.getNodeRef()); return site; } }); // Add a forum within it, used for the alternate testing FORUM_NODE = TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>() { @Override public NodeRef execute() throws Throwable { NodeRef node = NODE_SERVICE.createNode( DISCUSSION_SITE.getNodeRef(), ForumModel.ASSOC_DISCUSSION, QName.createQName("Forum"), ForumModel.TYPE_FORUM ).getChildRef(); NODE_SERVICE.setProperty(node, ContentModel.PROP_NAME, "Forum"); NODE_SERVICE.setProperty(node, ContentModel.PROP_TITLE, "Forum"); CLASS_TEST_NODES_TO_TIDY.add(node); return node; } }); // Create the alternate site as admin AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); TenantContextHolder.setTenantDomain(TENANT_DOMAIN); ALTERNATE_DISCUSSION_SITE = TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<SiteInfo>() { @Override public SiteInfo execute() throws Throwable { SiteInfo site = SITE_SERVICE.createSite( TEST_SITE_PREFIX, DiscussionServiceImplTest.class.getSimpleName() + "_testAltSite" + System.currentTimeMillis(), "alternate site title", "alternate site description", SiteVisibility.PRIVATE); privateDiscussionService.getSiteDiscussionsContainer(site.getShortName(), true); CLASS_TEST_NODES_TO_TIDY.add(site.getNodeRef()); return site; } }); AuthenticationUtil.setFullyAuthenticatedUser(TEST_USER); TenantContextHolder.setTenantDomain(TENANT_DOMAIN); } private static void createTenant() { TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { if (!TENANT_ADMIN_SERVICE.existsTenant(TENANT_DOMAIN)) { TENANT_ADMIN_SERVICE.createTenant(TENANT_DOMAIN, "password".toCharArray()); } return null; } }); } /** * By default, all tests are run as the admin user. */ @Before public void setAdminUser() { AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); TenantContextHolder.setTenantDomain(TENANT_DOMAIN); } @After public void deleteTestNodes() throws Exception { performDeletionOfNodes(testNodesToTidy); } @AfterClass public static void deleteClassTestNodesAndUsers() throws Exception { performDeletionOfNodes(CLASS_TEST_NODES_TO_TIDY); deleteUser(TEST_USER); deleteTenant(); TenantContextHolder.setTenantDomain(""); AuthenticationUtil.setMtEnabled(false); AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); } private static void deleteTenant() { TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { // TODO: WARNING: HACK for ALF-19155: MT deleteTenant does not work // PersonService prevents 'guest' authorities from being deleted { BehaviourFilter behaviourFilter = (BehaviourFilter) testContext.getBean("policyBehaviourFilter"); behaviourFilter.disableBehaviour(ContentModel.TYPE_PERSON); behaviourFilter.disableBehaviour(ContentModel.ASPECT_UNDELETABLE); } TENANT_ADMIN_SERVICE.deleteTenant(TENANT_DOMAIN); return null; } }); } /** * Deletes the specified NodeRefs, if they exist. * @param nodesToDelete List<NodeRef> */ private static void performDeletionOfNodes(final List<NodeRef> nodesToDelete) { TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { AuthenticationUtil.setFullyAuthenticatedUser(ADMIN_USER); for (NodeRef node : nodesToDelete) { if (NODE_SERVICE.exists(node)) { // st:site nodes can only be deleted via the SiteService if (NODE_SERVICE.getType(node).equals(SiteModel.TYPE_SITE)) { SiteInfo siteInfo = SITE_SERVICE.getSite(node); SITE_SERVICE.deleteSite(siteInfo.getShortName()); } else { NODE_SERVICE.deleteNode(node); } } } return null; } }); } private static void createUser(final String userName) { TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { if (!AUTHENTICATION_SERVICE.authenticationExists(userName)) { AUTHENTICATION_SERVICE.createAuthentication(userName, "PWD".toCharArray()); } if (!PERSON_SERVICE.personExists(userName)) { PropertyMap ppOne = new PropertyMap(); ppOne.put(ContentModel.PROP_USERNAME, userName); ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName"); ppOne.put(ContentModel.PROP_LASTNAME, "lastName"); ppOne.put(ContentModel.PROP_EMAIL, "[email protected]"); ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle"); PERSON_SERVICE.createPerson(ppOne); } return null; } }); } private static void deleteUser(final String userName) { TRANSACTION_HELPER.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() { @Override public Void execute() throws Throwable { if (PERSON_SERVICE.personExists(userName)) { PERSON_SERVICE.deletePerson(userName); } return null; } }); } }