From b94a0af2e9f841d59f4c866b201e8aa30a43eb6a Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Wed, 24 Aug 2011 13:45:59 +0000 Subject: [PATCH] ALF-9153 Discussions service CQ support for finding "hot" topics (those with recent replies) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@30027 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../alfresco/discussions-services-context.xml | 10 ++ .../alfresco/ibatis/alfresco-SqlMapConfig.xml | 4 + .../query-discussion-common-SqlMap.xml | 54 +++++++ .../discussion/DiscussionServiceImpl.java | 109 +++++++++++-- .../discussion/DiscussionServiceImplTest.java | 67 ++++++++ ...tDiscussionTopcisWithPostsCannedQuery.java | 153 ++++++++++++++++++ ...sionTopcisWithPostsCannedQueryFactory.java | 87 ++++++++++ ...ssionTopcisWithPostsCannedQueryParams.java | 56 +++++++ .../cannedqueries/NodeWithChildrenEntity.java | 110 +++++++++++++ .../cmr/discussion/DiscussionService.java | 33 ++-- 10 files changed, 653 insertions(+), 30 deletions(-) create mode 100644 config/alfresco/ibatis/org.hibernate.dialect.Dialect/query-discussion-common-SqlMap.xml create mode 100644 source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQuery.java create mode 100644 source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQueryFactory.java create mode 100644 source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQueryParams.java create mode 100644 source/java/org/alfresco/repo/discussion/cannedqueries/NodeWithChildrenEntity.java diff --git a/config/alfresco/discussions-services-context.xml b/config/alfresco/discussions-services-context.xml index df8ddf30e0..021eb2e5b6 100644 --- a/config/alfresco/discussions-services-context.xml +++ b/config/alfresco/discussions-services-context.xml @@ -59,6 +59,16 @@ + + + + + + + + + + diff --git a/config/alfresco/ibatis/alfresco-SqlMapConfig.xml b/config/alfresco/ibatis/alfresco-SqlMapConfig.xml index a54fcbf5bc..65045134b9 100644 --- a/config/alfresco/ibatis/alfresco-SqlMapConfig.xml +++ b/config/alfresco/ibatis/alfresco-SqlMapConfig.xml @@ -86,6 +86,9 @@ Inbound settings from iBatis + + + @@ -200,6 +203,7 @@ Inbound settings from iBatis + diff --git a/config/alfresco/ibatis/org.hibernate.dialect.Dialect/query-discussion-common-SqlMap.xml b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/query-discussion-common-SqlMap.xml new file mode 100644 index 0000000000..3987abfb77 --- /dev/null +++ b/config/alfresco/ibatis/org.hibernate.dialect.Dialect/query-discussion-common-SqlMap.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/discussion/DiscussionServiceImpl.java b/source/java/org/alfresco/repo/discussion/DiscussionServiceImpl.java index 303ed23ca8..70b02dd195 100644 --- a/source/java/org/alfresco/repo/discussion/DiscussionServiceImpl.java +++ b/source/java/org/alfresco/repo/discussion/DiscussionServiceImpl.java @@ -33,6 +33,10 @@ import org.alfresco.query.CannedQuerySortDetails; import org.alfresco.query.EmptyPagingResults; import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingResults; +import org.alfresco.repo.discussion.cannedqueries.GetDiscussionTopcisWithPostsCannedQuery; +import org.alfresco.repo.discussion.cannedqueries.GetDiscussionTopcisWithPostsCannedQueryFactory; +import org.alfresco.repo.discussion.cannedqueries.NodeWithChildrenEntity; +import org.alfresco.repo.discussion.cannedqueries.NodeWithChildrenEntity.NameAndCreatedAt; import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.node.getchildren.GetChildrenAuditableCannedQuery; import org.alfresco.repo.node.getchildren.GetChildrenAuditableCannedQueryFactory; @@ -80,6 +84,7 @@ public class DiscussionServiceImpl implements DiscussionService protected static final String CANNED_QUERY_GET_CHILDREN = "discussionGetChildrenCannedQueryFactory"; protected static final String CANNED_QUERY_GET_CHILDREN_TARGETS = "discussionGetChildrenWithTargetAssocsAuditableCannedQueryFactory"; + protected static final String CANNED_QUERY_GET_TOPICS_WITH_POSTS = "discussionGetDiscussionTopcisWithPostsCannedQueryFactory"; protected static final int MAX_REPLIES_FETCH_SIZE = 1000; /** @@ -651,7 +656,38 @@ public class DiscussionServiceImpl implements DiscussionService // Wrap and return return wrap(nodes, nodeRef); } + + @Override + public PagingResults> listHotTopics( + String siteShortName, Date since, PagingRequest paging) { + NodeRef container = getSiteDiscussionsContainer(siteShortName, false); + if(container == null) + { + // No topics + return new EmptyPagingResults>(); + } + + // We can now fetch by parent nodeRef + return listHotTopics(container, since, paging); + } + + @Override + public PagingResults> listHotTopics( + NodeRef nodeRef, Date since, PagingRequest paging) { + // Do the query + GetDiscussionTopcisWithPostsCannedQueryFactory getCQFactory = (GetDiscussionTopcisWithPostsCannedQueryFactory)cannedQueryRegistry.getNamedObject(CANNED_QUERY_GET_TOPICS_WITH_POSTS); + GetDiscussionTopcisWithPostsCannedQuery cq = (GetDiscussionTopcisWithPostsCannedQuery)getCQFactory.getCannedQuery( + nodeRef, null, since, null, paging); + + // Execute the canned query + CannedQueryResults results = cq.execute(); + + // Wrap and return + return wrapWithCount(results, nodeRef); + } + + @Override public PagingResults findTopics(String siteShortName, String username, String tag, PagingRequest paging) { @@ -845,21 +881,7 @@ public class DiscussionServiceImpl implements DiscussionService return new PostWithReplies(post, replies); } - - @Override - public PagingResults listPosts(NodeRef nodeRef, - PagingRequest paging) { - // TODO Auto-generated method stub - return null; - } - @Override - public PagingResults listPosts(String siteShortName, - PagingRequest paging) { - // TODO Auto-generated method stub - return null; - } - /** * Finds nodes in the specified parent container, with the given * type, optionally filtered by creator @@ -1035,4 +1057,63 @@ public class DiscussionServiceImpl implements DiscussionService } }; } + + /** + * Our class to wrap up paged results of NodeWithChildrenEntity as + * {@link TopicInfo} instances + */ + private PagingResults> wrapWithCount(final PagingResults results, final NodeRef container) + { + // Pre-load the nodes before we create them + List ids = new ArrayList(); + for(NodeBackedEntity node : results.getPage()) + { + ids.add(node.getId()); + } + nodeDAO.cacheNodesById(ids); + + // Wrap + return new PagingResults>() + { + @Override + public String getQueryExecutionId() + { + return results.getQueryExecutionId(); + } + @Override + public List> getPage() + { + List> topics = new ArrayList>(); + for(NodeWithChildrenEntity node : results.getPage()) + { + NodeRef nodeRef = node.getNodeRef(); + String name = node.getName(); + TopicInfo topic = buildTopic(nodeRef, container, name); + + int count = node.getChildren().size(); + for(NameAndCreatedAt c : node.getChildren()) + { + if(c.getName().equals(name)) + { + // Primary post + count--; + } + } + + topics.add(new Pair(topic, count)); + } + return topics; + } + @Override + public boolean hasMoreItems() + { + return results.hasMoreItems(); + } + @Override + public Pair getTotalResultCount() + { + return results.getTotalResultCount(); + } + }; + } } diff --git a/source/java/org/alfresco/repo/discussion/DiscussionServiceImplTest.java b/source/java/org/alfresco/repo/discussion/DiscussionServiceImplTest.java index 44dc9da574..5e2a87b216 100644 --- a/source/java/org/alfresco/repo/discussion/DiscussionServiceImplTest.java +++ b/source/java/org/alfresco/repo/discussion/DiscussionServiceImplTest.java @@ -1161,6 +1161,73 @@ public class DiscussionServiceImplTest DISCUSSION_SERVICE.deleteTopic(topic); } + /** + * Checks we correctly identify hot topics + */ + @Test public void discussionsHotTopicsListing() throws Exception + { + PagingRequest paging = new PagingRequest(10); + PagingResults> 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 + + + // TODO + } + /** * Checks that the correct permission checking occurs on fetching * topic and post listings (which go through canned queries) diff --git a/source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQuery.java b/source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQuery.java new file mode 100644 index 0000000000..8a3454d6be --- /dev/null +++ b/source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQuery.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2005-2011 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * 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 . + */ +package org.alfresco.repo.discussion.cannedqueries; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +import org.alfresco.query.CannedQuery; +import org.alfresco.query.CannedQueryParameters; +import org.alfresco.repo.discussion.cannedqueries.NodeWithChildrenEntity.NameAndCreatedAt; +import org.alfresco.repo.domain.query.CannedQueryDAO; +import org.alfresco.repo.security.permissions.impl.acegi.AbstractCannedQueryPermissions; +import org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityBean; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This class provides support for {@link CannedQuery canned queries} which + * filter topics by their posts + * + * @author Nick Burch + * @since 4.0 + */ +public class GetDiscussionTopcisWithPostsCannedQuery extends AbstractCannedQueryPermissions +{ + private Log logger = LogFactory.getLog(getClass()); + + private static final String QUERY_NAMESPACE = "alfresco.query.discussion"; + private static final String QUERY_SELECT_GET_NODES = "select_GetDiscussionTopcisWithPosts"; + + private final CannedQueryDAO cannedQueryDAO; + + public GetDiscussionTopcisWithPostsCannedQuery( + CannedQueryDAO cannedQueryDAO, + MethodSecurityBean methodSecurity, + CannedQueryParameters params) + { + super(params, methodSecurity); + this.cannedQueryDAO = cannedQueryDAO; + } + + @Override + protected List queryAndFilter(CannedQueryParameters parameters) + { + Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null); + + Object paramBeanObj = parameters.getParameterBean(); + if (paramBeanObj == null) + throw new NullPointerException("Null GetChildrenAuditable query params"); + + GetDiscussionTopcisWithPostsCannedQueryParams paramBean = (GetDiscussionTopcisWithPostsCannedQueryParams) paramBeanObj; + + boolean filterByTopicCreatedDate = (paramBean.getTopicCreatedAfter() != null); + boolean filterByPostCreatedDate = (paramBean.getPostCreatedAfter() != null); + + // note: refer to SQL for specific DB filtering (eg.parent nodes etc) + List results = cannedQueryDAO.executeQuery(QUERY_NAMESPACE, QUERY_SELECT_GET_NODES, paramBean, 0, Integer.MAX_VALUE); + + // Filter + List filtered = new ArrayList(results.size()); + for (NodeWithChildrenEntity result : results) + { + // Filter by topic date + if(filterByTopicCreatedDate) + { + Date createdDate = DefaultTypeConverter.INSTANCE.convert(Date.class, result.getCreatedDate()); + if(createdDate.before(paramBean.getTopicCreatedAfter())) + { + // Created too early + continue; + } + } + + // Filter by post date + if(filterByPostCreatedDate) + { + List wantedPosts = new ArrayList(); + for(NameAndCreatedAt post : result.getChildren()) + { + Date createdDate = DefaultTypeConverter.INSTANCE.convert(Date.class, post.getCreatedAt()); + if(createdDate.before(paramBean.getPostCreatedAfter())) + { + // Created too early + continue; + } + else + { + wantedPosts.add(post); + } + } + result.setChildren(wantedPosts); + } + + // Ignore any topic with no replies + // (As topics have a primary post, that means any with less than 2 children) + if(result.getChildren().size() <= 1) + { + // No posts at all, or only the primary one + continue; + } + + // If we get here, the topic is of interest + filtered.add(result); + } + + // Sort by the result count, and then the created date + Collections.sort(filtered, new Comparator() { + @Override + public int compare(NodeWithChildrenEntity o1, NodeWithChildrenEntity o2) { + int res = o2.getChildren().size() - o1.getChildren().size(); + if(res == 0) + { + res = o2.getCreatedDate().compareTo(o1.getCreatedDate()); + } + return res; + } + }); + + if (start != null) + { + logger.debug("Base query: "+filtered.size()+" in "+(System.currentTimeMillis()-start)+" msecs"); + } + + return filtered; + } + + @Override + protected boolean isApplyPostQuerySorting() + { + // No post-query sorting. It's done within the queryAndFilter() method above. + return false; + } +} diff --git a/source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQueryFactory.java b/source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQueryFactory.java new file mode 100644 index 0000000000..19ce932eb8 --- /dev/null +++ b/source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQueryFactory.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2005-2011 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * 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 . + */ +package org.alfresco.repo.discussion.cannedqueries; + +import java.util.Date; + +import org.alfresco.model.ContentModel; +import org.alfresco.model.ForumModel; +import org.alfresco.query.CannedQuery; +import org.alfresco.query.CannedQueryFactory; +import org.alfresco.query.CannedQueryPageDetails; +import org.alfresco.query.CannedQueryParameters; +import org.alfresco.query.CannedQuerySortDetails; +import org.alfresco.query.PagingRequest; +import org.alfresco.repo.query.AbstractQNameAwareCannedQueryFactory; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.util.ParameterCheck; + +/** + * A {@link CannedQueryFactory} for various queries relating to getting + * Topics with some information on their Posts + * + * @author Nick Burch + * @since 4.0 + */ +public class GetDiscussionTopcisWithPostsCannedQueryFactory extends AbstractQNameAwareCannedQueryFactory +{ + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + } + + @Override + public CannedQuery getCannedQuery(CannedQueryParameters parameters) + { + final GetDiscussionTopcisWithPostsCannedQuery cq = new GetDiscussionTopcisWithPostsCannedQuery( + cannedQueryDAO, methodSecurity, parameters + ); + + return (CannedQuery) cq; + } + + public CannedQuery getCannedQuery(NodeRef parentNodeRef, + Date topicCreatedFrom, Date postCreatedFrom, + CannedQuerySortDetails sortDetails, PagingRequest pagingReq) + { + ParameterCheck.mandatory("parentNodeRef", parentNodeRef); + ParameterCheck.mandatory("pagingReq", pagingReq); + + int requestTotalCountMax = pagingReq.getRequestTotalCountMax(); + + //FIXME Need tenant service like for GetChildren? + GetDiscussionTopcisWithPostsCannedQueryParams paramBean = new GetDiscussionTopcisWithPostsCannedQueryParams( + getNodeId(parentNodeRef), + getQNameId(ContentModel.PROP_NAME), + getQNameId(ForumModel.TYPE_TOPIC), + getQNameId(ForumModel.TYPE_POST), + topicCreatedFrom, postCreatedFrom + ); + + CannedQueryPageDetails cqpd = createCQPageDetails(pagingReq); + + // create query params holder + CannedQueryParameters params = new CannedQueryParameters( + paramBean, cqpd, sortDetails, requestTotalCountMax, pagingReq.getQueryExecutionId()); + + // return canned query instance + return getCannedQuery(params); + } +} diff --git a/source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQueryParams.java b/source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQueryParams.java new file mode 100644 index 0000000000..b2387d370c --- /dev/null +++ b/source/java/org/alfresco/repo/discussion/cannedqueries/GetDiscussionTopcisWithPostsCannedQueryParams.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2005-2011 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * 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 . + */ +package org.alfresco.repo.discussion.cannedqueries; + +import java.util.Date; + +/** + * Parameter objects for {@link GetDiscussionTopcisWithPostsCannedQuery}. + * + * @author Nick Burch + * @since 4.0 + */ +public class GetDiscussionTopcisWithPostsCannedQueryParams extends NodeWithChildrenEntity +{ + private Date topicCreatedAfter; + private Date postCreatedAfter; + + public GetDiscussionTopcisWithPostsCannedQueryParams(Long parentNodeId, + Long nameQNameId, + Long contentTypeQNameId, + Long childrenTypeId, + Date topicCreatedAfter, + Date postCreatedAfter) + + { + super(parentNodeId, nameQNameId, contentTypeQNameId, childrenTypeId); + this.topicCreatedAfter = topicCreatedAfter; + this.postCreatedAfter = postCreatedAfter; + } + + public Date getTopicCreatedAfter() + { + return topicCreatedAfter; + } + + public Date getPostCreatedAfter() + { + return postCreatedAfter; + } +} diff --git a/source/java/org/alfresco/repo/discussion/cannedqueries/NodeWithChildrenEntity.java b/source/java/org/alfresco/repo/discussion/cannedqueries/NodeWithChildrenEntity.java new file mode 100644 index 0000000000..170df810ef --- /dev/null +++ b/source/java/org/alfresco/repo/discussion/cannedqueries/NodeWithChildrenEntity.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2005-2011 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * 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 . + */ +package org.alfresco.repo.discussion.cannedqueries; + +import java.util.List; + +import org.alfresco.repo.domain.node.NodeEntity; +import org.alfresco.repo.query.NodeBackedEntity; + +/** + * An extension of a {@link NodeEntity} which has the name + * of all children of it, used with the discussions + * canned queries. + * As well as the name comes some auditable information, but + * not full nodes as we don't do permissions checking on + * the children. + * + * @author Nick Burch + * @since 4.0 + */ +public class NodeWithChildrenEntity extends NodeBackedEntity +{ + private List children; + + // Supplemental query-related parameters + private Long childrenTypeQNameId; + + /** + * Default constructor + */ + public NodeWithChildrenEntity() + { + } + + /** + * Query constructor + */ + public NodeWithChildrenEntity(Long parentNodeId, Long nameQNameId, Long contentTypeQNameId, Long childrenTypeQNameId) + { + super(parentNodeId, nameQNameId, contentTypeQNameId); + this.childrenTypeQNameId = childrenTypeQNameId; + } + + /** + * @return Child Node name+created at + */ + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } + + /** + * If set, the ID of the children's content type to limit + * the children too. + */ + public Long getChildrenTypeQNameId() + { + return childrenTypeQNameId; + } + + public static class NameAndCreatedAt + { + private final Long nodeId; + private final String name; + private final String createdAt; + + public NameAndCreatedAt(Long nodeId, String name, String createdAt) + { + this.nodeId = nodeId; + this.name = name; + this.createdAt = createdAt; + } + + public Long getNodeId() + { + return nodeId; + } + + public String getName() + { + return name; + } + + public String getCreatedAt() + { + return createdAt; + } + } +} diff --git a/source/java/org/alfresco/service/cmr/discussion/DiscussionService.java b/source/java/org/alfresco/service/cmr/discussion/DiscussionService.java index 96a4d216d7..57d3883b7f 100644 --- a/source/java/org/alfresco/service/cmr/discussion/DiscussionService.java +++ b/source/java/org/alfresco/service/cmr/discussion/DiscussionService.java @@ -205,6 +205,23 @@ public interface DiscussionService { PagingResults findTopics(NodeRef nodeRef, String username, String tag, PagingRequest paging); + /** + * Finds topics which have had replies since the specified date, and + * returns them along with the count of replies since then. + * Primary posts are not included in this. + */ + @NotAuditable + PagingResults> listHotTopics(String siteShortName, Date since, PagingRequest paging); + + /** + * Finds topics which have had replies since the specified date, and + * returns them along with the count of replies since then. + * Primary posts are not included in this. + */ + @NotAuditable + PagingResults> listHotTopics(NodeRef nodeRef, Date since, PagingRequest paging); + + /** * Retrieves all posts in a topic, ordered by creation date */ @@ -222,20 +239,4 @@ public interface DiscussionService { */ @NotAuditable PostWithReplies listPostReplies(PostInfo primaryPost, int levels); - - /** - * Retrieves all posts in a site, across all topics - * TODO Is this needed? - */ - @NotAuditable - PagingResults listPosts(String siteShortName, PagingRequest paging); - - /** - * Retrieves all posts attached to the specified Node, across all topics - * TODO Is this needed? - */ - @NotAuditable - PagingResults listPosts(NodeRef nodeRef, PagingRequest paging); - - // TODO Hot topics support }