View Javadoc

1   /**
2    * This file Copyright (c) 2003-2010 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.workflow;
35  
36  import info.magnolia.cms.security.Security;
37  import info.magnolia.cms.security.User;
38  import info.magnolia.context.Context;
39  import info.magnolia.context.MgnlContext;
40  import info.magnolia.module.workflow.flows.FlowDefinitionException;
41  import info.magnolia.module.workflow.flows.FlowDefinitionManager;
42  import info.magnolia.module.workflow.jcr.JCRPersistedEngine;
43  import info.magnolia.module.workflow.jcr.JCRWorkItemStore;
44  import openwfe.org.engine.expressions.FlowExpressionId;
45  import openwfe.org.engine.workitem.InFlowItem;
46  import openwfe.org.engine.workitem.InFlowWorkItem;
47  import openwfe.org.engine.workitem.LaunchItem;
48  import openwfe.org.engine.workitem.StringAttribute;
49  import openwfe.org.worklist.store.StoreException;
50  import org.apache.commons.lang.StringUtils;
51  import org.slf4j.Logger;
52  import org.slf4j.LoggerFactory;
53  
54  import java.util.Collection;
55  import java.util.Iterator;
56  import java.util.List;
57  
58  
59  /**
60   * Util to use the mangoila workflow module. Methods to launch and proceed.
61   * @author jackie
62   */
63  public class WorkflowUtil {
64  
65      final static public StringAttribute ATTRIBUTE_TRUE = new StringAttribute("true");
66  
67      final static public StringAttribute ATTRIBUTE_FALSE = new StringAttribute("false");
68  
69      private final static Logger log = LoggerFactory.getLogger(WorkflowUtil.class.getName());
70  
71      /**
72       * Util: don't instantiate
73       */
74      private WorkflowUtil() {
75      }
76  
77      public static JCRWorkItemStore getWorkItemStore(){
78          return WorkflowModule.getWorkItemStore();
79      }
80  
81      public static void launchFlow(LaunchItem li) {
82          try {
83              JCRPersistedEngine engine = WorkflowModule.getEngine();
84              // Launch the item
85              engine.launch(li, true);
86          }
87          catch (Exception e) {
88              log.error("Launching flow failed", e);
89          }
90      }
91  
92      /**
93       * Simply launch a flow for the specified node
94       */
95      public static void launchFlow(String repository, String path, String flowName) throws Exception {
96          try {
97              // Get the references
98              LaunchItem li = new LaunchItem();
99  
100             // start activation
101             if (repository != null) {
102                 li.addAttribute(Context.ATTRIBUTE_REPOSITORY, new StringAttribute(repository));
103             }
104             if (path != null) {
105                 li.addAttribute(Context.ATTRIBUTE_PATH, new StringAttribute(path));
106             }
107             launchFlow(li, flowName);
108             // Launch the item
109         }
110         catch (Exception e) {
111             log.error("Launching flow " + flowName + " failed", e);
112         }
113     }
114 
115     /**
116      * Start a flow
117      * @param li the prepared lunchItem
118      * @param flowName the flow to start
119      * @throws FlowDefinitionException
120      */
121     public static void launchFlow(LaunchItem li, String flowName) throws FlowDefinitionException {
122         FlowDefinitionManager configurator = WorkflowModule.getFlowDefinitionManager();
123 
124         configurator.configure(li, flowName);
125 
126         launchFlow(li);
127     }
128 
129     /**
130      * @param id
131      */
132     public static void proceed(String id) {
133         proceed(id, WorkflowConstants.ACTION_PROCEED);
134     }
135 
136     public static void proceed(String id, String action) {
137         proceed(id, action, null);
138     }
139 
140     public static void proceed(String id, String action, String comment) {
141         InFlowWorkItem wi = getWorkItem(id);
142         if (wi == null) {
143             log.error("can't proceed workitem [{}]", id);
144             return;
145         }
146         wi.touch();
147         // remove old exception
148         if(wi.containsAttribute(Context.ATTRIBUTE_EXCEPTION)){
149             wi.removeAttribute(Context.ATTRIBUTE_EXCEPTION);
150         }
151         if(wi.containsAttribute(Context.ATTRIBUTE_MESSAGE)){
152             wi.removeAttribute(Context.ATTRIBUTE_MESSAGE);
153         }
154         wi.getAttributes().puts(WorkflowConstants.ATTRIBUTE_ACTION, action);
155         wi.getAttributes().puts(WorkflowConstants.ATTRIBUTE_USERNAME, MgnlContext.getUser().getName());
156 
157         if (StringUtils.isNotEmpty(comment)) {
158             wi.getAttributes().puts(Context.ATTRIBUTE_COMMENT, comment);
159         }
160         proceed(wi);
161     }
162 
163     public static void reject(String id, String comment) {
164         proceed(id, WorkflowConstants.ACTION_REJECT, comment);
165     }
166 
167     public static void cancel(String id, String comment) {
168         proceed(id, WorkflowConstants.ACTION_CANCEL, comment);
169     }
170 
171     /**
172      * Proceed this item
173      * @param wi
174      */
175     public static void proceed(InFlowWorkItem wi) {
176         try {
177             WorkflowModule.getEngine().reply(wi);
178         }
179         catch (Exception e) {
180             log.error("Error while accessing the workflow engine", e);
181         }
182         finally {
183             removeWorkItem(wi);
184         }
185     }
186 
187     /**
188      * @param id identifier for the workitem as stored in the engine
189      * @return <code>InFlowWorkItem</code> corresponding to the workitem
190      */
191     public static InFlowWorkItem getWorkItem(String id) {
192         InFlowWorkItem wi = null;
193         try {
194             wi = getWorkItemStore().retrieveWorkItem(StringUtils.EMPTY, FlowExpressionId.fromParseableString(id));
195         }
196         catch (StoreException e) {
197             log.error("can't get the workitem by expression [" + id + "]", e);
198         }
199         return wi;
200     }
201 
202     public static String getPath(String id){
203         return getWorkItemStore().createPathFromId(FlowExpressionId.fromParseableString(id));
204     }
205 
206     /**
207      * get all work items for the user
208      */
209     public static List getWorkItems(String userName) throws Exception {
210         if (log.isDebugEnabled()) {
211             log.debug("enter getWorkItems");
212             log.debug("user name = " + userName);
213         }
214 
215         long start = System.currentTimeMillis();
216 
217         User user = Security.getUserManager().getUser(userName);
218         Collection groups = user.getAllGroups();
219         Collection roles = user.getAllRoles();
220 
221         StringBuffer queryString = new StringBuffer();
222         queryString.append("//*[(@assignTo=\"");
223         queryString.append(userName);
224         queryString.append("\") or (@participant=\""+WorkflowConstants.PARTICIPANT_PREFIX_USER);
225         queryString.append(userName);
226         queryString.append("\" and not(@assignTo))");
227         for (Iterator iter = groups.iterator(); iter.hasNext();) {
228             Object group = iter.next();
229             queryString.append(" or (@participant=\""+WorkflowConstants.PARTICIPANT_PREFIX_GROUP);
230             queryString.append(group);
231             // FIXME
232             // queryString.append("\" and @assignTo!=\"");
233             // queryString.append(userName);
234             queryString.append("\") ");
235         }
236         for (Iterator iter = roles.iterator(); iter.hasNext();) {
237             Object role = iter.next();
238             // FIXME
239             queryString.append(" or (@participant=\""+WorkflowConstants.PARTICIPANT_PREFIX_ROLE);
240             queryString.append(role);
241             // queryString.append("\" and @assignTo!=\"");
242             // queryString.append(userName);
243             queryString.append("\") ");
244         }
245         queryString.append("]");
246 
247         if (log.isDebugEnabled()) {
248             log.info("xpath query string = " + queryString);
249         }
250 
251         final List doQuery = getWorkItemStore().doQuery(queryString.toString());
252         long end = System.currentTimeMillis();
253         log.debug("Retrieving workitems done. (Took " + (end - start) + " ms)");
254         return doQuery;
255     }
256 
257     public static String getId(InFlowItem wi) {
258         return wi.getId().toParseableString();
259     }
260 
261     /**
262      * assign work item to a user, if userName = "", then assignment for the workItem will be deleted
263      */
264     public static void assignWorkItemToUser(String id, String userName) {
265         if (id == null || id.length() == 0) {
266             log.error("can not assign work item, invalid express id " + id);
267             return;
268         }
269 
270         if (userName == null) {
271             log.info("User name was null");
272             return;
273         }
274 
275         InFlowWorkItem wi = getWorkItem(id);
276         if (wi == null) {
277             log.error("can not assign work item, can not retrieve work tiem by  express id " + id);
278             return;
279         }
280         assignWorkItemToUser(wi, userName);
281     }
282 
283     /**
284      * assign work item to a user, if userName = "", then assignment for the workItem will be deleted
285      */
286     public static void assignWorkItemToUser(InFlowWorkItem wi, String userName) {
287         if (userName == null) {
288             log.info("User name was null");
289             return;
290         }
291 
292         try {
293             wi.addAttribute(WorkflowConstants.ATTRIBUTE_ASSIGN_TO, new StringAttribute(userName));
294             getWorkItemStore().storeWorkItem(StringUtils.EMPTY, wi);
295         }
296         catch (Exception e) {
297             log.error("assign work item to user " + userName + " failed.)", e);
298         }
299 
300     }
301 
302     /**
303      * return a list of workItem for one usre
304      */
305     public static List getUserInbox(String userName) throws Exception {
306         return getWorkItems(userName);
307     }
308 
309     /**
310      * return a list of workItem for one group
311      */
312     public static List getGroupInbox(String GroupName) throws Exception {
313         if (log.isDebugEnabled()) {
314             log.debug("enter getGroupInbox");
315             log.debug("GroupName = " + GroupName);
316         }
317 
318         StringBuffer queryString = new StringBuffer();
319         queryString.append("//*[@participant=\""+WorkflowConstants.PARTICIPANT_PREFIX_GROUP);
320         queryString.append(GroupName);
321         queryString.append("\"]");
322 
323         if (log.isDebugEnabled()) {
324             log.debug("xpath query string = " + queryString);
325         }
326         return getWorkItemStore().doQuery(queryString.toString());
327 
328     }
329 
330     /**
331      * return a list of workItem for one role
332      */
333     public static List getRoleInbox(String roleName) throws Exception {
334         if (log.isDebugEnabled()) {
335             log.debug("enter getGroupInbox");
336             log.debug("roleName = " + roleName);
337         }
338 
339         StringBuffer queryString = new StringBuffer();
340         queryString.append("//*[@participant=\""+WorkflowConstants.PARTICIPANT_PREFIX_GROUP);
341         queryString.append(roleName);
342         queryString.append("\"]");
343 
344         if (log.isDebugEnabled()) {
345             log.debug("xpath query string = " + queryString);
346         }
347         return getWorkItemStore().doQuery(queryString.toString());
348     }
349 
350     /**
351      * remove one work item by id
352      */
353     private static void removeWorkItem(InFlowWorkItem wi) {
354         try {
355             getWorkItemStore().removeWorkItem(wi.getId());
356         }
357         catch (StoreException e) {
358             log.error("can't remove workitem", e);
359         }
360     }
361 
362 }