diff --git a/config/alfresco/web-client-application-context.xml b/config/alfresco/web-client-application-context.xml index cff44dd5eb..a8c050501c 100644 --- a/config/alfresco/web-client-application-context.xml +++ b/config/alfresco/web-client-application-context.xml @@ -10,6 +10,7 @@ classpath:alfresco/web-client-config-properties.xml classpath:alfresco/web-client-config-navigation.xml classpath:alfresco/web-client-config-actions.xml + classpath:alfresco/web-client-config-forum-actions.xml classpath:alfresco/extension/web-client-config-custom.xml diff --git a/config/alfresco/web-client-config-actions.xml b/config/alfresco/web-client-config-actions.xml index 36c07eb227..d534b859f0 100644 --- a/config/alfresco/web-client-config-actions.xml +++ b/config/alfresco/web-client-config-actions.xml @@ -80,8 +80,6 @@ cifs - org.alfresco.web.action.evaluator.CheckinDocEvaluator @@ -118,33 +116,6 @@ - - - - org.alfresco.web.action.evaluator.DiscussNodeEvaluator - discuss - /images/icons/forum-16.gif - #{ForumsBean.discuss} - - #{actionContext.id} - - - - - - - - CreateChildren - - org.alfresco.web.action.evaluator.CreateForumNodeEvaluator - start_discussion - /images/icons/create_forum.gif - #{CreateDiscussionDialog.startWizard} - - #{actionContext.id} - - - view_details @@ -459,7 +430,6 @@ - false @@ -470,11 +440,10 @@ - - @@ -506,7 +474,6 @@ inlineAction - @@ -515,7 +482,6 @@ - @@ -556,8 +522,6 @@ - - @@ -572,8 +536,6 @@ - - diff --git a/config/alfresco/web-client-config-forum-actions.xml b/config/alfresco/web-client-config-forum-actions.xml new file mode 100644 index 0000000000..0104d18534 --- /dev/null +++ b/config/alfresco/web-client-config-forum-actions.xml @@ -0,0 +1,142 @@ + + + + + + + + + org.alfresco.web.action.evaluator.ForumsCheckinDocEvaluator + checkin + /images/icons/CheckIn_icon.gif + #{CheckinCheckoutBean.setupContentAction} + checkinFile + + #{actionContext.id} + + + + + + org.alfresco.web.action.evaluator.DiscussNodeEvaluator + discuss + /images/icons/forum-16.gif + #{ForumsBean.discuss} + + #{actionContext.id} + + + + + + + CreateChildren + + org.alfresco.web.action.evaluator.CreateForumNodeEvaluator + start_discussion + /images/icons/create_forum.gif + #{CreateDiscussionDialog.startWizard} + + #{actionContext.id} + + + + + + + + + + + false + inlineAction + + + + + + + + + + + + + + + + + + + + + + + + + + + false + inlineAction + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index 26bb0345d8..27d219fe8c 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -116,9 +116,10 @@ + diff --git a/source/java/org/alfresco/web/action/evaluator/ForumsCheckinDocEvaluator.java b/source/java/org/alfresco/web/action/evaluator/ForumsCheckinDocEvaluator.java new file mode 100644 index 0000000000..2d510fe9d7 --- /dev/null +++ b/source/java/org/alfresco/web/action/evaluator/ForumsCheckinDocEvaluator.java @@ -0,0 +1,72 @@ +/* + * 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.web.action.evaluator; + +import javax.faces.context.FacesContext; + +import org.alfresco.model.ContentModel; +import org.alfresco.model.ForumModel; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.web.action.ActionEvaluator; +import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; + +/** + * UI Action Evaluator - Checkin a document with potentially a Forum attached. + * + * @author Kevin Roast + */ +public final class ForumsCheckinDocEvaluator implements ActionEvaluator +{ + /** + * @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node) + */ + public boolean evaluate(Node node) + { + boolean allow = false; + + if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY)) + { + if (node.hasAspect(ForumModel.ASPECT_DISCUSSABLE)) + { + NodeService nodeService = + Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService(); + + // get the original locked node (via the copiedfrom aspect) + NodeRef lockedNodeRef = (NodeRef)nodeService.getProperty(node.getNodeRef(), ContentModel.PROP_COPY_REFERENCE); + if (lockedNodeRef != null) + { + Node lockedNode = new Node(lockedNodeRef); + allow = (node.hasPermission(PermissionService.CHECK_IN) && + lockedNode.hasPermission(PermissionService.CONTRIBUTOR)); + } + } + else + { + // there is no discussion so just check they have checkin permission for the node + allow = node.hasPermission(PermissionService.CHECK_IN); + } + } + + return allow; + } +} +/* + +*/ \ No newline at end of file diff --git a/source/java/org/alfresco/web/bean/BrowseBean.java b/source/java/org/alfresco/web/bean/BrowseBean.java index e15f6d4ab3..a296fe6376 100644 --- a/source/java/org/alfresco/web/bean/BrowseBean.java +++ b/source/java/org/alfresco/web/bean/BrowseBean.java @@ -412,7 +412,8 @@ public class BrowseBean implements IContextListener * Setup the common properties required at data-binding time. *

