View Javadoc

1   /*******************************************************************************
2    *  Imixs Workflow 
3    *  Copyright (C) 2001, 2011 Imixs Software Solutions GmbH,  
4    *  http://www.imixs.com
5    *  
6    *  This program is free software; you can redistribute it and/or 
7    *  modify it under the terms of the GNU General Public License 
8    *  as published by the Free Software Foundation; either version 2 
9    *  of the License, or (at your option) any later version.
10   *  
11   *  This program is distributed in the hope that it will be useful, 
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
14   *  General Public License for more details.
15   *  
16   *  You can receive a copy of the GNU General Public
17   *  License at http://www.gnu.org/licenses/gpl.html
18   *  
19   *  Project: 
20   *  	http://www.imixs.org
21   *  	http://java.net/projects/imixs-workflow
22   *  
23   *  Contributors:  
24   *  	Imixs Software Solutions GmbH - initial API and implementation
25   *  	Ralph Soika - Software Developer
26   *******************************************************************************/
27  
28  package org.imixs.workflow.jee.faces;
29  
30  import java.text.MessageFormat;
31  import java.util.ArrayList;
32  import java.util.Collection;
33  import java.util.List;
34  import java.util.Locale;
35  import java.util.ResourceBundle;
36  
37  import javax.ejb.EJB;
38  import javax.faces.application.FacesMessage;
39  import javax.faces.component.UIComponent;
40  import javax.faces.component.UIData;
41  import javax.faces.component.UIParameter;
42  import javax.faces.context.ExternalContext;
43  import javax.faces.context.FacesContext;
44  import javax.faces.event.ActionEvent;
45  
46  import org.imixs.workflow.ItemCollection;
47  import org.imixs.workflow.jee.ejb.WorkflowService;
48  
49  /**
50   * This Class is an abstract controller used in JSF Application A JSF Web Modul
51   * should subclass the AbstractWorkflowController for implementing a project
52   * specific Imixs Workflow BackingBean
53   * 
54   * 
55   * @author rsoika
56   * @version 0.0.1
57   */
58  public abstract class AbstractWorkflowController {
59  	protected ItemCollection workitemItemCollection = null;
60  
61  	private String type;
62  
63  	/* Workflow Model */
64  	private List<ItemCollection> activityList;
65  	private List<ItemCollection> startProcessList = null;
66  	private String modelVersion = null;
67  
68  	/* Worklist and Search */
69  	private List<ItemCollection> workitems = null;
70  	private int maxSearchResult = 10;
71  	private int row = 0;
72  	private boolean endOfList = false;
73  	private int queryType = 0;
74  	private String searchQuery = null;
75  	final int QUERY_WORKLIST_BY_OWNER = 0;
76  	final int QUERY_WORKLIST_BY_CREATOR = 1;
77  	final int QUERY_WORKLIST_BY_AUTHOR = 2;
78  	final int QUERY_WORKLIST_ALL = 3;
79  	final int QUERY_WORKLIST_ARCHIVE = 4;
80  	final int QUERY_SEARCH = 5;
81  	final int QUERY_WORKLIST_BY_WRITEACCESS = 6;
82  	private int sortOrder = WorkflowService.SORT_ORDER_CREATED_DESC;
83  	// private String accessRoles = null;
84  
85  	// EJBs
86  
87  	@EJB
88  	private org.imixs.workflow.jee.ejb.EntityService entityService;
89  
90  	@EJB
91  	private org.imixs.workflow.jee.ejb.ModelService modelService;
92  
93  	@EJB
94  	private org.imixs.workflow.jee.ejb.WorkflowService workflowService;
95  
96  	public AbstractWorkflowController() {
97  		super();
98  		setType("workitem");
99  		workitemItemCollection = new ItemCollection();
100 
101 	}
102 
103 	/**
104 	 * returns an instance of the EntityService EJB
105 	 * 
106 	 * @return
107 	 */
108 	public org.imixs.workflow.jee.ejb.EntityService getEntityService() {
109 		return entityService;
110 	}
111 
112 	/**
113 	 * returns an instance of the ModelService EJB
114 	 * 
115 	 * @return
116 	 */
117 	public org.imixs.workflow.jee.ejb.ModelService getModelService() {
118 		return modelService;
119 	}
120 
121 	/**
122 	 * returns an instance of the WorkflowService EJB
123 	 * 
124 	 * @return
125 	 */
126 	public org.imixs.workflow.jee.ejb.WorkflowService getWorkflowService() {
127 		return workflowService;
128 	}
129 
130 	/**
131 	 * returns the $uniqueID of the current workitem
132 	 * 
133 	 * @return
134 	 */
135 	public String getID() {
136 		if (workitemItemCollection == null)
137 			return null;
138 		else
139 			return workitemItemCollection.getItemValueString("$uniqueid");
140 	}
141 
142 	/**
143 	 * set the value for the attribute 'type' of a workitem to be generated or
144 	 * search by this controller
145 	 */
146 	public String getType() {
147 		return type;
148 	}
149 
150 	/**
151 	 * defines the type attribute of a workitem to be generated or search by
152 	 * this controller
153 	 * 
154 	 * Subclasses may overwrite the type
155 	 * 
156 	 * @param type
157 	 */
158 	public void setType(String type) {
159 		this.type = type;
160 	}
161 
162 	/**
163 	 * defines the default sortOrder for finder methods
164 	 * 
165 	 * @return
166 	 */
167 	public int getSortOrder() {
168 		return sortOrder;
169 	}
170 
171 	public void setSortOrder(int sortOrder) {
172 		this.sortOrder = sortOrder;
173 	}
174 
175 	/**
176 	 * returns the current ModelVersion. If no ModelVersion is defined the
177 	 * method returns the latest modelversion defined
178 	 * 
179 	 * @return
180 	 */
181 	public String getModelVersion() {
182 		if (modelVersion == null) {
183 			try {
184 				modelVersion = modelService.getLatestVersion();
185 			} catch (Exception e) {
186 				e.printStackTrace();
187 				return null;
188 			}
189 		}
190 		return modelVersion;
191 	}
192 
193 	public void setModelVersion(String modelVersion) {
194 		this.modelVersion = modelVersion;
195 	}
196 
197 	/**
198 	 * returns the maximum size of a search result
199 	 * 
200 	 * @return
201 	 */
202 	public int getMaxSearchResult() {
203 		return maxSearchResult;
204 	}
205 
206 	/**
207 	 * set the maximum size of a search result
208 	 * 
209 	 * @param searchCount
210 	 */
211 	public void setMaxSearchResult(int searchCount) {
212 		this.maxSearchResult = searchCount;
213 	}
214 
215 	/**
216 	 * defines the searchQuery to be use for a EQL search by the method
217 	 * doSwitchToSearchlist
218 	 * 
219 	 * Sublcasses may overwrite this method to define individual search queries.
220 	 * 
221 	 * @return
222 	 */
223 	public String getSearchQuery() {
224 		return searchQuery;
225 	}
226 
227 	/**
228 	 * set the current searchquery
229 	 * 
230 	 * @param query
231 	 */
232 	public void setSearchQuery(String query) {
233 		this.searchQuery = query;
234 	}
235 
236 	/**
237 	 * provides a list of writeaccess roles. Roles can be set by a
238 	 * managed-property tag
239 	 * 
240 	 * @return
241 	 */
242 	/*
243 	 * public String getAccessRoles() { return accessRoles; }
244 	 * 
245 	 * public void setAccessRoles(String accessRoles) { this.accessRoles =
246 	 * accessRoles; }
247 	 */
248 
249 	/**
250 	 * updates all attributes by the supported map into the ItemCollection
251 	 * 
252 	 * Diese Mehtode wird beim Klick auf einen Datensatz aufgerufen
253 	 * 
254 	 * @param ateam
255 	 */
256 	public void setWorkitem(ItemCollection aworkitem) {
257 		if (aworkitem != null)
258 			workitemItemCollection = aworkitem;
259 		else
260 			workitemItemCollection = new ItemCollection();
261 
262 	}
263 
264 	public ItemCollection getWorkitem() {
265 		return workitemItemCollection;
266 	}
267 
268 	/**
269 	 * This method is called by a jsf page to create a new instance of a
270 	 * process.
271 	 * 
272 	 * This method creates an empty worktitem
273 	 * 
274 	 * The Workflow attributes ProcessID, Modelversion and WorfklowGroup will be
275 	 * set to the attributes of the corresponding ProcessEntity provided by
276 	 * param ID in the ActionEvent
277 	 * 
278 	 * The Method expects an ID which identifies the ProcessID and optional a
279 	 * ModelVersion The ID is a String value with the following format:
280 	 * 
281 	 * 
282 	 * modelversion|processID
283 	 * 
284 	 * The first Part is the modelversion for the corresponding workflowmodel
285 	 * the second part will be vast to an integer which corresponds to the start
286 	 * process id in the model. The modelversion part with the '|' is optional.
287 	 * 
288 	 * @see WorkitemServiceBean
289 	 * 
290 	 * @param event
291 	 * @return
292 	 */
293 	public void doCreateWorkitem(ActionEvent event) throws Exception {
294 		// get Process ID out from the ActionEvent Object....
295 		List children = event.getComponent().getChildren();
296 		String processEntityIdentifier = "";
297 
298 		for (int i = 0; i < children.size(); i++) {
299 			if (children.get(i) instanceof UIParameter) {
300 				UIParameter currentParam = (UIParameter) children.get(i);
301 				if (currentParam.getName().equals("id")
302 						&& currentParam.getValue() != null) {
303 					processEntityIdentifier = currentParam.getValue()
304 							.toString();
305 					break;
306 				}
307 			}
308 		}
309 
310 		if (processEntityIdentifier != null
311 				&& !"".equals(processEntityIdentifier)) {
312 			// find ProcessEntity the Worktiem should be started at
313 			String sProcessModelVersion = null;
314 			String sProcessID = processEntityIdentifier;
315 
316 			// check if modelversion is provided (format: version|id)...
317 			if (processEntityIdentifier.indexOf('|') > -1) {
318 				// yes - extract modelversion from process id
319 				sProcessModelVersion = processEntityIdentifier.substring(0,
320 						processEntityIdentifier.indexOf('|'));
321 				sProcessID = processEntityIdentifier
322 						.substring(processEntityIdentifier.indexOf('|') + 1);
323 
324 				// update ModelVersion
325 				this.setModelVersion(sProcessModelVersion);
326 			}
327 
328 			// create new Workitem
329 			workitemItemCollection = createWorkitem(sProcessModelVersion,
330 					Integer.parseInt(sProcessID));
331 		} else {
332 			// no processid specified - create simple workitem
333 			workitemItemCollection = new ItemCollection();
334 			FacesContext context = FacesContext.getCurrentInstance();
335 			ExternalContext externalContext = context.getExternalContext();
336 			String sUser = externalContext.getRemoteUser();
337 			workitemItemCollection.replaceItemValue("namCreator", sUser);
338 			workitemItemCollection.replaceItemValue("type", getType());
339 
340 		}
341 
342 		// update the ItemCollectionAdapter...
343 		this.setWorkitem(workitemItemCollection);
344 	}
345 
346 	/**
347 	 * This method is called by a jsf page to create a new instance of a
348 	 * process.
349 	 * 
350 	 * This method creates an empty worktitem for a defined ProcessID in the
351 	 * current ModelVersion.
352 	 * 
353 	 * The Workflow attributes ProcessID, Modelversion and WorfklowGroup will be
354 	 * set to the attributes of the corresponding ProcessEntity provided by
355 	 * param ID in the ActionEvent
356 	 * 
357 	 * @param event
358 	 * @return
359 	 */
360 	public ItemCollection createWorkitem(String sModelVersion, int ProcessID)
361 			throws Exception {
362 		ItemCollection itemColProcessEntity = null;
363 		ItemCollection aWorkitem;
364 
365 		try {
366 			if (sModelVersion == null)
367 				sModelVersion = this.getModelVersion();
368 			else
369 				// update model version
370 				setModelVersion(sModelVersion);
371 			// find ProcessEntity
372 			itemColProcessEntity = modelService.getProcessEntityByVersion(
373 					ProcessID, sModelVersion);
374 
375 			// ProcessEntity found?
376 			if (itemColProcessEntity == null)
377 				throw new NullPointerException();
378 		} catch (Exception eproc) {
379 			throw new Exception(
380 					"unable to find ProcessEntity in model version "
381 							+ sModelVersion + " for ID=" + ProcessID);
382 		}
383 
384 		String sEditorID = itemColProcessEntity
385 				.getItemValueString("txteditorid");
386 		int processID = itemColProcessEntity
387 				.getItemValueInteger("numProcessID");
388 		String sWorkflowGroup = itemColProcessEntity
389 				.getItemValueString("txtworkflowgroup");
390 
391 		// Create new empty workitem
392 		aWorkitem = new ItemCollection();
393 		aWorkitem.replaceItemValue("$ProcessID", new Integer(processID));
394 		FacesContext context = FacesContext.getCurrentInstance();
395 		ExternalContext externalContext = context.getExternalContext();
396 		String sUser = externalContext.getRemoteUser();
397 
398 		aWorkitem.replaceItemValue("namCreator", sUser);
399 		aWorkitem.replaceItemValue("$WriteAccess", sUser);
400 
401 		// assigen ModelVersion, group and editor
402 		aWorkitem.replaceItemValue("$modelversion", this.getModelVersion());
403 		aWorkitem.replaceItemValue("txtworkflowgroup", sWorkflowGroup);
404 		aWorkitem.replaceItemValue("txteditorid", sEditorID);
405 
406 		aWorkitem.replaceItemValue("type", getType());
407 
408 		// update the ItemCollectionAdapter...
409 
410 		return aWorkitem;
411 
412 		// this.setWorkitem(workitemItemCollection);
413 
414 	}
415 
416 	/**
417 	 * processes the current issue. The method expects an parameter "id" with
418 	 * the activity ID which should be processed
419 	 * 
420 	 * Method should be overwritten to add additional Business logic here.
421 	 * 
422 	 * @param event
423 	 * @return
424 	 * @throws Exception
425 	 */
426 	public void doProcessWorkitem(ActionEvent event) throws Exception {
427 		// Activity ID raussuchen und in activityID speichern
428 		List children = event.getComponent().getChildren();
429 		int activityID = -1;
430 
431 		for (int i = 0; i < children.size(); i++) {
432 			if (children.get(i) instanceof UIParameter) {
433 				UIParameter currentParam = (UIParameter) children.get(i);
434 				if (currentParam.getName().equals("id")
435 						&& currentParam.getValue() != null) {
436 					// Value can be provided as String or Integer Object
437 					activityID = Integer.parseInt(currentParam.getValue()
438 							.toString());
439 					break;
440 				}
441 			}
442 		}
443 
444 		// update type
445 		workitemItemCollection.replaceItemValue("type", getType());
446 		// set activityid
447 		workitemItemCollection.replaceItemValue("$activityid", activityID);
448 
449 		// process workitem now...
450 		workitemItemCollection = workflowService
451 				.processWorkItem(workitemItemCollection);
452 
453 		// and finally update the Workitem Reference for the
454 		// ItemCollectionAdapter....
455 		this.setWorkitem(workitemItemCollection);
456 		// reset views
457 		doReset(event);
458 	}
459 
460 	/**
461 	 * this method is called by datatables to select an workitem
462 	 * 
463 	 * @return
464 	 */
465 	public void doEdit(ActionEvent event) {
466 		ItemCollection currentSelection = null;
467 		// suche selektierte Zeile....
468 		UIComponent component = event.getComponent();
469 		for (UIComponent parent = component.getParent(); parent != null; parent = parent
470 				.getParent()) {
471 			if (!(parent instanceof UIData))
472 				continue;
473 
474 			// Zeile gefunden
475 			currentSelection = (ItemCollection) ((UIData) parent).getRowData();
476 			setWorkitem(currentSelection);
477 			break;
478 
479 		}
480 	}
481 
482 	/**
483 	 * this method removes the current selected workitem from a view. The Method
484 	 * also deletes also all child workitems recursive
485 	 * 
486 	 * @param event
487 	 * @throws Exception
488 	 */
489 	public void doDelete(ActionEvent event) throws Exception {
490 		ItemCollection currentSelection = null;
491 		// suche selektierte Zeile....
492 		UIComponent component = event.getComponent();
493 		for (UIComponent parent = component.getParent(); parent != null; parent = parent
494 				.getParent()) {
495 			if (!(parent instanceof UIData))
496 				continue;
497 
498 			// Zeile gefunden
499 			currentSelection = (ItemCollection) ((UIData) parent).getRowData();
500 			break;
501 		}
502 
503 		// if nothing found - then try to cath current workitem
504 		if (currentSelection == null)
505 			currentSelection = this.workitemItemCollection;
506 		if (currentSelection != null) {
507 			deleteChilds(currentSelection);
508 			entityService.remove(currentSelection);
509 			this.setWorkitem(null);
510 			doReset(event);
511 		}
512 
513 	}
514 
515 	/**
516 	 * deletes all child workitmes of a workitem - recursive methode call
517 	 * 
518 	 * @param parent
519 	 */
520 	private void deleteChilds(ItemCollection parent) {
521 		try {
522 			String id = parent.getItemValueString("$uniqueid");
523 
524 			String sQuery = null;
525 			sQuery = "SELECT";
526 			sQuery += " wi FROM Entity as wi JOIN wi.textItems as t "
527 					+ "WHERE ";
528 			sQuery += " t.itemName = '$uniqueidref' and t.itemValue = '" + id
529 					+ "'";
530 
531 			Collection<ItemCollection> col = entityService.findAllEntities(
532 					sQuery, 0, -1);
533 
534 			for (ItemCollection aworkitem : col) {
535 				// recursive method call
536 				deleteChilds(aworkitem);
537 				// remove workitem
538 				entityService.remove(aworkitem);
539 			}
540 		} catch (Exception e) {
541 			e.printStackTrace();
542 		}
543 
544 	}
545 
546 	/**
547 	 * resets the current project list and projectMB
548 	 * 
549 	 * @return
550 	 */
551 	public void doReset(ActionEvent event) {
552 		workitems = null;
553 		row = 0;
554 	}
555 
556 	/**
557 	 * refreshes the current workitem list. so the list will be loaded again.
558 	 * but start pos will not be changed!
559 	 */
560 	public void doRefresh(ActionEvent event) {
561 		workitems = null;
562 	}
563 
564 	public void doSwitchToWorklistByAuthor(ActionEvent event) {
565 		queryType = this.QUERY_WORKLIST_BY_AUTHOR;
566 		doReset(event);
567 	}
568 
569 	public void doSwitchToWorklistByWriteAccess(ActionEvent event) {
570 		queryType = this.QUERY_WORKLIST_BY_WRITEACCESS;
571 		doReset(event);
572 	}
573 
574 	public void doSwitchToWorklistByOwner(ActionEvent event) {
575 		queryType = this.QUERY_WORKLIST_BY_OWNER;
576 		doReset(event);
577 	}
578 
579 	public void doSwitchToWorklistByCreator(ActionEvent event) {
580 		queryType = this.QUERY_WORKLIST_BY_CREATOR;
581 		doReset(event);
582 	}
583 
584 	public void doSwitchToWorklistAll(ActionEvent event) {
585 		queryType = this.QUERY_WORKLIST_ALL;
586 		doReset(event);
587 	}
588 
589 	public void doSwitchToSearchlist(ActionEvent event) {
590 		queryType = this.QUERY_SEARCH;
591 		doReset(event);
592 	}
593 
594 	public void doLoadNext(ActionEvent event) {
595 		row = row + maxSearchResult;
596 		workitems = null;
597 	}
598 
599 	public void doLoadPrev(ActionEvent event) {
600 		row = row - maxSearchResult;
601 		if (row < 0)
602 			row = 0;
603 		workitems = null;
604 	}
605 
606 	public List<ItemCollection> getWorkitems() {
607 		if (workitems == null)
608 			loadWorkItemList();
609 		return workitems;
610 	}
611 
612 	public void setWorkitems(List<ItemCollection> workitems) {
613 		this.workitems = workitems;
614 	}
615 
616 	/***************************************************************************
617 	 * Navigation
618 	 */
619 
620 	public int getRow() {
621 		return row;
622 	}
623 
624 	public boolean isEndOfList() {
625 		return endOfList;
626 	}
627 
628 	/**
629 	 * this method loads the workitems depending to the current query type The
630 	 * queryType is set during the getter Methods getWorkList, getStatusList and
631 	 * getIssueList For each query type a coresponding method is implmented by
632 	 * the issueService.
633 	 * 
634 	 * Caching: ======== The isDirty Flag is diabled because we recognize that
635 	 * in cases where people working online on share workitems the worklist is
636 	 * not uptodate. The only way to go back to a caching mechanism would be to
637 	 * place a refresh-button into the worklist pages.
638 	 * 
639 	 * @see org.imixs.shareyouwork.business.WorkitemServiceBean
640 	 */
641 	private void loadWorkItemList() {
642 		workitems = new ArrayList<ItemCollection>();
643 		Collection<ItemCollection> col = null;
644 		try {
645 			long lTime = System.currentTimeMillis();
646 
647 			switch (queryType) {
648 			case QUERY_WORKLIST_BY_OWNER:
649 				col = findWorkitemsByOwner(row, maxSearchResult);
650 				break;
651 			case QUERY_WORKLIST_BY_CREATOR:
652 				col = findWorkitemsByCreator(row, maxSearchResult);
653 				break;
654 
655 			case QUERY_WORKLIST_BY_AUTHOR:
656 				col = findWorkitemsByAuthor(row, maxSearchResult);
657 				break;
658 
659 			case QUERY_WORKLIST_BY_WRITEACCESS:
660 				col = findWorkitemsByWriteAccess(row, maxSearchResult);
661 				break;
662 
663 			case QUERY_SEARCH:
664 				col = findWorkitemsByQuery(getSearchQuery(), row,
665 						maxSearchResult);
666 				break;
667 
668 			// default find all
669 			default:
670 				col = findAllWorkitems(row, maxSearchResult);
671 			}
672 
673 			lTime = System.currentTimeMillis() - lTime;
674 			System.out.println("  loadWorkItemList (" + lTime + " ms)");
675 
676 			endOfList = col.size() < maxSearchResult;
677 			for (ItemCollection aworkitem : col) {
678 				workitems.add(aworkitem);
679 			}
680 		} catch (Exception ee) {
681 			ee.printStackTrace();
682 		}
683 
684 		// reset current workitem for detail views
685 		setWorkitem(null);
686 	}
687 
688 	private List<ItemCollection> findWorkitemsByQuery(String query, int row,
689 			int count) {
690 		ArrayList<ItemCollection> workitemList = new ArrayList<ItemCollection>();
691 
692 		if (query == null || "".equals(query))
693 			return workitemList;
694 		Collection<ItemCollection> col = entityService.findAllEntities(query,
695 				row, count);
696 		workitemList.addAll(col);
697 		return workitemList;
698 	}
699 
700 	/**
701 	 * Returns a collection of workitems where current user is owner (namOwner)
702 	 * 
703 	 * @param row
704 	 * @param count
705 	 * @return
706 	 * @throws Exception
707 	 */
708 	private List<ItemCollection> findWorkitemsByOwner(int row, int count)
709 			throws Exception {
710 		ArrayList<ItemCollection> workList = new ArrayList<ItemCollection>();
711 		Collection<ItemCollection> col = workflowService.getWorkListByOwner(
712 				null, row, count, type, getSortOrder());
713 		workList.addAll(col);
714 
715 		return workList;
716 
717 	}
718 
719 	/**
720 	 * Returns a collection representing the worklist for the current user
721 	 * 
722 	 * @param row
723 	 * @param count
724 	 * @return
725 	 * @throws Exception
726 	 */
727 	private List<ItemCollection> findWorkitemsByAuthor(int row, int count)
728 			throws Exception {
729 		ArrayList<ItemCollection> workList = new ArrayList<ItemCollection>();
730 		Collection<ItemCollection> col = workflowService.getWorkList(null, row,
731 				count, type, getSortOrder());
732 		workList.addAll(col);
733 
734 		return workList;
735 
736 	}
737 
738 	/**
739 	 * Returns a collection representing the worklist containing all workitems
740 	 * where the current user or one of its roles is in the writeAccess table
741 	 * 
742 	 * @param row
743 	 * @param count
744 	 * @return
745 	 * @throws Exception
746 	 */
747 	private List<ItemCollection> findWorkitemsByWriteAccess(int row, int count)
748 			throws Exception {
749 		ArrayList<ItemCollection> workList = new ArrayList<ItemCollection>();
750 		Collection<ItemCollection> col = workflowService
751 				.getWorkListByWriteAccess(row, count, type, getSortOrder());
752 		workList.addAll(col);
753 		return workList;
754 	}
755 
756 	/**
757 	 * Returns a collection representing the worklist for the current user
758 	 * 
759 	 * @param row
760 	 * @param count
761 	 * @return
762 	 * @throws Exception
763 	 */
764 	private List<ItemCollection> findWorkitemsByCreator(int row, int count)
765 			throws Exception {
766 		ArrayList<ItemCollection> workList = new ArrayList<ItemCollection>();
767 		Collection<ItemCollection> col = workflowService.getWorkListByCreator(
768 				null, row, count, type, getSortOrder());
769 		workList.addAll(col);
770 		return workList;
771 	}
772 
773 	/**
774 	 * Returns a collection of all Woritems independent of the current user
775 	 * name!
776 	 * 
777 	 * @param row
778 	 * @param count
779 	 * @return
780 	 */
781 	private List<ItemCollection> findAllWorkitems(int row, int count) {
782 		ArrayList<ItemCollection> teamList = new ArrayList<ItemCollection>();
783 
784 		String sQuery = "SELECT wi FROM Entity AS wi " + " WHERE wi.type= '"
785 				+ getType() + "' ORDER BY wi.modified desc";
786 
787 		Collection<ItemCollection> col = entityService.findAllEntities(sQuery,
788 				row, count);
789 
790 		teamList.addAll(col);
791 
792 		return teamList;
793 	}
794 
795 	/**
796 	 * returns the last computed workflow action. The property 'action' is
797 	 * computed by the ResultPlugin.
798 	 * 
799 	 * If no action is found show_workitem will be returned
800 	 * 
801 	 * @return
802 	 */
803 	public String getAction() {
804 		if (workitemItemCollection == null)
805 			return "show_workitem";
806 
807 		String sResult = workitemItemCollection.getItemValueString("action");
808 		if ("".equals(sResult))
809 			return "show_workitem";
810 		else
811 			return sResult;
812 	}
813 
814 	/**
815 	 * returns a arrayList of Activities to the corresponidng processiD of the
816 	 * current Worktiem. The Method returns the activities corresponding to the
817 	 * worktiems modelVersionID
818 	 * 
819 	 * @return
820 	 */
821 	public List<ItemCollection> getActivities() {
822 		activityList = new ArrayList<ItemCollection>();
823 
824 		if (workitemItemCollection == null)
825 			return activityList;
826 
827 		int processId = workitemItemCollection
828 				.getItemValueInteger("$processid");
829 		String sversion = workitemItemCollection
830 				.getItemValueString("$modelversion");
831 
832 		// get Workflow-Activities by version if provided by the workitem
833 		List<ItemCollection> col = null;
834 		if (sversion != null && !"".equals(sversion))
835 			col = this.getModelService().getPublicActivitiesByVersion(
836 					processId, sversion);
837 		// test if a model was found for this version - if not return the latest
838 		// version
839 		if (col == null || col.size() == 0)
840 			// return activities by defined modelversion
841 			col = this.getModelService().getPublicActivitiesByVersion(
842 					processId, getModelVersion());
843 
844 		for (ItemCollection aworkitem : col) {
845 			activityList.add(aworkitem);
846 		}
847 		return activityList;
848 	}
849 
850 	/**
851 	 * returns a arrayList of start processes. A Start process is the first
852 	 * ProcessEntity in a Process group of a model
853 	 * 
854 	 * The method only lookups the processEntities once!
855 	 * 
856 	 * @return
857 	 */
858 	public List<ItemCollection> getStartProcessList() {
859 		if (startProcessList != null)
860 			return startProcessList;
861 
862 		// build startProcessList frist time...
863 		startProcessList = new ArrayList<ItemCollection>();
864 
865 		// get ProcessEntities by version
866 		List<ItemCollection> col;
867 		col = modelService.getAllStartProcessEntitiesByVersion(this
868 				.getModelVersion());
869 
870 		for (ItemCollection aworkitem : col) {
871 			startProcessList.add(aworkitem);
872 		}
873 		return startProcessList;
874 	}
875 
876 	/**
877 	 * indicates if a workitem was processed before by the workflowService
878 	 * 
879 	 * @return
880 	 */
881 	public boolean isNewWorkitem() {
882 		try {
883 			return (!workitemItemCollection.hasItem("numlastactivityid"));
884 		} catch (Exception e) {
885 			return true;
886 		}
887 	}
888 
889 	/**
890 	 * This method can be used to add a Error Messege to the Application Context
891 	 * during an actionListener Call. Typical this method is used in the
892 	 * doProcessWrktiem method to display a processing exception to the user.
893 	 * The method expects the Ressoruce bundle name and the message key inside
894 	 * the bundle.
895 	 * 
896 	 * @param ressourceBundleName
897 	 * @param messageKey
898 	 * @param param
899 	 */
900 	public void addMessage(String ressourceBundleName, String messageKey,
901 			Object param) {
902 		FacesContext context = FacesContext.getCurrentInstance();
903 		Locale locale = context.getViewRoot().getLocale();
904 
905 		ResourceBundle rb = ResourceBundle.getBundle(ressourceBundleName,
906 				locale);
907 		String msgPattern = rb.getString(messageKey);
908 		String msg = msgPattern;
909 		if (param != null) {
910 			Object[] params = { param };
911 			msg = MessageFormat.format(msgPattern, params);
912 		}
913 		FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR,
914 				msg, msg);
915 		context.addMessage(null, facesMsg);
916 	}
917 
918 }