001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2005 Danet GmbH (www.danet.de), BU BTS.
004: * All rights reserved.
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * $Id: AssignmentService.java,v 1.5 2007/09/07 19:17:17 mlipp Exp $
021: *
022: * $Log: AssignmentService.java,v $
023: * Revision 1.5 2007/09/07 19:17:17 mlipp
024: * Added reload button.
025: *
026: * Revision 1.4 2007/02/27 14:34:22 drmlipp
027: * Some refactoring to reduce cyclic dependencies.
028: *
029: * Revision 1.3 2006/12/12 14:22:10 drmlipp
030: * Merged XForms client from branch.
031: *
032: * Revision 1.2.4.7 2006/12/11 21:12:52 mlipp
033: * Finished indirect assignment display.
034: *
035: * Revision 1.2.4.6 2006/12/11 16:24:51 drmlipp
036: * Started indirect assignments display.
037: *
038: * Revision 1.2.4.5 2006/12/11 13:30:19 drmlipp
039: * Continued with result delivery.
040: *
041: * Revision 1.2.4.4 2006/12/08 22:01:57 mlipp
042: * Minor improvements and adapted to Chiba update.
043: *
044: * Revision 1.2.4.3 2006/12/08 09:59:02 drmlipp
045: * Fixed caching.
046: *
047: * Revision 1.2.4.2 2006/12/05 14:18:43 drmlipp
048: * Initial display working.
049: *
050: * Revision 1.2.4.1 2006/10/31 16:07:17 drmlipp
051: * Seeing the form...
052: *
053: * Revision 1.2 2006/09/29 12:32:12 drmlipp
054: * Consistently using WfMOpen as projct name now.
055: *
056: * Revision 1.1 2006/09/21 15:02:31 drmlipp
057: * Continuing implementation.
058: *
059: */
060: package de.danet.an.xformstool.portletapp;
061:
062: import java.io.Serializable;
063: import java.lang.reflect.InvocationTargetException;
064: import java.rmi.RemoteException;
065: import java.security.Principal;
066: import java.util.ArrayList;
067: import java.util.Collection;
068: import java.util.Iterator;
069: import java.util.List;
070:
071: import javax.faces.application.FacesMessage;
072: import javax.faces.event.PhaseEvent;
073: import javax.faces.event.PhaseId;
074: import javax.faces.event.PhaseListener;
075: import javax.faces.model.DataModel;
076: import javax.faces.model.ListDataModel;
077:
078: import de.danet.an.util.BeanSorter;
079: import de.danet.an.util.jsf.JSFUtil;
080: import de.danet.an.workflow.api.Activity;
081: import de.danet.an.workflow.api.InvalidKeyException;
082: import de.danet.an.workflow.api.ProcessDirectory;
083: import de.danet.an.workflow.omgcore.WfResource;
084: import de.danet.an.workflow.tools.util.SimpleApplicationDirectory;
085: import de.danet.an.workflow.tools.util.SimpleApplicationDirectoryLookup;
086: import de.danet.an.workflow.tools.util.SimpleApplicationInfo;
087:
088: /**
089: * This class provides a service for looking up and managing the display
090: * of the the assignments.
091: *
092: * @author Michael Lipp
093: */
094: public class AssignmentService implements Serializable, PhaseListener {
095: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
096: .getLog(AssignmentService.class);
097:
098: public static final String APPLICATION_NAME = "de.danet.an.xformstool";
099:
100: private static String L10N_MSGS = "de.danet.an.xformstool.portletapp.L10n";
101:
102: private WorkflowServiceConnection wsc = null;
103: private transient SimpleApplicationDirectory applDirCache = null;
104: private transient DataModel directAssignmentsCache = null;
105: private transient DataModel indirectAssignmentsCache = null;
106: private BeanSorter directAssignmentsSorter = null;
107: private BeanSorter indirectAssignmentsSorter = null;
108: private Long chosenInstanceId = null;
109: private transient AssignmentData chosenInstance = null;
110:
111: /**
112: * Create a new instance with all attributes initialized
113: * to defaults or the given values.
114: */
115: public AssignmentService() {
116: JSFUtil.addPhaseListenerForPortlet(this );
117: }
118:
119: /* (non-Javadoc)
120: * @see javax.faces.event.PhaseListener#getPhaseId()
121: */
122: public PhaseId getPhaseId() {
123: return PhaseId.RENDER_RESPONSE;
124: }
125:
126: /* (non-Javadoc)
127: * @see javax.faces.event.PhaseListener#beforePhase
128: */
129: public void beforePhase(PhaseEvent arg0) {
130: // Get updated process list before rendering
131: // (may have been modified by action)
132: applDirCache = null;
133: chosenInstance = null;
134: directAssignmentsCache = null;
135: indirectAssignmentsCache = null;
136: }
137:
138: /* (non-Javadoc)
139: * @see javax.faces.event.PhaseListener#afterPhase
140: */
141: public void afterPhase(PhaseEvent arg0) {
142: applDirCache = null;
143: directAssignmentsCache = null;
144: indirectAssignmentsCache = null;
145: }
146:
147: /**
148: * @return Returns the workflowServiceConnection.
149: */
150: public WorkflowServiceConnection getWorkflowServiceConnection() {
151: return wsc;
152: }
153:
154: /**
155: * @param workflowServiceConnection The workflowServiceConnection to set.
156: */
157: public void setWorkflowServiceConnection(
158: WorkflowServiceConnection workflowServiceConnection) {
159: this .wsc = workflowServiceConnection;
160: }
161:
162: /**
163: * @return Returns the assignmentSorter.
164: */
165: public BeanSorter getDirectAssignmentsSorter() {
166: return directAssignmentsSorter;
167: }
168:
169: /**
170: * @param assignmentSorter The assignmentSorter to set.
171: */
172: public void setDirectAssignmentsSorter(BeanSorter assignmentSorter) {
173: this .directAssignmentsSorter = assignmentSorter;
174: }
175:
176: /**
177: * @return Returns the indirectAssignmentsSorter.
178: */
179: public BeanSorter getIndirectAssignmentsSorter() {
180: return indirectAssignmentsSorter;
181: }
182:
183: /**
184: * @param indirectAssignmentsSorter The indirectAssignmentsSorter to set.
185: */
186: public void setIndirectAssignmentsSorter(
187: BeanSorter indirectAssignmentsSorter) {
188: this .indirectAssignmentsSorter = indirectAssignmentsSorter;
189: }
190:
191: /**
192: * @return Returns the chosenInstanceId.
193: */
194: public Long getChosenInstanceId() {
195: return chosenInstanceId;
196: }
197:
198: /**
199: * @param chosenInstanceId The chosenInstanceId to set.
200: */
201: public void setChosenInstanceId(Long chosenInstanceId) {
202: if (this .chosenInstanceId == null
203: || !this .chosenInstanceId.equals(chosenInstanceId)) {
204: this .chosenInstanceId = chosenInstanceId;
205: chosenInstance = null;
206: }
207: }
208:
209: /**
210: * Get the simple application directory.
211: */
212: protected SimpleApplicationDirectory applicationDirectory()
213: throws RemoteException {
214: if (applDirCache == null) {
215: try {
216: applDirCache = (SimpleApplicationDirectory) wsc
217: .getWorkflowService().executeBatch(
218: new SimpleApplicationDirectoryLookup());
219: } catch (InvocationTargetException e) {
220: throw (IllegalStateException) (new IllegalStateException(
221: e.getMessage())).initCause(e);
222: }
223: }
224: return applDirCache;
225: }
226:
227: /**
228: * Get the direct assignments.
229: */
230: public DataModel getDirectAssignments() throws RemoteException {
231: if (directAssignmentsCache == null) {
232: try {
233: Principal principalMe = wsc.getWorkflowService()
234: .caller();
235: WfResource resourceMe = wsc.getWorkflowService()
236: .asResource(principalMe);
237: ProcessDirectory pd = wsc.getWorkflowService()
238: .processDirectory();
239: List assignments = new ArrayList();
240: assignments.addAll(assignmentDataFromInfos(pd,
241: resourceMe));
242: if (directAssignmentsSorter != null) {
243: directAssignmentsSorter.sort(assignments);
244: }
245: directAssignmentsCache = new ListDataModel(assignments);
246: } catch (InvalidKeyException e) {
247: JSFUtil.addMessage(FacesMessage.SEVERITY_ERROR,
248: L10N_MSGS, "resourceCurrentlyNotAvailable",
249: null, e);
250: }
251: } else {
252: if (directAssignmentsSorter != null
253: && directAssignmentsSorter.isModified()) {
254: directAssignmentsSorter
255: .sort((List) directAssignmentsCache
256: .getWrappedData());
257: }
258: }
259: return directAssignmentsCache;
260: }
261:
262: /**
263: * Get the indirect direct assignments.
264: */
265: public DataModel getIndirectAssignments() throws RemoteException {
266: if (indirectAssignmentsCache == null) {
267: try {
268: Principal principalMe = wsc.getWorkflowService()
269: .caller();
270: WfResource resourceMe = wsc.getWorkflowService()
271: .asResource(principalMe);
272: ProcessDirectory pd = wsc.getWorkflowService()
273: .processDirectory();
274: List assignments = new ArrayList();
275: Collection auths = wsc.getWorkflowService()
276: .authorizers(resourceMe);
277: for (Iterator i = auths.iterator(); i.hasNext();) {
278: WfResource res = (WfResource) i.next();
279: assignments
280: .addAll(assignmentDataFromInfos(pd, res));
281: }
282: if (indirectAssignmentsSorter != null) {
283: indirectAssignmentsSorter.sort(assignments);
284: }
285: indirectAssignmentsCache = new ListDataModel(
286: assignments);
287: } catch (InvalidKeyException e) {
288: JSFUtil.addMessage(FacesMessage.SEVERITY_ERROR,
289: L10N_MSGS, "resourceCurrentlyNotAvailable",
290: null, e);
291: }
292: } else {
293: if (indirectAssignmentsSorter != null
294: && indirectAssignmentsSorter.isModified()) {
295: indirectAssignmentsSorter
296: .sort((List) indirectAssignmentsCache
297: .getWrappedData());
298: }
299: }
300: return indirectAssignmentsCache;
301: }
302:
303: /**
304: * @param assignments
305: * @param pd
306: * @param resource
307: * @throws RemoteException
308: */
309: private Collection assignmentDataFromInfos(ProcessDirectory pd,
310: WfResource resource) throws RemoteException {
311: Collection assignments = new ArrayList();
312: Collection infos = applicationDirectory().infosByResource(
313: APPLICATION_NAME, resource.resourceKey());
314: for (Iterator i = infos.iterator(); i.hasNext();) {
315: SimpleApplicationInfo info = (SimpleApplicationInfo) i
316: .next();
317: Activity activity = null;
318: try {
319: activity = pd.lookupActivity(info.activityUniqueKey());
320: assignments.add(new AssignmentData(resource, info,
321: activity));
322: } catch (InvalidKeyException e) {
323: logger
324: .warn("Assignment for no longer existing activity, "
325: + "ignored: " + e.getMessage());
326: }
327: }
328: return assignments;
329: }
330:
331: /**
332: * @return the chosen instance data
333: */
334: public AssignmentData getChosenInstance() throws RemoteException {
335: if (chosenInstanceId == null) {
336: return null;
337: }
338: if (chosenInstance == null) {
339: try {
340: SimpleApplicationInfo info = applicationDirectory()
341: .instanceInfo(chosenInstanceId.longValue());
342: ProcessDirectory pd = wsc.getWorkflowService()
343: .processDirectory();
344: Activity activity = pd.lookupActivity(info
345: .activityUniqueKey());
346: chosenInstance = new AssignmentData(null, info,
347: activity);
348: } catch (InvalidKeyException e) {
349: // Must have been removed by concurrent action
350: chosenInstanceId = null;
351: }
352: }
353: return chosenInstance;
354: }
355:
356: /**
357: * @return outcome
358: */
359: public String showAssignments() {
360: return "showAssignments";
361: }
362:
363: /**
364: * Just a dummy for refreshing
365: * @return
366: */
367: public String refresh() {
368: return null;
369: }
370: }
|