* These are properties used by components on the page when iterating over the nodes. - * Information such as whether the node is locked, a working copy, download URL etc. + * The properties are available as the Node is a Map so they can be accessed directly + * by name. Information such as download URL, size and filetype are provided etc. *

* We use a set of anonymous inner classes to provide the implemention for the property * getters. The interfaces are only called when the properties are first requested. @@ -422,15 +423,10 @@ public class BrowseBean implements IContextListener public void setupCommonBindingProperties(Node node) { // special properties to be used by the value binding components on the page - node.addPropertyResolver("locked", this.resolverlocked); - node.addPropertyResolver("owner", this.resolverOwner); - node.addPropertyResolver("workingCopy", this.resolverWorkingCopy); node.addPropertyResolver("url", this.resolverUrl); node.addPropertyResolver("fileType16", this.resolverFileType16); node.addPropertyResolver("fileType32", this.resolverFileType32); node.addPropertyResolver("size", this.resolverSize); - node.addPropertyResolver("cancelCheckOut", this.resolverCancelCheckOut); - node.addPropertyResolver("checkIn", this.resolverCheckIn); node.addPropertyResolver("editLinkType", this.resolverEditLinkType); node.addPropertyResolver("webdavUrl", this.resolverWebdavUrl); node.addPropertyResolver("cifsPath", this.resolverCifsPath); @@ -775,36 +771,36 @@ public class BrowseBean implements IContextListener // ------------------------------------------------------------------------------ // Property Resolvers - public NodePropertyResolver resolverlocked = new NodePropertyResolver() { + /*public NodePropertyResolver resolverlocked = new NodePropertyResolver() { public Object get(Node node) { return node.isLocked(); } - }; + };*/ - public NodePropertyResolver resolverOwner = new NodePropertyResolver() { + /*public NodePropertyResolver resolverOwner = new NodePropertyResolver() { public Object get(Node node) { return getDocument().isWorkingCopyOwner(); } - }; + };*/ - public NodePropertyResolver resolverCancelCheckOut = new NodePropertyResolver() { + /*public NodePropertyResolver resolverCancelCheckOut = new NodePropertyResolver() { public Object get(Node node) { return node.hasAspect(ContentModel.ASPECT_WORKING_COPY) && node.hasPermission(PermissionService.CANCEL_CHECK_OUT); } - }; + };*/ - public NodePropertyResolver resolverCheckIn = new NodePropertyResolver() { + /*public NodePropertyResolver resolverCheckIn = new NodePropertyResolver() { public Object get(Node node) { return node.hasAspect(ContentModel.ASPECT_WORKING_COPY) && node.hasPermission(PermissionService.CHECK_IN); } - }; + };*/ - public NodePropertyResolver resolverWorkingCopy = new NodePropertyResolver() { + /*public NodePropertyResolver resolverWorkingCopy = new NodePropertyResolver() { public Object get(Node node) { return node.hasAspect(ContentModel.ASPECT_WORKING_COPY); } - }; + };*/ public NodePropertyResolver resolverDownload = new NodePropertyResolver() { public Object get(Node node) { return DownloadContentServlet.generateDownloadURL(node.getNodeRef(), node.getName()); @@ -1152,8 +1148,6 @@ public class BrowseBean implements IContextListener node.addPropertyResolver("fileType32", this.resolverFileType32); node.addPropertyResolver("mimetype", this.resolverMimetype); node.addPropertyResolver("size", this.resolverSize); - node.addPropertyResolver("cancelCheckOut", this.resolverCancelCheckOut); - node.addPropertyResolver("checkIn", this.resolverCheckIn); for (NodeEventListener listener : getNodeEventListeners()) { diff --git a/source/java/org/alfresco/web/bean/ForumsBean.java b/source/java/org/alfresco/web/bean/ForumsBean.java index f650fa8ee2..fa1507655a 100644 --- a/source/java/org/alfresco/web/bean/ForumsBean.java +++ b/source/java/org/alfresco/web/bean/ForumsBean.java @@ -47,7 +47,6 @@ import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.search.QueryParameterDefinition; import org.alfresco.service.cmr.search.SearchService; -import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; @@ -74,7 +73,7 @@ import org.apache.commons.logging.LogFactory; * * @author gavinc */ -public class ForumsBean implements IContextListener, NodeEventListener +public class ForumsBean implements IContextListener { private static Log logger = LogFactory.getLog(ForumsBean.class); private static final String PAGE_NAME_FORUMS = "forums"; @@ -594,25 +593,6 @@ public class ForumsBean implements IContextListener, NodeEventListener } - // ------------------------------------------------------------------------------ - // NodeEventListener implementation - - /** - * @see org.alfresco.web.bean.NodeEventListener#created(org.alfresco.web.bean.repository.Node, org.alfresco.service.namespace.QName) - */ - public void created(Node node, QName type) - { - // override the checkin resolver if appropriate - if (node.containsPropertyResolver("checkIn") == true) - { - node.addPropertyResolver("checkIn", this.resolverCheckIn); - } - - // add the forums specific action resolver - node.addPropertyResolver("beingDiscussed", this.resolverBeingDiscussed); - } - - // ------------------------------------------------------------------------------ // Navigation action event handlers @@ -872,44 +852,6 @@ public class ForumsBean implements IContextListener, NodeEventListener // ------------------------------------------------------------------------------ // Property Resolvers - public NodePropertyResolver resolverCheckIn = new NodePropertyResolver() { - public Object get(Node node) - { - boolean canCheckin = false; - - // if the working copy has a discussion the user will also need to have - // contributor permission on the locked node - if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY)) - { - if (node.hasAspect(ForumModel.ASPECT_DISCUSSABLE)) - { - // get the original locked node (via the copiedfrom aspect) - NodeRef lockedNodeRef = (NodeRef)nodeService.getProperty(node.getNodeRef(), ContentModel.PROP_COPY_REFERENCE); - if (lockedNodeRef != null) - { - Node lockedNode = new Node(lockedNodeRef); - canCheckin = node.hasPermission(PermissionService.CHECK_IN) && - lockedNode.hasPermission(PermissionService.CONTRIBUTOR); - } - } - else - { - // there is no discussion so just check they have checkin permission - // for the node - canCheckin = node.hasPermission(PermissionService.CHECK_IN); - } - } - - return canCheckin; - } - }; - - public NodePropertyResolver resolverBeingDiscussed = new NodePropertyResolver() { - public Object get(Node node) { - return node.hasAspect(ForumModel.ASPECT_DISCUSSABLE); - } - }; - public NodePropertyResolver resolverReplies = new NodePropertyResolver() { public Object get(Node node) { @@ -942,7 +884,6 @@ public class ForumsBean implements IContextListener, NodeEventListener // get the content property from the node and retrieve the // full content as a string (obviously should only be used // for small amounts of content) - ContentReader reader = contentService.getReader(node.getNodeRef(), ContentModel.PROP_CONTENT); @@ -960,7 +901,6 @@ public class ForumsBean implements IContextListener, NodeEventListener { // determine if this node is a reply to another post, if so find // the creator of the original poster - String replyTo = null; List assocs = nodeService.getTargetAssocs(node.getNodeRef(), diff --git a/source/java/org/alfresco/web/config/ActionsConfigElement.java b/source/java/org/alfresco/web/config/ActionsConfigElement.java index 6ef546ffeb..d880982405 100644 --- a/source/java/org/alfresco/web/config/ActionsConfigElement.java +++ b/source/java/org/alfresco/web/config/ActionsConfigElement.java @@ -20,8 +20,10 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.alfresco.config.ConfigElement; import org.alfresco.config.ConfigException; @@ -78,11 +80,6 @@ public class ActionsConfigElement extends ConfigElementAdapter combinedElement.actionGroups.putAll(this.actionGroups); combinedElement.actionGroups.putAll(existingElement.actionGroups); - // - // TODO: do we need to check all groups here and update ActionDefinition references incase they - // have changed? e.g. if an actiondef ID is overriden, a group using it will not know! - // - return combinedElement; } @@ -170,7 +167,7 @@ public class ActionsConfigElement extends ConfigElementAdapter return params; } - private String id; + String id; private List permissionAllow = null; private List permissionDeny = null; private Map params = null; @@ -197,7 +194,7 @@ public class ActionsConfigElement extends ConfigElementAdapter * * @author Kevin Roast */ - public static class ActionGroup implements Iterable + public static class ActionGroup implements Iterable { public ActionGroup(String id) { @@ -213,24 +210,24 @@ public class ActionsConfigElement extends ConfigElementAdapter return id; } - public void addAction(ActionDefinition actionDef) + public void addAction(String actionId) { - actions.put(actionDef.getId(), actionDef); + actions.add(actionId); } /** - * @return Iterator to the ActionDefinition objects referenced by this group + * @return Iterator over the ActionDefinition IDs referenced by this group */ - public Iterator iterator() + public Iterator iterator() { - return actions.values().iterator(); + return actions.iterator(); } private String id; - /** the action definitions, we use a linked hashmap to ensure we do not have more + /** the action definitions, we use a Linked HashSet to ensure we do not have more than one action with the same Id and that the insertion order is preserved */ - private Map actions = new LinkedHashMap(8, 1.0f); + private Set actions = new LinkedHashSet(16, 1.0f); public boolean ShowLink; public String Style; diff --git a/source/java/org/alfresco/web/config/ActionsElementReader.java b/source/java/org/alfresco/web/config/ActionsElementReader.java index 8824eb4514..8533270d36 100644 --- a/source/java/org/alfresco/web/config/ActionsElementReader.java +++ b/source/java/org/alfresco/web/config/ActionsElementReader.java @@ -107,30 +107,24 @@ public class ActionsElementReader implements ConfigElementReader Element actionRefElement = actionRefItr.next(); // look for an action referred to be Id - this is the common use-case - ActionDefinition def = null; String idRef = actionRefElement.attributeValue(ATTRIBUTE_IDREF); - if (idRef != null && idRef.length() != 0) - { - // try to find the referenced action by Id - def = configElement.getActionDefinition(idRef); - if (def == null) - { - throw new ConfigException("Action group '" + groupId + - "' cannot find action definition referenced by '" + idRef + "'"); - } - } - else + if (idRef == null || idRef.length() == 0) { // look for an action defined directly rather than referenced by Id String id = actionRefElement.attributeValue(ATTRIBUTE_ID); if (id != null && id.length() != 0) { - def = parseActionDefinition(actionRefElement); + ActionDefinition def = parseActionDefinition(actionRefElement); + // override action definition ID based on the group name to avoid conflicts + def.id = actionGroup.getId() + '_' + def.getId(); + configElement.addActionDefinition(def); + actionGroup.addAction(def.getId()); } } - if (def != null) + else { - actionGroup.addAction(def); + // add the action definition ID to the group + actionGroup.addAction(idRef); } } diff --git a/source/java/org/alfresco/web/ui/repo/component/UIActions.java b/source/java/org/alfresco/web/ui/repo/component/UIActions.java index eda8b1c040..cf2b87f191 100644 --- a/source/java/org/alfresco/web/ui/repo/component/UIActions.java +++ b/source/java/org/alfresco/web/ui/repo/component/UIActions.java @@ -30,6 +30,7 @@ import javax.faces.context.ResponseWriter; import javax.faces.el.ValueBinding; import org.alfresco.config.Config; +import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.config.ActionsConfigElement; @@ -149,7 +150,7 @@ public class UIActions extends SelfRenderingComponent // render the action group component tree if (logger.isDebugEnabled()) logger.debug("-constructing ActionGroup: " + groupId); - buildActionGroup(context, actionGroup); + buildActionGroup(context, actionConfig, actionGroup); } else { @@ -221,7 +222,7 @@ public class UIActions extends SelfRenderingComponent * @param context * @param actionGroup */ - private void buildActionGroup(FacesContext context, ActionGroup actionGroup) + private void buildActionGroup(FacesContext context, ActionsConfigElement config, ActionGroup actionGroup) throws IOException { javax.faces.application.Application facesApp = context.getApplication(); @@ -238,10 +239,16 @@ public class UIActions extends SelfRenderingComponent } // process each ActionDefinition in the order they were defined - for (ActionDefinition actionDef : actionGroup) + for (String actionId : actionGroup) { if (logger.isDebugEnabled()) - logger.debug("---processing ActionDefinition: " + actionDef.getId()); + logger.debug("---processing ActionDefinition: " + actionId); + + ActionDefinition actionDef = config.getActionDefinition(actionId); + if (actionDef == null) + { + throw new AlfrescoRuntimeException("Unable to find configured ActionDefinition Id: " + actionId); + } UIComponent currentParent = this; @@ -433,7 +440,7 @@ public class UIActions extends SelfRenderingComponent } if (logger.isDebugEnabled()) - logger.debug("-----adding UIActionLink component for: " + actionDef.getId()); + logger.debug("-----adding UIActionLink component for: " + actionId); currentParent.getChildren().add(control); } }