From c81c8f59e86413040c4c0cfd58d372cba8970f04 Mon Sep 17 00:00:00 2001 From: Gavin Cornwell Date: Fri, 27 Jan 2006 15:43:49 +0000 Subject: [PATCH] Fixed issue where discussions were lost after checkin & updated version number git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2230 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/core-services-context.xml | 12 + .../alfresco/messages/coci-service.properties | 2 + config/alfresco/version.properties | 2 +- .../repo/forum/DiscussableAspect.java | 256 ++++++++++++++++++ 4 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 source/java/org/alfresco/repo/forum/DiscussableAspect.java diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml index 9e405227f8..09a7212a60 100644 --- a/config/alfresco/core-services-context.xml +++ b/config/alfresco/core-services-context.xml @@ -515,6 +515,18 @@ + + + + + + + + + + + + diff --git a/config/alfresco/messages/coci-service.properties b/config/alfresco/messages/coci-service.properties index 034bcbfd6f..6f57e97296 100644 --- a/config/alfresco/messages/coci-service.properties +++ b/config/alfresco/messages/coci-service.properties @@ -6,3 +6,5 @@ coci_service.err_not_owner=This user is not the owner of the working copy and ca coci_service.err_workingcopy_checkout=A working copy can not be checked out. coci_service.err_not_authenticated=Can not find the currently authenticated user details required by the CheckOutCheckIn service. coci_service.err_workingcopy_has_no_mimetype=Working copy node ({0}) has no mimetype + +coci_service.discussion_for={0} discussion \ No newline at end of file diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties index 695b488544..0306053284 100644 --- a/config/alfresco/version.properties +++ b/config/alfresco/version.properties @@ -7,7 +7,7 @@ version.major=1 version.minor=2 version.revision=0 -version.label=dev +version.label=RC1 # Edition label diff --git a/source/java/org/alfresco/repo/forum/DiscussableAspect.java b/source/java/org/alfresco/repo/forum/DiscussableAspect.java new file mode 100644 index 0000000000..b01fc9fed0 --- /dev/null +++ b/source/java/org/alfresco/repo/forum/DiscussableAspect.java @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.repo.forum; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.i18n.I18NUtil; +import org.alfresco.model.ContentModel; +import org.alfresco.model.ForumModel; +import org.alfresco.repo.policy.JavaBehaviour; +import org.alfresco.repo.policy.PolicyComponent; +import org.alfresco.repo.policy.PolicyScope; +import org.alfresco.service.cmr.coci.CheckOutCheckInServiceException; +import org.alfresco.service.cmr.model.FileExistsException; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileNotFoundException; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class DiscussableAspect +{ + private static final Log logger = LogFactory.getLog(DiscussableAspect.class); + + /** + * Policy component + */ + private PolicyComponent policyComponent; + + /** + * The node service + */ + private NodeService nodeService; + + /** + * The file folder service + */ + private FileFolderService fileFolderService; + + /** + * Sets the policy component + * + * @param policyComponent the policy component + */ + public void setPolicyComponent(PolicyComponent policyComponent) + { + this.policyComponent = policyComponent; + } + + /** + * Set the node service + * + * @param nodeService the node service + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * Set the file folder service + * + * @param fileFolderService the file folder service + */ + public void setFileFolderService(FileFolderService fileFolderService) + { + this.fileFolderService = fileFolderService; + } + + /** + * Initialise method + */ + public void init() + { + // Register copy behaviour for the discussable aspect + this.policyComponent.bindClassBehaviour( + QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyNode"), + ForumModel.ASPECT_DISCUSSABLE, + new JavaBehaviour(this, "onCopy")); + + this.policyComponent.bindClassBehaviour( + QName.createQName(NamespaceService.ALFRESCO_URI, "onCopyComplete"), + ForumModel.ASPECT_DISCUSSABLE, + new JavaBehaviour(this, "onCopyComplete")); + } + + /** + * onCopy policy behaviour + * + * @see org.alfresco.repo.copy.CopyServicePolicies.OnCopyNodePolicy#onCopyNode(QName, NodeRef, StoreRef, boolean, PolicyScope) + */ + public void onCopy( + QName sourceClassRef, + NodeRef sourceNodeRef, + StoreRef destinationStoreRef, + boolean copyToNewNode, + PolicyScope copyDetails) + { + // NOTE: we intentionally don't do anything in here, this stops the discussable + // aspect from being added to the new copied node - the behaviour we want. + } + + public void onCopyComplete( + QName classRef, + NodeRef sourceNodeRef, + NodeRef destinationRef, + boolean copyNewNode, + Map copyMap) + { + // if the copy is not a new node it is a checkin, we therefore + // need to copy any discussions from the working copy document + // to the document being checked in + if (copyNewNode == false) + { + List sourceChildren = this.nodeService.getChildAssocs(sourceNodeRef, + ForumModel.ASSOC_DISCUSSION, RegexQNamePattern.MATCH_ALL); + + if (sourceChildren.size() != 1) + { + throw new CheckOutCheckInServiceException( + "The source node has the discussable aspect but does not have 1 child, it has " + + sourceChildren.size() + " children!"); + } + + NodeRef sourceForum = sourceChildren.get(0).getChildRef(); + + // get the forum for the destination node, it's created if necessary + NodeRef destinationForum = getDestinationForum(destinationRef); + + // copy any topics from the source forum to the destination forum + int copied = 0; + List sourceForums = this.nodeService.getChildAssocs(sourceForum); + for (ChildAssociationRef childRef : sourceForums) + { + String topicName = null; + NodeRef childNode = childRef.getChildRef(); + if (this.nodeService.getType(childNode).equals(ForumModel.TYPE_TOPIC)) + { + try + { + // work out the name for the copied topic + String childName = this.nodeService.getProperty(childNode, + ContentModel.PROP_NAME).toString(); + Serializable labelProp = this.nodeService.getProperty(destinationRef, + ContentModel.PROP_VERSION_LABEL); + if (labelProp == null) + { + topicName = childName + " - " + new Date(); + } + else + { + topicName = childName + " (" + labelProp.toString() + ")"; + } + + this.fileFolderService.copy(childNode, destinationForum, topicName); + copied++; + } + catch (FileNotFoundException fnfe) + { + throw new CheckOutCheckInServiceException( + "Failed to copy topic from working copy to checked out content", fnfe); + } + catch (FileExistsException fee) + { + throw new CheckOutCheckInServiceException("Failed to checkin content as a topic called " + + topicName + " already exists on the checked out content", fee); + } + } + } + + if (logger.isDebugEnabled()) + logger.debug("Copied " + copied + " topics from the working copy to the checked out content"); + } + } + + /** + * Retrieves or creates the forum node for the given destination node + * + * @param destNodeRef The node to get the forum for + * @return NodeRef representing the forum + */ + private NodeRef getDestinationForum(NodeRef destNodeRef) + { + NodeRef destinationForum = null; + + if (this.nodeService.hasAspect(destNodeRef, ForumModel.ASPECT_DISCUSSABLE)) + { + List destChildren = this.nodeService.getChildAssocs(destNodeRef, + ForumModel.ASSOC_DISCUSSION, RegexQNamePattern.MATCH_ALL); + + if (destChildren.size() != 1) + { + throw new IllegalStateException("Locked node has the discussable aspect but does not have 1 child, it has " + + destChildren.size() + " children!"); + } + + destinationForum = destChildren.get(0).getChildRef(); + } + else + { + // create the forum - TODO: Move this to a repo discussion service so that it can + // be shared between here and the discussion wizard + + // add the discussable aspect + this.nodeService.addAspect(destNodeRef, ForumModel.ASPECT_DISCUSSABLE, null); + + // create a child forum space using the child association just introduced by + // adding the discussable aspect + String name = (String)this.nodeService.getProperty(destNodeRef, + ContentModel.PROP_NAME); + String forumName = I18NUtil.getMessage("coci_service.discussion_for", new Object[] {name}); + + Map forumProps = new HashMap(1); + forumProps.put(ContentModel.PROP_NAME, forumName); + + ChildAssociationRef childRef = this.nodeService.createNode(destNodeRef, + ForumModel.ASSOC_DISCUSSION, + QName.createQName(ForumModel.FORUMS_MODEL_URI, "discussion"), + ForumModel.TYPE_FORUM, forumProps); + + destinationForum = childRef.getChildRef(); + + // apply the uifacets aspect + Map uiFacetsProps = new HashMap(5); + uiFacetsProps.put(ContentModel.PROP_ICON, "forum_large"); + this.nodeService.addAspect(destinationForum, ContentModel.ASPECT_UIFACETS, uiFacetsProps); + } + + return destinationForum; + } +}