mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
ALF-9153 Get the discussions reply CQ working, via some careful mybatis collections handling, and add some tests for it
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29843 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -18,8 +18,12 @@
|
|||||||
<id property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
<id property="id" column="id" jdbcType="BIGINT" javaType="java.lang.Long"/>
|
||||||
<result property="name" column="name" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
<result property="name" column="name" jdbcType="VARCHAR" javaType="java.lang.String"/>
|
||||||
<association property="node" resultMap="alfresco.node.result_Node"/>
|
<association property="node" resultMap="alfresco.node.result_Node"/>
|
||||||
<collection property="targetIds" column="target_node_id" jdbcType="BIGINT" javaType="ArrayList" ofType="java.lang.Long"/>
|
<collection property="targets" javaType="ArrayList" ofType="org.alfresco.repo.query.NodeWithTargetsEntity$TargetAndTypeId">
|
||||||
<collection property="targetAssocTypeIds" column="target_assoc_type_id" jdbcType="BIGINT" javaType="ArrayList" ofType="java.lang.Long"/>
|
<constructor>
|
||||||
|
<idArg column="target_node_id" javaType="Long" jdbcType="BIGINT"/>
|
||||||
|
<idArg column="target_assoc_type_id" javaType="Long" jdbcType="BIGINT"/>
|
||||||
|
</constructor>
|
||||||
|
</collection>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
|
|
||||||
@@ -60,19 +64,21 @@
|
|||||||
childNode.audit_modified as audit_modified,
|
childNode.audit_modified as audit_modified,
|
||||||
childNode.audit_modifier as audit_modifier,
|
childNode.audit_modifier as audit_modifier,
|
||||||
prop_name.string_value as name,
|
prop_name.string_value as name,
|
||||||
targetAssoc.parent_node_id as target_node_id,
|
targetAssoc.target_node_id as target_node_id,
|
||||||
targetAssoc.type_qname_id as target_assoc_type_id
|
targetAssoc.type_qname_id as target_assoc_type_id
|
||||||
from
|
from
|
||||||
alf_child_assoc assoc
|
alf_child_assoc assoc
|
||||||
join alf_node childNode on (childNode.id = assoc.child_node_id)
|
join alf_node childNode on (childNode.id = assoc.child_node_id)
|
||||||
join alf_store childStore on (childStore.id = childNode.store_id)
|
join alf_store childStore on (childStore.id = childNode.store_id)
|
||||||
left join alf_node_properties prop_name on (prop_name.node_id = childNode.id and prop_name.qname_id = #{nameQNameId})
|
left join alf_node_properties prop_name on (prop_name.node_id = childNode.id and prop_name.qname_id = #{nameQNameId})
|
||||||
left join alf_child_assoc targetAssoc on (childNode.id = targetAssoc.child_node_id)
|
left join alf_node_assoc targetAssoc on (
|
||||||
where
|
childNode.id = targetAssoc.source_node_id
|
||||||
assoc.parent_node_id = #{parentNodeId}
|
|
||||||
and childNode.type_qname_id = #{contentTypeQNameId}
|
|
||||||
<if test="assocTypeId != null">
|
<if test="assocTypeId != null">
|
||||||
and targetAssoc.type_qname_id = #{assocTypeId}
|
and targetAssoc.type_qname_id = #{assocTypeId}
|
||||||
</if>
|
</if>
|
||||||
|
)
|
||||||
|
where
|
||||||
|
assoc.parent_node_id = #{parentNodeId}
|
||||||
|
and childNode.type_qname_id = #{contentTypeQNameId}
|
||||||
</select>
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
@@ -40,6 +40,7 @@ import org.alfresco.repo.node.getchildren.GetChildrenWithTargetAssocsAuditableCa
|
|||||||
import org.alfresco.repo.node.getchildren.GetChildrenWithTargetAssocsAuditableCannedQueryFactory;
|
import org.alfresco.repo.node.getchildren.GetChildrenWithTargetAssocsAuditableCannedQueryFactory;
|
||||||
import org.alfresco.repo.query.NodeBackedEntity;
|
import org.alfresco.repo.query.NodeBackedEntity;
|
||||||
import org.alfresco.repo.query.NodeWithTargetsEntity;
|
import org.alfresco.repo.query.NodeWithTargetsEntity;
|
||||||
|
import org.alfresco.repo.query.NodeWithTargetsEntity.TargetAndTypeId;
|
||||||
import org.alfresco.repo.site.SiteServiceImpl;
|
import org.alfresco.repo.site.SiteServiceImpl;
|
||||||
import org.alfresco.service.cmr.discussion.DiscussionService;
|
import org.alfresco.service.cmr.discussion.DiscussionService;
|
||||||
import org.alfresco.service.cmr.discussion.PostInfo;
|
import org.alfresco.service.cmr.discussion.PostInfo;
|
||||||
@@ -608,11 +609,77 @@ public class DiscussionServiceImpl implements DiscussionService
|
|||||||
CannedQueryResults<NodeWithTargetsEntity> results = cq.execute();
|
CannedQueryResults<NodeWithTargetsEntity> results = cq.execute();
|
||||||
|
|
||||||
// Prepare to invert
|
// Prepare to invert
|
||||||
// TODO
|
Map<Long,NodeRef> idToNodeRef = new HashMap<Long, NodeRef>();
|
||||||
Map<Long,NodeRef> idToNode = new HashMap<Long, NodeRef>();
|
for(NodeWithTargetsEntity e : results.getPage())
|
||||||
|
{
|
||||||
|
idToNodeRef.put(e.getId(), e.getNodeRef());
|
||||||
|
}
|
||||||
|
|
||||||
// All done
|
Map<NodeRef,List<NodeWithTargetsEntity>> idToReplies = new HashMap<NodeRef, List<NodeWithTargetsEntity>>();
|
||||||
return null;
|
for(NodeWithTargetsEntity e : results.getPage())
|
||||||
|
{
|
||||||
|
for(TargetAndTypeId idP : e.getTargetIds())
|
||||||
|
{
|
||||||
|
Long id = idP.getTargetId();
|
||||||
|
NodeRef nodeRef = idToNodeRef.get(id);
|
||||||
|
if(nodeRef == null)
|
||||||
|
{
|
||||||
|
// References a node outside of this topic
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(id.equals(e.getId()))
|
||||||
|
{
|
||||||
|
// Self reference
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(! idToReplies.containsKey(nodeRef))
|
||||||
|
{
|
||||||
|
idToReplies.put(nodeRef, new ArrayList<NodeWithTargetsEntity>());
|
||||||
|
}
|
||||||
|
idToReplies.get(nodeRef).add(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the list of NodeRefs to pre-load, and pre-load them
|
||||||
|
List<NodeRef> preLoad = new ArrayList<NodeRef>();
|
||||||
|
calculateRepliesPreLoad(primaryPost.getNodeRef(), preLoad, idToReplies, levels);
|
||||||
|
nodeDAO.cacheNodes(preLoad);
|
||||||
|
|
||||||
|
// Wrap
|
||||||
|
return wrap(primaryPost, idToReplies, levels);
|
||||||
|
}
|
||||||
|
private void calculateRepliesPreLoad(NodeRef nodeRef, List<NodeRef> preLoad,
|
||||||
|
Map<NodeRef,List<NodeWithTargetsEntity>> idToReplies, int levels)
|
||||||
|
{
|
||||||
|
preLoad.add(nodeRef);
|
||||||
|
if(levels > 0)
|
||||||
|
{
|
||||||
|
List<NodeWithTargetsEntity> replies = idToReplies.get(nodeRef);
|
||||||
|
if(replies != null && replies.size() > 0)
|
||||||
|
{
|
||||||
|
for(NodeWithTargetsEntity entity : replies)
|
||||||
|
{
|
||||||
|
calculateRepliesPreLoad(entity.getNodeRef(), preLoad, idToReplies, levels-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private PostWithReplies wrap(PostInfo post, Map<NodeRef,List<NodeWithTargetsEntity>> idToReplies, int levels)
|
||||||
|
{
|
||||||
|
List<PostWithReplies> replies = new ArrayList<PostWithReplies>();
|
||||||
|
if(levels > 0)
|
||||||
|
{
|
||||||
|
List<NodeWithTargetsEntity> replyEntities = idToReplies.get(post.getNodeRef());
|
||||||
|
if(replyEntities != null && replyEntities.size() > 0)
|
||||||
|
{
|
||||||
|
for(NodeWithTargetsEntity entity : replyEntities)
|
||||||
|
{
|
||||||
|
PostInfo replyPost = buildPost(entity.getNodeRef(), post.getTopic(), entity.getName(), null);
|
||||||
|
replies.add(wrap(replyPost, idToReplies, levels-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new PostWithReplies(post, replies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -39,6 +39,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti
|
|||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.discussion.DiscussionService;
|
import org.alfresco.service.cmr.discussion.DiscussionService;
|
||||||
import org.alfresco.service.cmr.discussion.PostInfo;
|
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.discussion.TopicInfo;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
@@ -686,7 +687,56 @@ public class DiscussionServiceImplTest
|
|||||||
for(TopicInfo topic : new TopicInfo[] {siteT1, nodeT1})
|
for(TopicInfo topic : new TopicInfo[] {siteT1, nodeT1})
|
||||||
{
|
{
|
||||||
// Listing initially gives nothing
|
// 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");
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -31,8 +31,7 @@ import org.alfresco.repo.domain.node.NodeEntity;
|
|||||||
*/
|
*/
|
||||||
public class NodeWithTargetsEntity extends NodeBackedEntity
|
public class NodeWithTargetsEntity extends NodeBackedEntity
|
||||||
{
|
{
|
||||||
private List<Long> targetIds;
|
private List<TargetAndTypeId> targets;
|
||||||
private List<Long> targetAssocTypeIds;
|
|
||||||
|
|
||||||
// Supplemental query-related parameters
|
// Supplemental query-related parameters
|
||||||
private Long assocTypeId;
|
private Long assocTypeId;
|
||||||
@@ -53,24 +52,17 @@ public class NodeWithTargetsEntity extends NodeBackedEntity
|
|||||||
this.assocTypeId = assocTypeId;
|
this.assocTypeId = assocTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Long> getTargetIds()
|
/**
|
||||||
|
* @return Pairs of (Target Node, Assoc Type)
|
||||||
|
*/
|
||||||
|
public List<TargetAndTypeId> getTargetIds()
|
||||||
{
|
{
|
||||||
return targetIds;
|
return targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTargetIds(List<Long> targetIds)
|
public void setTargets(List<TargetAndTypeId> targets)
|
||||||
{
|
{
|
||||||
this.targetIds = targetIds;
|
this.targets = targets;
|
||||||
}
|
|
||||||
|
|
||||||
public List<Long> getTargetAssocTypeIds()
|
|
||||||
{
|
|
||||||
return targetAssocTypeIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTargetAssocTypeIds(List<Long> targetAssocTypeIds)
|
|
||||||
{
|
|
||||||
this.targetAssocTypeIds = targetAssocTypeIds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,4 +73,26 @@ public class NodeWithTargetsEntity extends NodeBackedEntity
|
|||||||
{
|
{
|
||||||
return assocTypeId;
|
return assocTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class TargetAndTypeId
|
||||||
|
{
|
||||||
|
private final Long targetId;
|
||||||
|
private final Long assocTypeId;
|
||||||
|
|
||||||
|
public TargetAndTypeId(Long targetId, Long assocTypeId)
|
||||||
|
{
|
||||||
|
this.targetId = targetId;
|
||||||
|
this.assocTypeId = assocTypeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getTargetId()
|
||||||
|
{
|
||||||
|
return targetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getAssocTypeId()
|
||||||
|
{
|
||||||
|
return assocTypeId;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user