/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2005 Danet GmbH (www.danet.de), BU BTS.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: AssignmentService.java 2443 2007-09-07 19:17:17Z mlipp $
*
* $Log$
* Revision 1.4 2007/02/27 14:34:22 drmlipp
* Some refactoring to reduce cyclic dependencies.
*
* Revision 1.3 2006/12/12 14:22:10 drmlipp
* Merged XForms client from branch.
*
* Revision 1.2.4.7 2006/12/11 21:12:52 mlipp
* Finished indirect assignment display.
*
* Revision 1.2.4.6 2006/12/11 16:24:51 drmlipp
* Started indirect assignments display.
*
* Revision 1.2.4.5 2006/12/11 13:30:19 drmlipp
* Continued with result delivery.
*
* Revision 1.2.4.4 2006/12/08 22:01:57 mlipp
* Minor improvements and adapted to Chiba update.
*
* Revision 1.2.4.3 2006/12/08 09:59:02 drmlipp
* Fixed caching.
*
* Revision 1.2.4.2 2006/12/05 14:18:43 drmlipp
* Initial display working.
*
* Revision 1.2.4.1 2006/10/31 16:07:17 drmlipp
* Seeing the form...
*
* Revision 1.2 2006/09/29 12:32:12 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.1 2006/09/21 15:02:31 drmlipp
* Continuing implementation.
*
*/
package de.danet.an.xformstool.portletapp;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import de.danet.an.util.BeanSorter;
import de.danet.an.util.jsf.JSFUtil;
import de.danet.an.workflow.api.Activity;
import de.danet.an.workflow.api.InvalidKeyException;
import de.danet.an.workflow.api.ProcessDirectory;
import de.danet.an.workflow.omgcore.WfResource;
import de.danet.an.workflow.tools.util.SimpleApplicationDirectory;
import de.danet.an.workflow.tools.util.SimpleApplicationDirectoryLookup;
import de.danet.an.workflow.tools.util.SimpleApplicationInfo;
/**
* This class provides a service for looking up and managing the display
* of the the assignments.
*
* @author Michael Lipp
*/
public class AssignmentService implements Serializable, PhaseListener {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory
.getLog (AssignmentService.class);
public static final String APPLICATION_NAME = "de.danet.an.xformstool";
private static String L10N_MSGS
= "de.danet.an.xformstool.portletapp.L10n";
private WorkflowServiceConnection wsc = null;
private transient SimpleApplicationDirectory applDirCache = null;
private transient DataModel directAssignmentsCache = null;
private transient DataModel indirectAssignmentsCache = null;
private BeanSorter directAssignmentsSorter = null;
private BeanSorter indirectAssignmentsSorter = null;
private Long chosenInstanceId = null;
private transient AssignmentData chosenInstance = null;
/**
* Create a new instance with all attributes initialized
* to defaults or the given values.
*/
public AssignmentService() {
JSFUtil.addPhaseListenerForPortlet(this);
}
/* (non-Javadoc)
* @see javax.faces.event.PhaseListener#getPhaseId()
*/
public PhaseId getPhaseId() {
return PhaseId.RENDER_RESPONSE;
}
/* (non-Javadoc)
* @see javax.faces.event.PhaseListener#beforePhase
*/
public void beforePhase(PhaseEvent arg0) {
// Get updated process list before rendering
// (may have been modified by action)
applDirCache = null;
chosenInstance = null;
directAssignmentsCache = null;
indirectAssignmentsCache = null;
}
/* (non-Javadoc)
* @see javax.faces.event.PhaseListener#afterPhase
*/
public void afterPhase(PhaseEvent arg0) {
applDirCache = null;
directAssignmentsCache = null;
indirectAssignmentsCache = null;
}
/**
* @return Returns the workflowServiceConnection.
*/
public WorkflowServiceConnection getWorkflowServiceConnection() {
return wsc;
}
/**
* @param workflowServiceConnection The workflowServiceConnection to set.
*/
public void setWorkflowServiceConnection(
WorkflowServiceConnection workflowServiceConnection) {
this.wsc = workflowServiceConnection;
}
/**
* @return Returns the assignmentSorter.
*/
public BeanSorter getDirectAssignmentsSorter() {
return directAssignmentsSorter;
}
/**
* @param assignmentSorter The assignmentSorter to set.
*/
public void setDirectAssignmentsSorter(BeanSorter assignmentSorter) {
this.directAssignmentsSorter = assignmentSorter;
}
/**
* @return Returns the indirectAssignmentsSorter.
*/
public BeanSorter getIndirectAssignmentsSorter() {
return indirectAssignmentsSorter;
}
/**
* @param indirectAssignmentsSorter The indirectAssignmentsSorter to set.
*/
public void setIndirectAssignmentsSorter(BeanSorter indirectAssignmentsSorter) {
this.indirectAssignmentsSorter = indirectAssignmentsSorter;
}
/**
* @return Returns the chosenInstanceId.
*/
public Long getChosenInstanceId() {
return chosenInstanceId;
}
/**
* @param chosenInstanceId The chosenInstanceId to set.
*/
public void setChosenInstanceId(Long chosenInstanceId) {
if (this.chosenInstanceId == null
|| !this.chosenInstanceId.equals(chosenInstanceId)) {
this.chosenInstanceId = chosenInstanceId;
chosenInstance = null;
}
}
/**
* Get the simple application directory.
*/
protected SimpleApplicationDirectory applicationDirectory ()
throws RemoteException {
if (applDirCache == null) {
try {
applDirCache = (SimpleApplicationDirectory)
wsc.getWorkflowService()
.executeBatch(new SimpleApplicationDirectoryLookup());
} catch (InvocationTargetException e) {
throw (IllegalStateException)
(new IllegalStateException(e.getMessage())).initCause(e);
}
}
return applDirCache;
}
/**
* Get the direct assignments.
*/
public DataModel getDirectAssignments () throws RemoteException {
if (directAssignmentsCache == null) {
try {
Principal principalMe = wsc.getWorkflowService().caller();
WfResource resourceMe
= wsc.getWorkflowService().asResource(principalMe);
ProcessDirectory pd
= wsc.getWorkflowService().processDirectory();
List assignments = new ArrayList ();
assignments.addAll (assignmentDataFromInfos(pd, resourceMe));
if (directAssignmentsSorter != null) {
directAssignmentsSorter.sort(assignments);
}
directAssignmentsCache = new ListDataModel (assignments);
} catch (InvalidKeyException e) {
JSFUtil.addMessage(FacesMessage.SEVERITY_ERROR, L10N_MSGS,
"resourceCurrentlyNotAvailable", null, e);
}
} else {
if (directAssignmentsSorter != null
&& directAssignmentsSorter.isModified()) {
directAssignmentsSorter.sort
((List)directAssignmentsCache.getWrappedData());
}
}
return directAssignmentsCache;
}
/**
* Get the indirect direct assignments.
*/
public DataModel getIndirectAssignments () throws RemoteException {
if (indirectAssignmentsCache == null) {
try {
Principal principalMe = wsc.getWorkflowService().caller();
WfResource resourceMe
= wsc.getWorkflowService().asResource(principalMe);
ProcessDirectory pd
= wsc.getWorkflowService().processDirectory();
List assignments = new ArrayList ();
Collection auths
= wsc.getWorkflowService().authorizers(resourceMe);
for (Iterator i = auths.iterator(); i.hasNext();) {
WfResource res = (WfResource)i.next();
assignments.addAll (assignmentDataFromInfos(pd, res));
}
if (indirectAssignmentsSorter != null) {
indirectAssignmentsSorter.sort(assignments);
}
indirectAssignmentsCache = new ListDataModel (assignments);
} catch (InvalidKeyException e) {
JSFUtil.addMessage(FacesMessage.SEVERITY_ERROR, L10N_MSGS,
"resourceCurrentlyNotAvailable", null, e);
}
} else {
if (indirectAssignmentsSorter != null
&& indirectAssignmentsSorter.isModified()) {
indirectAssignmentsSorter.sort
((List)indirectAssignmentsCache.getWrappedData());
}
}
return indirectAssignmentsCache;
}
/**
* @param assignments
* @param pd
* @param resource
* @throws RemoteException
*/
private Collection assignmentDataFromInfos
(ProcessDirectory pd, WfResource resource) throws RemoteException {
Collection assignments = new ArrayList ();
Collection infos = applicationDirectory()
.infosByResource(APPLICATION_NAME, resource.resourceKey());
for (Iterator i = infos.iterator(); i.hasNext();) {
SimpleApplicationInfo info = (SimpleApplicationInfo)i.next();
Activity activity = null;
try {
activity = pd.lookupActivity(info.activityUniqueKey());
assignments.add (new AssignmentData (resource, info, activity));
} catch (InvalidKeyException e) {
logger.warn("Assignment for no longer existing activity, "
+ "ignored: " + e.getMessage());
}
}
return assignments;
}
/**
* @return the chosen instance data
*/
public AssignmentData getChosenInstance () throws RemoteException {
if (chosenInstanceId == null) {
return null;
}
if (chosenInstance == null) {
try {
SimpleApplicationInfo info = applicationDirectory()
.instanceInfo(chosenInstanceId.longValue());
ProcessDirectory pd
= wsc.getWorkflowService().processDirectory();
Activity activity = pd.lookupActivity(info.activityUniqueKey());
chosenInstance = new AssignmentData (null, info, activity);
} catch (InvalidKeyException e) {
// Must have been removed by concurrent action
chosenInstanceId = null;
}
}
return chosenInstance;
}
/**
* @return outcome
*/
public String showAssignments () {
return "showAssignments";
}
/**
* Just a dummy for refreshing
* @return
*/
public String refresh () {
return null;
}
}