WfActivityImpl.java :  » Workflow-Engines » shark » org » enhydra » shark » Java Open Source

Java Open Source » Workflow Engines » shark 
shark » org » enhydra » shark » WfActivityImpl.java
package org.enhydra.shark;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.enhydra.shark.api.RootException;
import org.enhydra.shark.api.client.wfmc.wapi.WMSessionHandle;
import org.enhydra.shark.api.client.wfmodel.AlreadyRunning;
import org.enhydra.shark.api.client.wfmodel.AlreadySuspended;
import org.enhydra.shark.api.client.wfmodel.CannotAcceptSuspended;
import org.enhydra.shark.api.client.wfmodel.CannotComplete;
import org.enhydra.shark.api.client.wfmodel.CannotResume;
import org.enhydra.shark.api.client.wfmodel.CannotStart;
import org.enhydra.shark.api.client.wfmodel.CannotStop;
import org.enhydra.shark.api.client.wfmodel.CannotSuspend;
import org.enhydra.shark.api.client.wfmodel.InvalidData;
import org.enhydra.shark.api.client.wfmodel.InvalidPerformer;
import org.enhydra.shark.api.client.wfmodel.InvalidState;
import org.enhydra.shark.api.client.wfmodel.NotRunning;
import org.enhydra.shark.api.client.wfmodel.NotSuspended;
import org.enhydra.shark.api.client.wfmodel.ResultNotAvailable;
import org.enhydra.shark.api.client.wfmodel.TransitionNotAllowed;
import org.enhydra.shark.api.client.wfmodel.UpdateNotAllowed;
import org.enhydra.shark.api.client.wfmodel.WfDataEventAudit;
import org.enhydra.shark.api.client.wfmodel.WfEventAudit;
import org.enhydra.shark.api.client.wfmodel.WfRequester;
import org.enhydra.shark.api.common.DeadlineInfo;
import org.enhydra.shark.api.common.SharkConstants;
import org.enhydra.shark.api.internal.assignment.AssignmentManager;
import org.enhydra.shark.api.internal.assignment.PerformerData;
import org.enhydra.shark.api.internal.instancepersistence.ActivityPersistenceObject;
import org.enhydra.shark.api.internal.instancepersistence.ActivityVariablePersistenceObject;
import org.enhydra.shark.api.internal.instancepersistence.AssignmentPersistenceObject;
import org.enhydra.shark.api.internal.instancepersistence.DeadlinePersistenceObject;
import org.enhydra.shark.api.internal.instancepersistence.PersistentManagerInterface;
import org.enhydra.shark.api.internal.scripting.Evaluator;
import org.enhydra.shark.api.internal.security.SecurityManager;
import org.enhydra.shark.api.internal.toolagent.ToolAgentGeneralException;
import org.enhydra.shark.api.internal.working.ToolActivityHandler;
import org.enhydra.shark.api.internal.working.WfActivityInternal;
import org.enhydra.shark.api.internal.working.WfAssignmentInternal;
import org.enhydra.shark.api.internal.working.WfProcessInternal;
import org.enhydra.shark.api.internal.working.WfProcessMgrInternal;
import org.enhydra.shark.api.internal.working.WfResourceInternal;
import org.enhydra.shark.utilities.MiscUtilities;
import org.enhydra.shark.xpdl.XMLCollectionElement;
import org.enhydra.shark.xpdl.XMLUtil;
import org.enhydra.shark.xpdl.XPDLConstants;
import org.enhydra.shark.xpdl.elements.Activity;
import org.enhydra.shark.xpdl.elements.ActivitySet;
import org.enhydra.shark.xpdl.elements.ActualParameter;
import org.enhydra.shark.xpdl.elements.ActualParameters;
import org.enhydra.shark.xpdl.elements.Deadline;
import org.enhydra.shark.xpdl.elements.FormalParameter;
import org.enhydra.shark.xpdl.elements.FormalParameters;
import org.enhydra.shark.xpdl.elements.Package;
import org.enhydra.shark.xpdl.elements.Participant;
import org.enhydra.shark.xpdl.elements.Responsible;
import org.enhydra.shark.xpdl.elements.SubFlow;
import org.enhydra.shark.xpdl.elements.WorkflowProcess;

/**
 * WfActivityImpl - Workflow Activity Object implementation
 * 
 * @author Sasa Bojanic
 * @author Vladimir Puskas
 */
public class WfActivityImpl extends WfExecutionObjectImpl implements WfActivityInternal {

   protected String mgrName;

   protected String processId;

   protected Activity activityDefinition;

   protected WorkflowProcess processDefinition;

   protected String activitySetDefinitionId;

   protected String activityDefinitionId;

   protected String blockActivityId;

   protected String resourceUsername;

   protected Map activitiesProcessContext = new HashMap();

   protected boolean contextInitialized = false;

   // for implementation of requester interface
   protected String performerId;

   protected boolean isSubflowSynchronous = true;

   // holds Ids of variables that make activity results - only those variables will be
   // returned to the process context when activity finishes
   protected Set resultVariableIds;

   protected Evaluator evaluator;

   protected WfProcessInternal process;

   protected long acceptedTime = SharkConstants.UNDEFINED_TIME;

   protected long activatedTime = SharkConstants.UNDEFINED_TIME;

   protected List assignmentResourceIds;

   protected Set variableIdsToPersist = new HashSet();

   // protected ToolRunner myToolRunner;

   protected Thread startSubflowThread = null;

   // protected boolean deleteAssignments=false;

   protected WfActivityInternal blockActivity = null;

   protected Exception exc = null;

   protected String exceptionName = null;

   protected List deadlinesInfo;

   protected boolean justCreated = false;

   protected boolean justCreatedVariables = false;

   protected boolean justCreatedDeadlines = false;

   /**
    * Create a new WfActivityImpl
    */
   protected WfActivityImpl(WMSessionHandle shandle,
                            WfProcessInternal process,
                            String key,
                            String activityDefId,
                            WfActivityInternal blockActivity) throws Exception {
      this.mgrName = process.manager_name(shandle);
      this.processId = process.key(shandle);
      this.key = key;
      this.process = process;
      this.activityDefinitionId = activityDefId;
      // initializing activity definition
      getActivityDefinition(shandle);
      this.blockActivity = blockActivity;
      this.justCreated = true;
      this.justCreatedVariables = true;
      this.justCreatedDeadlines = true;
      if (this.blockActivity != null) {
         this.blockActivityId = this.blockActivity.key(shandle);
         this.activitySetDefinitionId = ((ActivitySet) activityDefinition.getParent()
            .getParent()).getId();
      }
      name = activityDefinition.getName();
      if (name.equals("")) {
         name = activityDefinitionId;
      }
      description = activityDefinition.getDescription();
      if (description != null && description.length() > 254) {
         description = description.substring(0, 253);
      }
      try {
         String pr = activityDefinition.getPriority();
         if (pr.trim().equals("")) {
            priority = process.priority(shandle);
         } else {
            priority = Integer.valueOf(activityDefinition.getPriority()).shortValue();
            boolean allowOutOfRangePriority = Boolean.valueOf(SharkEngineManager.getInstance()
               .getCallbackUtilities()
               .getProperty("SharkKernel.allowOutOfRangePriority", "false"))
               .booleanValue();
            if (!allowOutOfRangePriority && priority < 1)
               priority = 1;
            if (!allowOutOfRangePriority && priority > 5)
               priority = 5;
         }
      } catch (Exception ex) {
         priority = 3;
      }

      initializeActivityContext(shandle);

      assignmentResourceIds = new ArrayList();
      if (activitiesProcessContext.size() > 0) {
         variableIdsToPersist.addAll(getContext(shandle).keySet());
      }
      resultVariableIds = new HashSet();

      this.calculateLimit(shandle);

   }

   /**
    * Used to create object when restoring it from database.
    */
   protected WfActivityImpl(ActivityPersistenceObject po, WfProcessInternal proc) {
      this.process = proc;
      restore(po);
   }

   /**
    * Activates this activity.
    */
   public void activate(WMSessionHandle shandle)
      throws Exception,
         CannotStart,
         AlreadyRunning {

      checkReadOnly();

      // make sure we aren't already running
      if (state(shandle).equals(SharkConstants.STATE_OPEN_RUNNING)) {
         throw new AlreadyRunning("Activity "
                                  + this + " - can't activate already running activity");
      }

      lastStateTime = System.currentTimeMillis();

      activatedTime = lastStateTime;

      // re-evaluate deadlines - the information will be stored into DB
      reevaluateDeadlines(shandle);

      persist(shandle);
      persistActivityContext(shandle);
      persistDeadlines(shandle);

      lastStateEventAudit = SharkEngineManager.getInstance()
         .getObjectFactory()
         .createStateEventAuditWrapper(shandle,
                                       this,
                                       SharkConstants.EVENT_ACTIVITY_STATE_CHANGED,
                                       null,
                                       state);

      if (activitiesProcessContext.size() > 0) { // do not use getContext() here because
         // of extensions
         if (SharkEngineManager.getInstance().getEventAuditManagers().size() > 0) {
            SharkEngineManager.getInstance()
               .getObjectFactory()
               .createDataEventAuditWrapper(shandle,
                                            this,
                                            SharkConstants.EVENT_ACTIVITY_CONTEXT_CHANGED,
                                            null,
                                            new HashMap(getContext(shandle)));
         }
      }

      try {
         startActivity(shandle);
      } catch (ToolAgentGeneralException tage) {
         exc = tage;
         finishImproperlyAndNotifyProcess(shandle,
                                          SharkUtilities.extractExceptionName(tage));
      }

      startSubflowThread = null;
   }

   public synchronized List getAssignmentResourceIds(WMSessionHandle shandle)
      throws Exception {
      if (assignmentResourceIds == null) {

         assignmentResourceIds = new ArrayList();
         boolean createAssignments = canCreateAssignments(shandle);
         if (createAssignments) {
            List l = SharkEngineManager.getInstance()
               .getInstancePersistenceManager()
               .getAllAssignmentsForActivity(shandle, processId, key);
            for (int i = 0; i < l.size(); i++) {
               AssignmentPersistenceObject po = (AssignmentPersistenceObject) l.get(i);
               assignmentResourceIds.add(po.getResourceUsername());
            }
         }
      }

      return assignmentResourceIds;
   }

   /**
    * Getter for the process of this activity.
    */
   public WfProcessInternal container(WMSessionHandle shandle) throws Exception {
      return process;
   }

   /**
    * Retrieve the Result map of this activity.
    * 
    * @return Map of results from this activity
    */
   public Map result(WMSessionHandle shandle) throws Exception, ResultNotAvailable {
      Map resultMap = new HashMap();
      // System.out.println("Updating process with the variables
      // "+getChangedContextVariableIds(t));
      Iterator it = resultMap(shandle).entrySet().iterator();
      while (it.hasNext()) {
         Map.Entry me = (Map.Entry) it.next();
         try {
            resultMap.put(me.getKey(), MiscUtilities.cloneWRD(me.getValue()));
         } catch (Throwable thr) {
            throw new RootException(thr);
         }
      }
      return resultMap;
   }

   protected Map resultMap(WMSessionHandle shandle) throws Exception {
      Map resultMap = new HashMap();
      // System.out.println("Updating process with the variables
      // "+getChangedContextVariableIds(t));
      Iterator it = getResultVariableIds(shandle).iterator();
      while (it.hasNext()) {
         java.lang.Object vId = it.next();
         resultMap.put(vId, getContext(shandle).get(vId));
      }
      return resultMap;
   }

   /**
    * Assign Result for this activity.
    */
   public void set_result(WMSessionHandle shandle, Map results)
      throws Exception,
         InvalidData {
      checkReadOnly();
      try {
         setProcessContext(shandle, results, SharkConstants.EVENT_ACTIVITY_RESULT_CHANGED);
      } catch (InvalidData id) {
         SharkEngineManager.getInstance()
            .getCallbackUtilities()
            .error(shandle,
                   "Activity" + toString() + " - failed to set the activity result");
         throw id;
      } catch (Exception be) {
         SharkEngineManager.getInstance()
            .getCallbackUtilities()
            .error(shandle,
                   "Activity" + toString() + " - failed to set the activity result");
         throw be;
      }
   }

   public void complete(WMSessionHandle shandle) throws Exception, CannotComplete {
      checkReadOnly();
      // get the type of this activity
      int type = getActivityDefinition(shandle).getActivityType();
      switch (type) {
         case XPDLConstants.ACTIVITY_TYPE_ROUTE: // Route
            throw new Exception("Activity "
                                + this
                                + " - route activity can be finished only automatically");
            // this.finish(t); // ROUTE goes directly to complete status
         case XPDLConstants.ACTIVITY_TYPE_NO: // NoImplementation
            this.finish(shandle); // NO impl goes directly to complete status
            break;
         case XPDLConstants.ACTIVITY_TYPE_TOOL: // Tools
            boolean shouldFinishImmediatelly = getActivityDefinition(shandle).getActivityFinishMode() == XPDLConstants.ACTIVITY_MODE_AUTOMATIC;
            if (getActivityDefinition(shandle).getActivityStartMode() == XPDLConstants.ACTIVITY_MODE_MANUAL) {
               try {
                  if (shouldFinishImmediatelly
                      || getAssignmentResourceIds(shandle).size() > 0) {
                     this.runTool(shandle);
                  }
               } catch (Exception ex) {
                  if (ex instanceof ToolAgentGeneralException) {
                     exc = ex;
                     finishImproperlyAndNotifyProcess(shandle,
                                                      SharkUtilities.extractExceptionName(exc));

                     return;
                  }

                  throw ex;
               }

               if (shouldFinishImmediatelly
                   || getAssignmentResourceIds(shandle).size() == 0) {
                  finish(shandle);
               } else {
                  // delete assignments
                  removeAssignments(shandle, true, true);
               }
            } else {
               if (!shouldFinishImmediatelly) {
                  this.finish(shandle);
               }
            }
            break;
         case XPDLConstants.ACTIVITY_TYPE_SUBFLOW: // SubFlow
            throw new Exception("Activity "
                                + this
                                + " - subflow activity can be finished only automatically");
            // this.finish(t); // Subflow act. goes directly to complete status
            // break;
         case XPDLConstants.ACTIVITY_TYPE_BLOCK: // BlockActivity
            throw new Exception("Activity "
                                + this
                                + " - block activity can be finished only automatically");
            // this.finish(t); // Block act. goes directly to complete status
            // break;
      }
   }

   /**
    * Complete this activity.
    */
   public void finish(WMSessionHandle shandle) throws Exception, CannotComplete {
      checkReadOnly();
      try {
         boolean cont = true;
         if (handleAllAssignments(shandle)) {
            checkReadOnly();
            int[] es = execution_status(shandle);
            removeAssignment(shandle, SharkEngineManager.getInstance()
               .getCallbackUtilities()
               .getUserId(shandle), false, true);
            if ((es[1] + es[2]) > 1) {
               cont = false;
            }
         }
         if (cont) {
            // remove assignments first, because method for getting assignments
            // from database depends on activity's state
            removeAssignments(shandle, true, true);

            change_state(shandle, SharkConstants.STATE_CLOSED_COMPLETED);
            process.set_process_context(shandle, resultMap(shandle));

            process.activity_complete(shandle, this);
         }
      } catch (InvalidData e) {
         throw new CannotComplete("Activity "
                                  + this
                                  + " -> can't complete activity. Invalid result data was passed.");
      } catch (ResultNotAvailable rne) {
         throw new CannotComplete("Activity "
                                  + this
                                  + " -> can't complete activity. Result of activity is not available.");
      } catch (UpdateNotAllowed una) {
         throw new CannotComplete("Activity "
                                  + this
                                  + " -> can't complete activity. Process context update is not allowed.");
      }
   }

   protected void change_state(WMSessionHandle shandle, String new_state)
      throws Exception,
         InvalidState,
         TransitionNotAllowed {
      // System.out.println("Act "+this+" Curr st is "+state(t)+", new state is
      // "+new_state+", valid states are
      // "+SharkUtilities.valid_activity_states(state(t)));
      if (!SharkUtilities.valid_activity_states(state(shandle)).contains(new_state)) {
         throw new TransitionNotAllowed("Activity "
                                        + this + " - current state is " + state
                                        + ", can't change to state " + new_state + "!");
      }

      // persist changes to activity state
      String oldState = state;
      state = new_state;

      lastStateTime = System.currentTimeMillis();

      persist(shandle);

      lastStateEventAudit = SharkEngineManager.getInstance()
         .getObjectFactory()
         .createStateEventAuditWrapper(shandle,
                                       this,
                                       SharkConstants.EVENT_ACTIVITY_STATE_CHANGED,
                                       oldState,
                                       new_state);

   }

   public void set_process_context(WMSessionHandle shandle, Map new_value)
      throws Exception,
         InvalidData,
         UpdateNotAllowed {
      checkReadOnly();
      setProcessContext(shandle, new_value, SharkConstants.EVENT_ACTIVITY_CONTEXT_CHANGED);
   }

   protected void setProcessContext(WMSessionHandle shandle,
                                    Map newValue,
                                    String eventType)
      throws Exception,
         InvalidData,
         UpdateNotAllowed,
         Exception {
      if (newValue == null) {
         throw new Exception("Activity "
                             + this + " - can't set context map which is null");
      }
      Map oldValues = new HashMap();
      Map newChanged = new HashMap();
      Iterator it = newValue.entrySet().iterator();
      while (it.hasNext()) {
         Map.Entry me = (Map.Entry) it.next();
         String id = (String) me.getKey();
         if (getContext(shandle).containsKey(id)) {
            Object oldVal = getContext(shandle).get(id);
            // type checking - throws an exception if type is invalid or can't be
            // converted to a valid one
            Object val = SharkUtilities.checkDataType(getProcessDefinition(shandle),
                                                      id,
                                                      oldVal,
                                                      me.getValue());

            // System.out.println("var "+id+"["+oldVal+","+val+"]");
            if ((oldVal != null && !oldVal.equals(val))
                || (oldVal == null && val != null)) {
               oldValues.put(id, oldVal);
               newChanged.put(id, val);
            }
         } else {
            // System.err.println("The variable "+id+" is not in the context");
            throw new UpdateNotAllowed("Activity "
                                       + this
                                       + " - context attribute "
                                       + id
                                       + " does not exist in the activity context - adding new attributes to activity context is not allowed");
         }
      }
      if (newChanged.size() > 0
          || eventType.equals(SharkConstants.EVENT_ACTIVITY_RESULT_CHANGED)) {
         getContext(shandle).putAll(newChanged);
         Map toPersist = new HashMap(newChanged);
         Map newSRVars = null;
         if (eventType.equals(SharkConstants.EVENT_ACTIVITY_RESULT_CHANGED)) {
            newSRVars = new HashMap();
            Set oldRVIds = new HashSet(getResultVariableIds(shandle));
            getResultVariableIds(shandle).addAll(newValue.keySet());
            Set newRVIds = new HashSet(getResultVariableIds(shandle));
            newRVIds.removeAll(oldRVIds);
            Iterator itRV = newRVIds.iterator();
            while (itRV.hasNext()) {
               String id = (String) itRV.next();
               Object val = getContext(shandle).get(id);
               toPersist.put(id, val);
               newSRVars.put(id, val);
            }
         }

         variableIdsToPersist.addAll(toPersist.keySet());
         persistActivityContext(shandle);
         if (newChanged.size() > 0) {
            if (SharkEngineManager.getInstance().getEventAuditManagers().size() > 0) {
               boolean persistOldEventAuditData = new Boolean(SharkEngineManager.getInstance()
                  .getCallbackUtilities()
                  .getProperty("PERSIST_OLD_EVENT_AUDIT_DATA", "true")).booleanValue();
               if (!persistOldEventAuditData) {
                  oldValues = null;
               }
               SharkEngineManager.getInstance()
                  .getObjectFactory()
                  .createDataEventAuditWrapper(shandle,
                                               this,
                                               SharkConstants.EVENT_ACTIVITY_CONTEXT_CHANGED,
                                               oldValues,
                                               newChanged);
            }
         }
         if (newSRVars != null && newSRVars.size() > 0) {
            if (SharkEngineManager.getInstance().getEventAuditManagers().size() > 0) {
               boolean persistOldEventAuditData = new Boolean(SharkEngineManager.getInstance()
                  .getCallbackUtilities()
                  .getProperty("PERSIST_OLD_EVENT_AUDIT_DATA", "true")).booleanValue();
               if (!persistOldEventAuditData) {
                  oldValues = null;
               }
               SharkEngineManager.getInstance()
                  .getObjectFactory()
                  .createDataEventAuditWrapper(shandle, this, eventType, null, newSRVars);
            }
         }
      }
   }

   /**
    * Resume this process or activity.
    */
   public void resume(WMSessionHandle shandle)
      throws Exception,
         CannotResume,
         NotSuspended {
      checkReadOnly();
      int type = getActivityDefinition(shandle).getActivityType();

      // try {
      if (!state(shandle).equals(SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED)) {
         throw new NotSuspended("Activity "
                                + this + " - can't resume activity that is not suspended");
      }
      if (process.state(shandle).equals(SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED)) {
         throw new CannotResume("Activity "
                                + this
                                + " - can't resume activity which process is suspended");
      }
      if (blockActivityId != null
          && block_activity(shandle).state(shandle)
             .equals(SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED)) {
         throw new CannotResume("Activity "
                                + this
                                + " - can't resume activity which block is suspended");
      }

      try {
         int[] es = execution_status(shandle);
         if ((es[0] + es[1]) > 0
             || type == XPDLConstants.ACTIVITY_TYPE_BLOCK
             || type == XPDLConstants.ACTIVITY_TYPE_SUBFLOW) {
            change_state(shandle, SharkConstants.STATE_OPEN_RUNNING);
         } else {
            change_state(shandle, SharkConstants.STATE_OPEN_NOT_RUNNING_NOT_STARTED);
         }
      } catch (Exception ex) {
         throw new CannotResume(ex);
      }

      if (type == XPDLConstants.ACTIVITY_TYPE_SUBFLOW) {
         // if this is a subflow activity, resume it's process
         // if it is SYNCHRONOUS
         if (isSubflowSynchronous) {
            WfProcessInternal performer = getPerformer(shandle);
            if (performer == null) {
               SubFlow subflow = getActivityDefinition(shandle).getActivityTypes()
                  .getImplementation()
                  .getImplementationTypes()
                  .getSubFlow();
               String refSbflw = subflow.getId();
               WorkflowProcess wp = SharkUtilities.getWorkflowProcess(shandle,
                                                                      subflow,
                                                                      refSbflw);
               if (wp != null || performerId == null || performerId.equals("")) {
                  throw new Exception("Activity "
                                      + this
                                      + " - null performer of sync. subflow activity");
               }

               SharkEngineManager.getInstance()
                  .getWfEngineInteroperabilityMgr()
                  .resume(shandle,
                          performerId,
                          processId,
                          MiscUtilities.createAssignmentKey(key,
                                                            getResourceRequesterUsername(shandle)));

            } else {
               if (performer.state(shandle)
                  .equals(SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED)) {
                  performer.resume(shandle);
               }
            }
         }
      } else if (type == XPDLConstants.ACTIVITY_TYPE_BLOCK) {
         List actActs = process.getAllActiveActivitiesForBlockActivity(shandle, key);
         Iterator it = actActs.iterator();
         while (it.hasNext()) {
            WfActivityInternal act = (WfActivityInternal) it.next();
            if (act.state(shandle)
               .equals(SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED)) {
               act.resume(shandle);
            }
         }
      }

   }

   /**
    * Suspend this process or activity.
    */
   public void suspend(WMSessionHandle shandle)
      throws Exception,
         CannotSuspend,
         NotRunning,
         AlreadySuspended {
      checkReadOnly();
      if (state(shandle).equals(SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED)) {
         throw new AlreadySuspended("Activity " + this + " is already suspended!");
      }
      if (state(shandle).startsWith(SharkConstants.STATEPREFIX_CLOSED)) {
         throw new CannotSuspend("Activity " + this + " is closed - can't suspend!");
      }

      try {
         change_state(shandle, SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED);
      } catch (Exception ex) {
         throw new CannotSuspend(ex);
      }

      int type = getActivityDefinition(shandle).getActivityType();
      if (type == XPDLConstants.ACTIVITY_TYPE_SUBFLOW) {
         // if this is a subflow activity, suspend it's process
         // if it is SYNCHRONOUS
         if (isSubflowSynchronous) {
            WfProcessInternal performer = getPerformer(shandle);
            if (performer == null) {
               SubFlow subflow = getActivityDefinition(shandle).getActivityTypes()
                  .getImplementation()
                  .getImplementationTypes()
                  .getSubFlow();
               String refSbflw = subflow.getId();
               WorkflowProcess wp = SharkUtilities.getWorkflowProcess(shandle,
                                                                      subflow,
                                                                      refSbflw);
               if (wp != null || performerId == null || performerId.equals("")) {
                  throw new Exception("Activity "
                                      + this
                                      + " - null performer of sync. subflow activity");
               }

               SharkEngineManager.getInstance()
                  .getWfEngineInteroperabilityMgr()
                  .suspend(shandle,
                           performerId,
                           processId,
                           MiscUtilities.createAssignmentKey(key,
                                                             getResourceRequesterUsername(shandle)));
            } else {
               String perfState = performer.state(shandle);
               if (perfState.startsWith(SharkConstants.STATEPREFIX_OPEN)
                   && !perfState.equals(SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED)) {
                  performer.suspend(shandle);
               }
            }
         }
      } else if (type == XPDLConstants.ACTIVITY_TYPE_BLOCK) {
         List actActs = process.getAllActiveActivitiesForBlockActivity(shandle, key);
         Iterator it = actActs.iterator();
         while (it.hasNext()) {
            WfActivityInternal act = (WfActivityInternal) it.next();
            String actState = act.state(shandle);
            if (actState.startsWith(SharkConstants.STATEPREFIX_OPEN)
                && !actState.equals(SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED)) {
               act.suspend(shandle);
            }
         }
      }

   }

   /**
    * Terminate this process or activity.
    */
   public void terminateFromProcess(WMSessionHandle shandle)
      throws Exception,
         CannotStop,
         NotRunning {
      checkReadOnly();
      terminateActivity(shandle, true);
   }

   /**
    * Terminate this process or activity.
    */
   public void terminate(WMSessionHandle shandle)
      throws Exception,
         CannotStop,
         NotRunning {
      checkReadOnly();
      terminateActivity(shandle, false);
   }

   protected void terminateActivity(WMSessionHandle shandle, boolean fromProcess)
      throws Exception,
         CannotStop,
         NotRunning {
      checkReadOnly();
      String stateStr = SharkConstants.STATE_CLOSED_TERMINATED;
      if (!state(shandle).startsWith(SharkConstants.STATEPREFIX_OPEN)) {
         throw new CannotStop("Activity "
                              + this
                              + " - the activity is already in the closed state - can't terminate it!");
      }

      // remove assignments first, because method for getting assignments
      // from database depends on activity's state
      removeAssignments(shandle, true, true);

      try {
         change_state(shandle, stateStr);
      } catch (Exception ex) {
         throw new CannotStop(ex);
      }

      int type = getActivityDefinition(shandle).getActivityType();
      if (type == XPDLConstants.ACTIVITY_TYPE_SUBFLOW) {
         // if this is a subflow activity, terminate it's process
         // if it is SYNCHRONOUS
         if (isSubflowSynchronous) {
            WfProcessInternal performer = getPerformer(shandle);
            if (performer == null) {
               SubFlow subflow = getActivityDefinition(shandle).getActivityTypes()
                  .getImplementation()
                  .getImplementationTypes()
                  .getSubFlow();
               String refSbflw = subflow.getId();
               WorkflowProcess wp = SharkUtilities.getWorkflowProcess(shandle,
                                                                      subflow,
                                                                      refSbflw);
               if (wp != null || performerId == null || performerId.equals("")) {
                  throw new Exception("Activity "
                                      + this
                                      + " - null performer of sync. subflow activity");
               }

               SharkEngineManager.getInstance()
                  .getWfEngineInteroperabilityMgr()
                  .terminate(shandle,
                             performerId,
                             processId,
                             MiscUtilities.createAssignmentKey(key,
                                                               getResourceRequesterUsername(shandle)));

            } else {
               if (performer.state(shandle).startsWith(SharkConstants.STATEPREFIX_OPEN)) {
                  performer.terminateFromActivity(shandle);
               }
            }
         }
      } else if (type == XPDLConstants.ACTIVITY_TYPE_BLOCK) {
         List actActs = process.getAllActiveActivitiesForBlockActivity(shandle, key);
         Iterator it = actActs.iterator();
         while (it.hasNext()) {
            WfActivityInternal act = (WfActivityInternal) it.next();
            if (act.state(shandle).startsWith(SharkConstants.STATEPREFIX_OPEN)) {
               act.terminateFromProcess(shandle);
            }
         }
      }

      if (!fromProcess) {
         process.activity_terminate(shandle, this);
      }
   }

   public void abortFromProcess(WMSessionHandle shandle)
      throws Exception,
         CannotStop,
         NotRunning {
      checkReadOnly();
      abortActivity(shandle, true);
   }

   /**
    * Abort the execution of this process or activity.
    */
   public void abort(WMSessionHandle shandle) throws Exception, CannotStop, NotRunning {
      checkReadOnly();
      abortActivity(shandle, false);
   }

   protected void abortActivity(WMSessionHandle shandle, boolean fromProcess)
      throws Exception,
         CannotStop,
         NotRunning {
      checkReadOnly();
      String stateStr = SharkConstants.STATE_CLOSED_ABORTED;
      if (!state(shandle).startsWith(SharkConstants.STATEPREFIX_OPEN)) {
         throw new CannotStop("Activity "
                              + this
                              + " - the activity is already in the closed state - can't abort it!");
      }

      // remove assignments first, because method for getting assignments
      // from database depends on activity's state
      removeAssignments(shandle, true, true);

      try {
         change_state(shandle, stateStr);
      } catch (Exception ex) {
         throw new CannotStop(ex);
      }

      int type = getActivityDefinition(shandle).getActivityType();
      if (type == XPDLConstants.ACTIVITY_TYPE_SUBFLOW) {
         // if this is a subflow activity, abort it's process
         // if it is SYNCHRONOUS
         if (isSubflowSynchronous) {
            WfProcessInternal performer = getPerformer(shandle);
            if (performer == null) {
               SubFlow subflow = getActivityDefinition(shandle).getActivityTypes()
                  .getImplementation()
                  .getImplementationTypes()
                  .getSubFlow();
               String refSbflw = subflow.getId();
               WorkflowProcess wp = SharkUtilities.getWorkflowProcess(shandle,
                                                                      subflow,
                                                                      refSbflw);
               if (wp != null || performerId == null || performerId.equals("")) {
                  throw new Exception("Activity "
                                      + this
                                      + " - null performer of sync. subflow activity");
               }

               SharkEngineManager.getInstance()
                  .getWfEngineInteroperabilityMgr()
                  .abort(shandle,
                         performerId,
                         processId,
                         MiscUtilities.createAssignmentKey(key,
                                                           getResourceRequesterUsername(shandle)));

            } else {
               if (performer.state(shandle).startsWith(SharkConstants.STATEPREFIX_OPEN)) {
                  performer.abortFromActivity(shandle);
               }
            }
         }
      } else if (type == XPDLConstants.ACTIVITY_TYPE_BLOCK) {
         List actActs = process.getAllActiveActivitiesForBlockActivity(shandle, key);
         Iterator it = actActs.iterator();
         while (it.hasNext()) {
            WfActivityInternal act = (WfActivityInternal) it.next();
            if (act.state(shandle).startsWith(SharkConstants.STATEPREFIX_OPEN)) {
               act.abortFromProcess(shandle);
            }
         }
      }

      if (!fromProcess) {
         process.activity_abort(shandle, this);
      }
   }

   /**
    * Receives notice of event status changes. This is called when some subflow process
    * has finished its execution.
    */
   public void receive_event(WMSessionHandle shandle,
                             WfEventAudit event,
                             WfProcessInternal performer)
      throws Exception,
         InvalidPerformer {
      checkReadOnly();
      // System.out.println("Act "+this+" receives event from process "+performer+",
      // ms="+state);
      Activity aDef = getActivityDefinition(shandle);
      SubFlow subflow = aDef.getActivityTypes()
         .getImplementation()
         .getImplementationTypes()
         .getSubFlow();

      if (!isSubflowSynchronous)
         return;

      try {
         if (performer != null) {
            if (state(shandle).startsWith(SharkConstants.STATEPREFIX_CLOSED)) {
               return;
            }
            String perfState = performer.state(shandle);
            if (perfState.startsWith(SharkConstants.STATEPREFIX_OPEN)) {
               return;
            }
            if (perfState.equals(SharkConstants.STATE_CLOSED_COMPLETED)) {
               // if
               // (event.event_type().equals(SharkConstants.EVENT_PROCESS_STATE_CHANGED)
               // &&
               // The Ids of variables of result from the subflow process must be
               // corrected to correspond to the actual param variables
               // In the following map are only OUT and INOUT formal params of
               // subflow process
               Map rm = performer.result(shandle);
               // This is a subflow activity, so it's context consists
               // of actual parameters to be passed to the referenced
               // process in exact order. The Ids of the passed values
               // are not the same as the Ids used internally by the subprocess
               // formal parameters, so we get appropriate ids by getting the
               // process context param at the appropriate place which must be
               // determined from matching activities actual parameter order
               // with the subflow process formal parameter order

               // Get actual parameters definition of the subflow activity

               Iterator actualParameters = subflow.getActualParameters()
                  .toElements()
                  .iterator();
               // make a list of actual parameter Ids
               List originalIds = new ArrayList();
               while (actualParameters.hasNext()) {
                  ActualParameter ap = (ActualParameter) actualParameters.next();
                  String apId = ap.toValue();
                  originalIds.add(apId);
               }

               Map updatedContext = new HashMap();
               WorkflowProcess wp = SharkUtilities.getWorkflowProcess(shandle,
                                                                      performer.package_id(shandle),
                                                                      performer.manager_version(shandle),
                                                                      performer.process_definition_id(shandle));
               Iterator it = rm.entrySet().iterator();
               while (it.hasNext()) {
                  Map.Entry me = (Map.Entry) it.next();
                  String fpId = (String) me.getKey();
                  int index = 0;
                  int foundIndex = -1;
                  // find the index of formal parameter by searching for it's Id
                  Iterator fps = wp.getFormalParameters().toElements().iterator();
                  while (fps.hasNext()) {
                     FormalParameter fp = (FormalParameter) fps.next();
                     if (fpId.equals(fp.getId())) {
                        foundIndex = index;
                        break;
                     }
                     index++;
                  }
                  // if formal parameter is found, put the appropriate actual param
                  // name and formal param value into new context
                  if (foundIndex != -1) {
                     java.lang.Object apId = originalIds.get(foundIndex);
                     updatedContext.put(apId, me.getValue());
                  }
               }
               set_result(shandle, updatedContext);
               finish(shandle);
            } else {
               change_state(shandle, perfState);
               if (perfState.equals(SharkConstants.STATE_CLOSED_TERMINATED)) {
                  process.activity_terminate(shandle, this);
               } else {
                  process.activity_abort(shandle, this);
               }

            }
         } else {
            if (performerId == null) {
               throw new Exception("Activity "
                                   + this + " - this is not remote subflow activity!");
            }
            if (event instanceof WfDataEventAudit) {
               WfDataEventAudit dea = (WfDataEventAudit) event;
               Map res = dea.new_data();
               // TODO: in the future, we'll need another call to wfxml API, to get
               // info about variables to update
               res = SharkEngineManager.getInstance()
                  .getWfEngineInteroperabilityMgr()
                  .parseOutParams(shandle,
                                  processId,
                                  MiscUtilities.createAssignmentKey(key,
                                                                    getResourceRequesterUsername(shandle)),
                                  res,
                                  container(shandle).manager(shandle)
                                     .context_signature(shandle));
               set_result(shandle, res);
            } else if (event instanceof org.enhydra.shark.api.client.wfmodel.WfStateEventAudit
                       && ((org.enhydra.shark.api.client.wfmodel.WfStateEventAudit) event).new_state()
                          .startsWith(SharkConstants.STATEPREFIX_CLOSED)) {
               finish(shandle);
            }
         }
      } catch (Exception ex) {
         SharkEngineManager.getInstance()
            .getCallbackUtilities()
            .error(shandle,
                   "Activity"
                         + toString()
                         + " - problems when receiving finishing event of subprocess");
         // System.err.println(ex.getMessage());
         // ex.printStackTrace();

         throw ex;
      }
   }

   public String activity_set_definition_id(WMSessionHandle shandle) throws Exception {
      return activitySetDefinitionId;
   }

   public String activity_definition_id(WMSessionHandle shandle) throws Exception {
      return activityDefinitionId;
   }

   public String activity_definition_name(WMSessionHandle shandle) throws Exception {
      return getActivityDefinition(shandle).getName();
   }

   public String block_activity_id(WMSessionHandle shandle) throws Exception {
      return blockActivityId;
   }

   public WfActivityInternal block_activity(WMSessionHandle shandle) throws Exception {
      if (blockActivity == null && blockActivityId != null) {
         blockActivity = process.getActivity(shandle, blockActivityId);
      }
      return blockActivity;
   }

   public String manager_name(WMSessionHandle shandle) throws Exception {
      return mgrName;
   }

   public String process_id(WMSessionHandle shandle) throws Exception {
      return processId;
   }

   public int getDefinitionType(WMSessionHandle shandle) throws Exception {
      int type = getActivityDefinition(shandle).getActivityType();
      if (type == XPDLConstants.ACTIVITY_TYPE_TOOL) {
         Participant p = findParticipant(shandle,
                                         getActivityDefinition(shandle).getPerformer());
         boolean isSystemParticipant = p != null
                                       && p.getParticipantType()
                                          .equals((XPDLConstants.PARTICIPANT_TYPE_SYSTEM));
         if (!isSystemParticipant) {
            boolean isManualStart = getActivityDefinition(shandle).getActivityStartMode() == XPDLConstants.ACTIVITY_MODE_MANUAL;
            if (isManualStart) {
               type = 2 * type + 1;
            } else {
               boolean isManualFinish = getActivityDefinition(shandle).getActivityFinishMode() == XPDLConstants.ACTIVITY_MODE_MANUAL;
               if (isManualFinish) {
                  type = 2 * type + 2;
               }
            }
         }
      }
      return type;
   }

   /**
    * Initializes the context of the given activity. Currently, it returns the whole
    * process context for the activities which type is not Route or Block.
    */
   protected void initializeActivityContext(WMSessionHandle shandle) throws Exception {
      // must be linked map to preserve the exact order of parameters,
      // which is important for subflow, and tool activities
      int type = getActivityDefinition(shandle).getActivityType();
      // set the needed process context to activity context
      if (type != XPDLConstants.ACTIVITY_TYPE_ROUTE
          && type != XPDLConstants.ACTIVITY_TYPE_BLOCK) {
         activitiesProcessContext = process.process_context(shandle);
      }
      contextInitialized = true;
   }

   // TODO: what to do with assignments that are already accepted???
   public int reevaluateAssignments(WMSessionHandle shandle) throws Exception {
      checkReadOnly();
      if (!(state(shandle).equals(SharkConstants.STATE_OPEN_NOT_RUNNING_NOT_STARTED) || state(shandle).equals(SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED)))
         return -1;

      List arids = getAssignmentResourceIds(shandle);

      PerformerData xpdlParticipant = findPerformerData(shandle);
      if (xpdlParticipant == null)
         return -1;

      List users = findUsers(shandle, xpdlParticipant);

      List toAdd = new ArrayList(users);
      toAdd.removeAll(arids);

      List toRemove = new ArrayList(arids);
      toRemove.removeAll(users);

      // removing old assignments
      for (int i = 0; i < toRemove.size(); i++) {
         String resUsername = (String) toRemove.get(i);
         removeAssignment(shandle, resUsername, true, false);
      }

      createAssignments(shandle, toAdd);

      if (toAdd.size() != 0 || toRemove.size() != 0) {
         return 1;
      }
      return 0;
   }

   protected PerformerData findPerformerData(WMSessionHandle shandle) throws Exception {
      boolean createAssignments = canCreateAssignments(shandle);
      if (!createAssignments)
         return null;

      int type = getActivityDefinition(shandle).getActivityType();
      if (!(type == XPDLConstants.ACTIVITY_TYPE_NO || type == XPDLConstants.ACTIVITY_TYPE_TOOL)) {
         return null;
      }

      Participant p = findParticipant(shandle,
                                      getActivityDefinition(shandle).getPerformer());
      PerformerData xpdlParticipant = null;

      xpdlParticipant = checkParticipant(shandle, p, type);

      return xpdlParticipant;
   }

   protected List findUsers(WMSessionHandle shandle, PerformerData xpdlParticipant)
      throws Exception {
      if (xpdlParticipant == null)
         return null;

      List users = null;

      AssignmentManager am = getAssignmentManager(shandle);
      if (am != null) {
         List xpdlResponsibleParticipants = new ArrayList();
         List resps = XMLUtil.getResponsibles(getProcessDefinition(shandle));
         Iterator it = resps.iterator();
         int type = getActivityDefinition(shandle).getActivityType();
         while (it.hasNext()) {
            Responsible resp = (Responsible) it.next();
            // if responsible is not unresolved expression, this will return Participant
            // object
            Participant p = findParticipant(shandle, resp.toValue());

            PerformerData pd = checkParticipant(shandle, p, type);
            if (pd != null) {
               xpdlResponsibleParticipants.add(pd);
            }
         }

         users = am.getAssignments(shandle,
                                   processId,
                                   key,
                                   getResourceRequesterUsername(shandle),
                                   xpdlParticipant,
                                   xpdlResponsibleParticipants);
      }

      if (users == null) {
         users = new ArrayList();
      }
      if (users.size() == 0) {
         boolean createDefaultAssignment = createDefaultAssignment(shandle);
         if (createDefaultAssignment) {
            users.add(getResourceRequesterUsername(shandle));
         }
      }

      SecurityManager sm = SharkEngineManager.getInstance().getSecurityManager();
      if (sm != null) {
         users = sm.getAssignments(shandle, processId, key, users);
         if (users == null) {
            users = new ArrayList();
         }
      }

      return users;
   }

   protected void createAssignments(WMSessionHandle shandle, List users) throws Exception {
      if (users == null || users.size() == 0)
         return;

      // optimization in the case of DODS persistence layer
      int lrLimit = 5;
      try {
         lrLimit = Integer.parseInt(SharkEngineManager.getInstance()
            .getCallbackUtilities()
            .getProperty("SharkKernel.LimitForRetrievingAllResourcesWhenCreatingAssignments",
                         "5"));
      } catch (Exception ex) {
      }
      if (users.size() > lrLimit) {
         SharkEngineManager.getInstance()
            .getInstancePersistenceManager()
            .getAllResources(shandle);
      }

      Iterator resourcesIt = users.iterator();
      while (resourcesIt.hasNext()) {
         String username = (String) resourcesIt.next();
         WfResourceInternal wr = SharkUtilities.getResource(shandle, username);
         if (wr == null) {
            wr = SharkEngineManager.getInstance()
               .getObjectFactory()
               .createResource(shandle, username);
         }
         WfAssignmentInternal ass = SharkEngineManager.getInstance()
            .getObjectFactory()
            .createAssignment(shandle, this, wr);
         wr.addAssignment(shandle, ass);
         getAssignmentResourceIds(shandle).add(username);
      }
   }

   protected void createAssignments(WMSessionHandle shandle) throws Exception {
      PerformerData xpdlParticipant = findPerformerData(shandle);

      List users = findUsers(shandle, xpdlParticipant);

      createAssignments(shandle, users);
   }

   protected PerformerData checkParticipant(WMSessionHandle shandle,
                                            Participant p,
                                            int activityType) throws Exception {
      if (p != null) {
         // check if participant is SYSTEM, and if it is, do not create PerformerData,
         // which will indicate not to create any assignments
         String participantType = p.getParticipantType().getType();
         if (participantType.equals(XPDLConstants.PARTICIPANT_TYPE_SYSTEM)) {
            return null;
         }
         String pDefId = null;
         if (p.getParent().getParent() instanceof WorkflowProcess) {
            pDefId = ((WorkflowProcess) p.getParent().getParent()).getId();
         }
         Package pkg = XMLUtil.getPackage(p);
         return new PerformerData(pkg.getId(),
                                  pkg.getInternalVersion(),
                                  pDefId,
                                  p.getId(),
                                  false,
                                  participantType);
      }
      String performerExpr = getActivityDefinition(shandle).getPerformer();
      // check if this is a tool activity with an empty performer, and if it
      // is, do not create PerformerData, which will indicate not to create any
      // assignments
      // if (performerExpr.trim().length()==0 &&
      // activityType==XPDLConstants.ACTIVITY_TYPE_TOOL) {
      // return null;
      // }

      try {
         // if participant is an expression, calculate an expression
         performerExpr = evaluateParticipantExpression(shandle, performerExpr);
      } catch (Exception ex) {
      }

      Package pkg = XMLUtil.getPackage(getActivityDefinition(shandle));
      return new PerformerData(pkg.getId(),
                               pkg.getInternalVersion(),
                               XMLUtil.getWorkflowProcess(getActivityDefinition(shandle))
                                  .getId(),
                               performerExpr.trim(),
                               true,
                               null);
   }

   protected Participant findParticipant(WMSessionHandle shandle, String performerExpr)
      throws Exception {
      Participant p = SharkUtilities.getParticipant(shandle,
                                                    getActivityDefinition(shandle),
                                                    performerExpr);
      if (p == null) {
         try {
            // if participant is an expression, calculate an expression, and
            // try to retrieve the participant
            if (performerExpr.trim().length() > 0) {
               String participantId = evaluateParticipantExpression(shandle,
                                                                    performerExpr);
               p = SharkUtilities.getParticipant(shandle,
                                                 getActivityDefinition(shandle),
                                                 participantId);
               return p;
            }
         } catch (Exception ex) {
         }
      }
      return p;
   }

   // Starts or activates this automatic activity
   protected void startActivity(WMSessionHandle shandle)
      throws Exception,
         CannotStart,
         ToolAgentGeneralException {

      // get the type of this activity
      int type = getActivityDefinition(shandle).getActivityType();
      // log.info("Executing activity " + activity.getId());

      if (type != XPDLConstants.ACTIVITY_TYPE_NO
          && type != XPDLConstants.ACTIVITY_TYPE_TOOL) {
         try {
            change_state(shandle, SharkConstants.STATE_OPEN_RUNNING);
         } catch (InvalidState is) {
            throw new CannotStart("Activity "
                                  + this + " -> can't start: errMsg=" + is.getMessage());
         } catch (TransitionNotAllowed tna) {
            throw new CannotStart("Activity "
                                  + this + " -> can't start: errMsg=" + tna.getMessage());
         } catch (Exception be) {
            throw new CannotStart("Activity "
                                  + this + " -> can't start: errMsg=" + be.getMessage());
         }
      }

      // configure the limit agent - this is handled in change_state
      // this is not a point for all activities

      // set the new previousActivity

      // set the estimatedStartDate

      switch (type) {
         case XPDLConstants.ACTIVITY_TYPE_ROUTE: // Route
            try {
               this.finish(shandle); // ROUTE goes directly to complete status
            } catch (CannotComplete cc) {
               // System.err.println(cc.getMessage());
               throw new CannotStart("Activity " + this + " -> can't start", cc);
            }
            break;
         case XPDLConstants.ACTIVITY_TYPE_NO: // NoImplementation
            this.runNo(shandle);
            break;
         case XPDLConstants.ACTIVITY_TYPE_TOOL: // Tools
            if (getActivityDefinition(shandle).getActivityStartMode() == XPDLConstants.ACTIVITY_MODE_AUTOMATIC) {
               boolean shouldFinishImmediatelly = getActivityDefinition(shandle).getActivityFinishMode() == XPDLConstants.ACTIVITY_MODE_AUTOMATIC;
               this.runTool(shandle);
               if (shouldFinishImmediatelly) {
                  finish(shandle);
               } else {
                  String perf = getActivityDefinition(shandle).getPerformer();
                  Participant p = null;
                  boolean isSystemParPerfOrNoPerf = false;
                  if (!perf.equals("")) {
                     findParticipant(shandle, perf);
                  } else {
                     isSystemParPerfOrNoPerf = true;
                  }

                  if (p != null) {
                     String participantType = p.getParticipantType().getType();
                     if (participantType.equals(XPDLConstants.PARTICIPANT_TYPE_SYSTEM)) {
                        isSystemParPerfOrNoPerf = true;
                     }
                  }
                  if (isSystemParPerfOrNoPerf) {
                     removeAssignments(shandle, true, true);
                  } else {
                     change_state(shandle,
                                  SharkConstants.STATE_OPEN_NOT_RUNNING_NOT_STARTED);
                     this.runNo(shandle);
                  }
               }
            } else {
               this.runNo(shandle);
            }
            break;
         case XPDLConstants.ACTIVITY_TYPE_SUBFLOW: // SubFlow
            startSubflowThread = Thread.currentThread();
            this.runSubFlow(shandle); // Begin a sub workflow
            startSubflowThread = null;
            break;
         case XPDLConstants.ACTIVITY_TYPE_BLOCK: // BlockActivity
            this.runBlock(shandle); // Block activity
            break;
      }
   }

   protected void runNo(WMSessionHandle shandle) throws Exception, CannotStart {
      createAssignments(shandle);
   }

   // Runs a TOOL activity - there can be 0..n
   protected void runTool(WMSessionHandle shandle)
      throws Exception,
         CannotStart,
         ToolAgentGeneralException {

      if (!state(shandle).equals(SharkConstants.STATE_OPEN_RUNNING)) {
         try {
            change_state(shandle, SharkConstants.STATE_OPEN_RUNNING);
         } catch (InvalidState is) {
            throw new CannotStart("Activity "
                                  + this + " -> can't start: errMsg=" + is.getMessage());
         } catch (TransitionNotAllowed tna) {
            throw new CannotStart("Activity "
                                  + this + " -> can't start: errMsg=" + tna.getMessage());
         } catch (Exception be) {
            throw new CannotStart("Activity "
                                  + this + " -> can't start: errMsg=" + be.getMessage());
         }
      }

      ToolActivityHandler tam = SharkEngineManager.getInstance().getToolActivityHandler();
      tam.executeActivity(shandle, this);
   }

   // Runs a SUBFLOW activity
   protected void runSubFlow(WMSessionHandle shandle)
      throws Exception,
         ToolAgentGeneralException {
      SubFlow subflow = getActivityDefinition(shandle).getActivityTypes()
         .getImplementation()
         .getImplementationTypes()
         .getSubFlow();
      if (subflow == null) {
         return;
      }

      // Get actual parameters definition of the subflow activity
      ActualParameters aps = subflow.getActualParameters();
      isSubflowSynchronous = getActivityDefinition(shandle).isSubflowSynchronous();

      String refSbflw = subflow.getId();
      WorkflowProcess wp = SharkUtilities.getWorkflowProcess(shandle, subflow, refSbflw);

      String packageId = process.package_id(shandle);
      String packageVersion = process.manager_version(shandle);

      if (wp != null) {
         // start the process
         WfProcessMgrInternal mgr;
         WfProcessInternal subProc;
         String sbflwPkgId;
         String sbflwPkgVersion;
         String sbflwProcId;

         sbflwPkgId = XMLUtil.getPackage(wp).getId();
         sbflwPkgVersion = XMLUtil.getPackage(wp).getInternalVersion();
         sbflwProcId = refSbflw;
         String pmgrName = MiscUtilities.createProcessMgrKey(sbflwPkgId,
                                                             sbflwPkgVersion,
                                                             sbflwProcId);
         // System.out.println("SPIDWV="+sbflwPkgIdWithVersion+", PMGRN="+pmgrName);
         mgr = SharkUtilities.getProcessMgr(shandle, pmgrName);
         if (mgr == null) {
            throw new Exception("Activity " + this + " - subflow process is not found");
         }

         try {
            subProc = mgr.create_process(shandle, this);
            subProc.set_name(shandle, process.name(shandle) + "-" + this.name(shandle));
         } catch (Exception ex) {
            SharkEngineManager.getInstance()
               .getCallbackUtilities()
               .error(shandle,
                      "Activity" + toString() + " - Error instantiating sub-process");
            throw ex;
         }

         FormalParameters fps = SharkUtilities.getWorkflowProcess(shandle,
                                                                  sbflwPkgId,
                                                                  sbflwPkgVersion,
                                                                  sbflwProcId)
            .getFormalParameters();

         Map m = null;

         m = SharkUtilities.createContextMap(shandle,
                                             processId,
                                             key,
                                             this.getContext(shandle),
                                             aps,
                                             fps,
                                             packageId,
                                             packageVersion);
         subProc.set_process_context(shandle, m);
         performerId = subProc.key(shandle);
         persist(shandle);
         subProc.start(shandle);

         // this is a remote subflow
      } else {
         Map m = SharkUtilities.createContextMap(shandle,
                                                 processId,
                                                 key,
                                                 this.getContext(shandle),
                                                 aps,
                                                 packageId,
                                                 packageVersion);
         String assId = MiscUtilities.createAssignmentKey(key,
                                                          getResourceRequesterUsername(shandle));
         // check if some variable is used to define a reference to remote subflow
         if (this.getContext(shandle).containsKey(refSbflw)) {
            Object rsv = this.getContext(shandle).get(refSbflw);
            if (rsv instanceof String) {
               refSbflw = (String) rsv;
            }
         }

         performerId = SharkEngineManager.getInstance()
            .getWfEngineInteroperabilityMgr()
            .start(shandle, refSbflw, processId, assId, isSubflowSynchronous, m);

         persist(shandle);
      }

      // if this is asynchronous execution, complete activity, otherwise
      // wait until the process calls the receive_event() method
      if (!isSubflowSynchronous) {
         this.finish(shandle);
      }
   }

   // Runs a BLOCK activity
   protected void runBlock(WMSessionHandle shandle) throws Exception {
   }

   /**
    * Complete this activity.
    */
   protected void finishImproperlyAndNotifyProcess(WMSessionHandle shandle, String excName)
      throws Exception {
      // remove assignments first, because method for getting assignments
      // from database depends on activity's state
      removeAssignments(shandle, true, true);

      // The activity can already be terminated it is a sub-flow activity
      if (!state.equals(SharkConstants.STATE_CLOSED_TERMINATED)) {
         change_state(shandle, SharkConstants.STATE_CLOSED_TERMINATED);
      }

      this.exceptionName = excName;

      if (exc == null && excName != null) {
         int type = getActivityDefinition(shandle).getActivityType();
         if (type == XPDLConstants.ACTIVITY_TYPE_SUBFLOW) {
            // if this is a subflow activity, terminate it's process
            // if it is SYNCHRONOUS
            if (isSubflowSynchronous) {
               WfProcessInternal performer = getPerformer(shandle);
               if (performer == null) {
                  SubFlow subflow = getActivityDefinition(shandle).getActivityTypes()
                     .getImplementation()
                     .getImplementationTypes()
                     .getSubFlow();
                  String refSbflw = subflow.getId();
                  WorkflowProcess wp = SharkUtilities.getWorkflowProcess(shandle,
                                                                         subflow,
                                                                         refSbflw);
                  if (wp != null || performerId == null || performerId.equals("")) {
                     throw new Exception("Activity "
                                         + this
                                         + " - null performer of sync. subflow activity");
                  }

                  SharkEngineManager.getInstance()
                     .getWfEngineInteroperabilityMgr()
                     .abort(shandle,
                            performerId,
                            processId,
                            MiscUtilities.createAssignmentKey(key,
                                                              getResourceRequesterUsername(shandle)));

               } else {
                  if (performer.state(shandle)
                     .startsWith(SharkConstants.STATEPREFIX_OPEN)) {
                     performer.terminateFromActivity(shandle);
                  }
               }
            }
         } else if (type == XPDLConstants.ACTIVITY_TYPE_BLOCK) {
            List actActs = process.getAllActiveActivitiesForBlockActivity(shandle, key);
            Iterator it = actActs.iterator();
            while (it.hasNext()) {
               WfActivityInternal act = (WfActivityInternal) it.next();
               act.terminateFromProcess(shandle);
            }
         }
      }

      process.activity_terminate(shandle, this);
   }

   public void set_accepted_status(WMSessionHandle shandle,
                                   boolean accept,
                                   String resourceUname)
      throws Exception,
         CannotAcceptSuspended {
      checkReadOnly();
      if (state(shandle).startsWith(SharkConstants.STATEPREFIX_CLOSED)) {
         throw new Exception("Activity "
                             + this
                             + " - can't change accepted status - activity state is closed"); // activity
         // is
         // closed
      }
      if (state(shandle).equals(SharkConstants.STATE_OPEN_NOT_RUNNING_SUSPENDED)) {
         throw new CannotAcceptSuspended("Activity "
                                         + this
                                         + " - can't accept or reject suspended activity"); // activity
         // is
         // suspended
      }

      boolean handleAAS = handleAllAssignments(shandle);
      boolean accepted = state(shandle).equals(SharkConstants.STATE_OPEN_RUNNING);
      if (accepted && accept && !handleAAS) {
         throw new Exception("Activity "
                             + this + " - someone else already accepted assignment!"); // activity
         // is
         // already
         // accepted
      }

      if (SharkEngineManager.getInstance().getEventAuditManagers().size() > 0) {
         WfResourceInternal res = SharkUtilities.getResource(shandle, resourceUname);
         SharkEngineManager.getInstance()
            .getObjectFactory()
            .createAssignmentEventAuditWrapper(shandle, this, res, res, accept);
      }
      // accept
      boolean deleteOtherAssignments = deleteOtherAssignments(shandle);
      boolean createAssignments = canCreateAssignments(shandle);

      if (accept) {
         // the following must come before change_state where peristing happens
         if (!accepted) {
            acceptedTime = System.currentTimeMillis();
            this.resourceUsername = resourceUname;
         }
         if (createAssignments) {
            if (!handleAAS) {
               removeAssignments(shandle, false, deleteOtherAssignments);
            }
            if (getAssignmentResourceIds(shandle).contains(resourceUname)) {
               setAssignmentStatus(shandle, resourceUname, true, true);
               WfResourceInternal res = SharkUtilities.getResourceFromCache(resourceUname);
               if (res != null) {
                  res.restoreAssignment(shandle, mgrName, processId, key, true);
               }
            }
         }
         if (!accepted) {
            change_state(shandle, SharkConstants.STATE_OPEN_RUNNING);
         } else {
            persist(shandle);
         }

         // reject
      } else {
         if (accepted) {
            int es[] = execution_status(shandle);
            if (createAssignments) {
               setAssignmentStatus(shandle, resourceUname, true, false);
               WfResourceInternal res = SharkUtilities.getResourceFromCache(resourceUname);
               if (res != null) {
                  res.restoreAssignment(shandle, mgrName, processId, key, false);
               }
            }
            if (!handleAAS || (es[0] + es[1]) <= 1) {
               // put activity into not_started status
               change_state(shandle, SharkConstants.STATE_OPEN_NOT_RUNNING_NOT_STARTED);
               this.acceptedTime = SharkConstants.UNDEFINED_TIME;
               this.resourceUsername = null;
               accepted = false;
            }
            if (!handleAAS) {
               if (createAssignments && !deleteOtherAssignments) {
                  Iterator it = getAssignmentResourceIds(shandle).iterator();
                  while (it.hasNext()) {
                     String resUsername = (String) it.next();
                     if (resUsername.equals(resourceUname))
                        continue;
                     setAssignmentStatus(shandle, resUsername, true, false);
                     WfResourceInternal res = SharkUtilities.getResourceFromCache(resUsername);
                     if (res != null) {
                        res.restoreAssignment(shandle, mgrName, processId, key, false);
                     }
                  }
               }
            }
            persist(shandle);

            if (!handleAAS && createAssignments && deleteOtherAssignments) {
               reevaluateAssignments(shandle);
            }
         }
      }
   }

   public String getResourceUsername(WMSessionHandle shandle) throws Exception {
      return resourceUsername;
   }

   protected Activity getActivityDefinition(WMSessionHandle shandle) throws Exception {
      if (activityDefinition == null) {
         activityDefinition = SharkUtilities.getActivityDefinition(shandle,
                                                                   this,
                                                                   getProcessDefinition(shandle));
      }
      return activityDefinition;
   }

   protected WorkflowProcess getProcessDefinition(WMSessionHandle shandle)
      throws Exception {
      if (processDefinition == null) {
         String packageId = process.package_id(shandle);
         String packageVer = process.manager_version(shandle);
         String pDefId = process.process_definition_id(shandle);
         processDefinition = SharkUtilities.getWorkflowProcess(shandle,
                                                               packageId,
                                                               packageVer,
                                                               pDefId);
      }
      return processDefinition;
   }

   public String toString() {
      return "[Process Id="
             + processId + ", Id=" + key + ", ba=" + blockActivityId + ", ActDefId="
             + activityDefinitionId + "]";
   }

   protected synchronized void setActivityVariables(WMSessionHandle shandle)
      throws Exception {
      if (contextInitialized) {
         return;
      }
      // System.out.println("SPVCVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV");
      // initialize context, just to keep the order of variables
      // initializeActivityContext(t);
      resultVariableIds = new HashSet();

      int type = getActivityDefinition(shandle).getActivityType();
      // ROUTE AND BLOCK Activities do not have a context
      if (type == XPDLConstants.ACTIVITY_TYPE_ROUTE
          || type == XPDLConstants.ACTIVITY_TYPE_BLOCK) {
         return;
      }

      WorkflowProcess wp = getProcessDefinition(shandle);
      List l = new ArrayList(wp.getAllVariables().values());

      if (l.size() == 0)
         return;

      PersistentManagerInterface ipm = SharkEngineManager.getInstance()
         .getInstancePersistenceManager();

      // System.err.println("INIT PC="+processContext);
      Iterator it = l.iterator();
      List variableIds = new ArrayList();
      while (it.hasNext()) {
         XMLCollectionElement dfOrFp = (XMLCollectionElement) it.next();
         String vdId = dfOrFp.getId();
         variableIds.add(vdId);
      }
      l = ipm.getActivityVariables(shandle, processId, key, variableIds);
      it = l.iterator();
      while (it.hasNext()) {
         ActivityVariablePersistenceObject var = (ActivityVariablePersistenceObject) it.next();
         String vdId = var.getDefinitionId();
         Object val = var.getValue();
         // System.out.println("Restoring act var "+vdId+", val="+val);
         // if (anyVal!=null) {
         activitiesProcessContext.put(vdId, val);
         if (var.isResultVariable()) {
            resultVariableIds.add(vdId);
         }
         //
      }
      contextInitialized = true;
      // System.err.println("REFILLED AC="+activitiesProcessContext);
   }

   /**
    * It is assumed that there can't be two or more activities having the same key.
    */
   public boolean equals(java.lang.Object obj) {
      if (!(obj instanceof WfActivityImpl))
         return false;

      return ((WfActivityImpl) obj).key.equals(key);
   }

   public int hashCode() {
      return key.hashCode();
   }

   protected String evaluateParticipantExpression(WMSessionHandle shandle, String expr)
      throws Exception {
      if (expr == null || expr.trim().length() == 0)
         throw new Exception("Activity " + this + " - improper participant expression!");
      // use process_context - these are cloned variables
      return evaluator(shandle).evaluateExpression(shandle,
                                                   processId,
                                                   key,
                                                   expr.trim(),
                                                   process_context(shandle),
                                                   java.lang.String.class).toString();
   }

   protected Evaluator evaluator(WMSessionHandle shandle) throws Exception {
      if (evaluator == null) {
         evaluator = SharkEngineManager.getInstance()
            .getScriptingManager()
            .getEvaluator(shandle,
                          SharkUtilities.getScriptType(shandle,
                                                       process.package_id(shandle),
                                                       process.manager_version(shandle)));
      }

      return evaluator;
   }

   protected WfProcessInternal getPerformer(WMSessionHandle shandle) throws Exception {
      if (performerId != null) {
         return SharkUtilities.getProcess(shandle, performerId, SharkUtilities.WRITE_MODE);
      }

      return null;
   }

   public String getResourceRequesterUsername(WMSessionHandle shandle) throws Exception {
      return process.requester(shandle).getResourceRequesterUsername(shandle);
   }

   public WfRequester getExternalRequester(WMSessionHandle shandle) throws Exception {
      return null;
   }

   public void setExternalRequester(WMSessionHandle shandle, WfRequester extReq)
      throws Exception {
      return;
   }

   protected int[] execution_status(WMSessionHandle shandle) throws Exception {
      List l = SharkEngineManager.getInstance()
         .getInstancePersistenceManager()
         .getAllAssignmentsForActivity(shandle, processId, key);
      int[] hm = {
            0, 0, 0
      };
      for (int i = 0; i < l.size(); i++) {
         AssignmentPersistenceObject po = (AssignmentPersistenceObject) l.get(i);
         if (!po.isValid()) {
            hm[0]++;
         } else if (po.isAccepted()) {
            hm[1]++;
         } else {
            hm[2]++;
         }
      }
      return hm;
   }

   public void persist(WMSessionHandle shandle) throws Exception {
      // System.err.println("The act "+this+" is being persisted with thread
      // "+Thread.currentThread());
      // System.err.println(" The act "+key+" is being persisted:");
      PersistentManagerInterface pmi = SharkEngineManager.getInstance()
         .getInstancePersistenceManager();

      pmi.persist(shandle, createAndFillPersistentObject(), this.justCreated);
      // persistActivityContext(t);
      this.justCreated = false;
      // delete assignments if needed
      /*
       * if (deleteAssignments) { Iterator aRes=getAssignmentResourceIds(t).iterator();
       * while (aRes.hasNext()) { String resKey=(String)aRes.next();
       * //System.err.println(" The act "+key+" is deleting its assignment for resource
       * "+resKey); pmi.deleteAssignment(key,resKey,t.getSharkTransaction()); }
       * deleteAssignments=false; }
       */

      /*
       * if (deadlinesInfo!=null && deadlinesInfo.size()>0) { persistDeadlines(t); }
       */
   }

   /**
    * Method persistActivityContext stores content of the workflow relevant data of this
    * activity, either all of them, or modified only.
    * 
    * @exception Exception
    */
   protected void persistActivityContext(WMSessionHandle shandle) throws Exception {
      if (variableIdsToPersist.size() == 0)
         return;

      PersistentManagerInterface pmgr = SharkEngineManager.getInstance()
         .getInstancePersistenceManager();
      // System.out.println("Persisting act var map="+getContext(t));
      Iterator it = getContext(shandle).entrySet().iterator();
      while (it.hasNext()) {
         Map.Entry me = (Map.Entry) it.next();
         String defId = (String) me.getKey();
         // boolean modifiedOnly = (null != modified);
         // if (!modifiedOnly||(modifiedOnly && modified.contains(defId))) {
         if (variableIdsToPersist.contains(defId)) {
            Object val = me.getValue();
            ActivityVariablePersistenceObject var = new ActivityVariablePersistenceObject();
            var.setProcessId(processId);
            var.setActivityId(key);
            var.setDefinitionId(defId);
            var.setValue(val);
            var.setResultVariable(getResultVariableIds(shandle).contains(defId));
            pmgr.persist(shandle, var, this.justCreatedVariables);
            // System.out.println("Persisting activity variable "+defId+", val="+val+"
            // for activity "+key+" of process "+processId);
         }
      }
      variableIdsToPersist.clear();
      this.justCreatedVariables = false;
   }

   protected void persistDeadlines(WMSessionHandle shandle) throws Exception {
      if (deadlinesInfo == null || deadlinesInfo.size() == 0)
         return;

      PersistentManagerInterface pmgr = SharkEngineManager.getInstance()
         .getInstancePersistenceManager();
      Iterator it = deadlinesInfo.iterator();
      while (it.hasNext()) {
         DeadlineInfo dinfo = (DeadlineInfo) it.next();
         DeadlinePersistenceObject dpi = new DeadlinePersistenceObject();
         dpi.setProcessId(processId);
         dpi.setActivityId(key);
         dpi.setExceptionName(dinfo.exceptionName);
         dpi.setSynchronous(dinfo.isSynchronous);
         dpi.setTimeLimit(dinfo.timeLimit);
         pmgr.persist(shandle, dpi, justCreatedDeadlines);
      }
      deadlinesInfo.clear();
      this.justCreatedDeadlines = false;
   }

   protected void persistExecutedDeadline(WMSessionHandle shandle, String uniqueId)
      throws Exception {
      PersistentManagerInterface pmgr = SharkEngineManager.getInstance()
         .getInstancePersistenceManager();
      DeadlinePersistenceObject dpi = new DeadlinePersistenceObject();
      dpi.setProcessId(processId);
      dpi.setActivityId(key);
      dpi.setUniqueId(uniqueId);
      dpi.setExecuted(true);
      pmgr.persist(shandle, dpi, false);
   }

   public void delete(WMSessionHandle shandle) throws Exception {
      // try {System.err.println("Deleting activity "+key());}catch (Exception ex){};
      SharkEngineManager.getInstance()
         .getInstancePersistenceManager()
         .deleteActivity(shandle, processId, key);
   }

   protected XMLCollectionElement getXPDLObject(WMSessionHandle shandle) throws Exception {
      return getActivityDefinition(shandle);
   }

   public Map getContext(WMSessionHandle shandle) throws Exception {
      if (!contextInitialized) {
         setActivityVariables(shandle);
      }
      return activitiesProcessContext;
   }

   protected Set getResultVariableIds(WMSessionHandle shandle) throws Exception {
      if (resultVariableIds == null) {
         setActivityVariables(shandle);
      }
      return resultVariableIds;
   }

   protected ActivityPersistenceObject createAndFillPersistentObject() {
      ActivityPersistenceObject po = new ActivityPersistenceObject();
      fillPersistentObject(po);
      return po;
   }

   protected void fillPersistentObject(ActivityPersistenceObject po) {
      po.setId(this.key);
      po.setActivitySetDefinitionId(this.activitySetDefinitionId);
      po.setActivityDefinitionId(this.activityDefinitionId);
      po.setProcessMgrName(this.mgrName);
      po.setProcessId(this.processId);
      po.setResourceUsername(this.resourceUsername);
      po.setSubflowProcessId(this.performerId);
      po.setSubflowAsynchronous(!this.isSubflowSynchronous);
      po.setState(this.state);
      po.setBlockActivityId(this.blockActivityId);
      po.setName(this.name);
      po.setDescription(this.description);
      po.setPriority(this.priority);
      po.setAcceptedTime(this.acceptedTime);
      po.setActivatedTime(this.activatedTime);
      po.setLastStateTime(this.lastStateTime);
      po.setLimitTime(limitTime);
   }

   protected void restore(ActivityPersistenceObject po) {
      this.key = po.getId();
      this.activitySetDefinitionId = po.getActivitySetDefinitionId();
      this.activityDefinitionId = po.getActivityDefinitionId();
      this.mgrName = po.getProcessMgrName();
      this.processId = po.getProcessId();
      this.resourceUsername = po.getResourceUsername();
      this.performerId = po.getSubflowProcessId();
      this.isSubflowSynchronous = !po.isSubflowAsynchronous();
      this.state = po.getState();
      this.blockActivityId = po.getBlockActivityId();
      this.name = po.getName();
      this.description = po.getDescription();
      this.priority = po.getPriority();
      this.acceptedTime = po.getAcceptedTime();
      this.activatedTime = po.getActivatedTime();
      this.lastStateTime = po.getLastStateTime();
      this.limitTime = po.getLimitTime();
   }

   public String getPerformerId(WMSessionHandle shandle) {
      return performerId;
   }

   public boolean isPerformerSynchronous(WMSessionHandle shandle) {
      return isSubflowSynchronous;
   }

   public long getCreationTime(WMSessionHandle shandle) throws Exception {
      return activatedTime;
   }

   public long getStartTime(WMSessionHandle shandle) throws Exception {
      return acceptedTime;
   }

   public synchronized void updateAssignmentResourceIds(WMSessionHandle shandle,
                                                        String oldResUname,
                                                        String newResUname)
      throws Exception {
      checkReadOnly();
      if (assignmentResourceIds != null) {
         assignmentResourceIds.remove(oldResUname);
         if (!assignmentResourceIds.contains(newResUname)) {
            assignmentResourceIds.add(newResUname);
         }
      }

      if (this.resourceUsername != null && this.resourceUsername.equals(oldResUname)) {
         this.resourceUsername = newResUname;

         persist(shandle);
      }
   }

   protected synchronized void removeAssignments(WMSessionHandle shandle,
                                                 boolean removeActiveOne,
                                                 boolean deleteOtherAssignments)
      throws Exception {
      int actType = getActivityDefinition(shandle).getActivityType();
      if (actType == XPDLConstants.ACTIVITY_TYPE_BLOCK
          || actType == XPDLConstants.ACTIVITY_TYPE_ROUTE
          || actType == XPDLConstants.ACTIVITY_TYPE_SUBFLOW)
         return;

      boolean createAssignments = canCreateAssignments(shandle);
      if (!createAssignments)
         return;
      Iterator itAss = new ArrayList(getAssignmentResourceIds(shandle)).iterator();
      while (itAss.hasNext()) {
         String resUsername = (String) itAss.next();
         if (!removeActiveOne && resUsername.equals(resourceUsername))
            continue;
         removeAssignment(shandle, resUsername, deleteOtherAssignments, false);
      }
   }

   protected void removeAssignment(WMSessionHandle shandle,
                                   String resUsername,
                                   boolean delete,
                                   boolean assStat) throws Exception {
      PersistentManagerInterface pmi = SharkEngineManager.getInstance()
         .getInstancePersistenceManager();

      WfResourceInternal res = SharkUtilities.getResourceFromCache(resUsername);
      if (delete) {
         pmi.deleteAssignment(shandle, processId, key, resUsername);
         getAssignmentResourceIds(shandle).remove(resUsername);
      } else {
         setAssignmentStatus(shandle, resUsername, false, assStat);
      }

      if (res != null) {
         res.removeAssignment(shandle, processId, key);
      }
   }

   protected void setAssignmentStatus(WMSessionHandle shandle,
                                      String resUsername,
                                      boolean isValid,
                                      boolean isAccepted) throws Exception {
      PersistentManagerInterface pmi = SharkEngineManager.getInstance()
         .getInstancePersistenceManager();
      AssignmentPersistenceObject asspo = new AssignmentPersistenceObject();
      asspo.setProcessMgrName(mgrName);
      asspo.setProcessId(processId);
      asspo.setActivityId(key);
      asspo.setResourceUsername(resUsername);
      asspo.setValid(isValid);
      asspo.setAccepted(isAccepted);
      pmi.persist(shandle, asspo, false);
      // System.out.println("PA "+asspo.getActivityId()+",
      // "+asspo.getResourceUsername()+", a="+asspo.isAccepted()+",
      // v="+asspo.isValid());
   }

   public List getDeadlineInfo(WMSessionHandle shandle) throws Exception {
      List ret = null;
      List pDeadlines = null;

      pDeadlines = SharkEngineManager.getInstance()
         .getInstancePersistenceManager()
         .getAllDeadlinesForActivity(shandle, this.processId, this.key);
      Collections.sort(pDeadlines, new DeadlineComparator());

      if (pDeadlines == null || pDeadlines.size() == 0)
         return new ArrayList();

      if (!performDeadlineReevaluation()) {
         ret = new ArrayList();
         for (Iterator iter = pDeadlines.iterator(); iter.hasNext();) {
            DeadlinePersistenceObject dpo = (DeadlinePersistenceObject) iter.next();
            DeadlineInfo info = new DeadlineInfo(processId,
                                                 key,
                                                 dpo.isExecuted(),
                                                 dpo.getTimeLimit(),
                                                 dpo.getExceptionName(),
                                                 dpo.isSynchronous());
            ret.add(info);
         }
      } else {
         ret = new ArrayList(reevaluateDeadlines(shandle));

         for (int i = 0; i < ret.size(); i++) {
            DeadlineInfo di = (DeadlineInfo) ret.get(i);
            DeadlinePersistenceObject dpo = (DeadlinePersistenceObject) pDeadlines.get(i);
            di.isExecuted = dpo.isExecuted();
         }
      }

      return ret;
   }

   public boolean checkDeadlines(WMSessionHandle shandle,
                                 long timeLimitBoundary,
                                 Map actsToAsyncExcNames) throws Exception {
      checkReadOnly();
      String syncDeadlineExcName = null;
      List brokenDeadlines = null;
      List excNames = new ArrayList();
      if (performDeadlineReevaluation()) {
         List pDeadlines = null;

         pDeadlines = SharkEngineManager.getInstance()
            .getInstancePersistenceManager()
            .getAllDeadlinesForActivity(shandle, this.processId, this.key);
         Collections.sort(pDeadlines, new DeadlineComparator());
         reevaluateDeadlines(shandle);
         brokenDeadlines = new ArrayList();
         for (int i = 0; i < pDeadlines.size(); i++) {
            DeadlineInfo di = (DeadlineInfo) deadlinesInfo.get(i);
            DeadlinePersistenceObject dpo = (DeadlinePersistenceObject) pDeadlines.get(i);
            if (di.timeLimit < timeLimitBoundary) {
               dpo.setTimeLimit(di.timeLimit);
               brokenDeadlines.add(dpo);
            }
         }

         deadlinesInfo.clear();
      } else {
         brokenDeadlines = SharkEngineManager.getInstance()
            .getInstancePersistenceManager()
            .getAllDeadlinesForActivity(shandle,
                                        this.processId,
                                        this.key,
                                        timeLimitBoundary);
      }

      if (brokenDeadlines != null && brokenDeadlines.size() > 0) {
         boolean raiseAsyncDeadlineOnce = new Boolean(SharkEngineManager.getInstance()
            .getCallbackUtilities()
            .getProperty("Deadlines.raiseAsyncDeadlineOnlyOnce", "true")).booleanValue();

         for (int i = 0; i < brokenDeadlines.size(); i++) {
            DeadlinePersistenceObject dpi = (DeadlinePersistenceObject) brokenDeadlines.get(i);
            if (dpi.isExecuted() && raiseAsyncDeadlineOnce) {
               continue;
            }
            persistExecutedDeadline(shandle, dpi.getUniqueId());
            String excName = dpi.getExceptionName();
            if (dpi.isSynchronous()) {
               syncDeadlineExcName = excName;
               break;
            }
            if (!excNames.contains(excName)) {
               excNames.add(excName);
            }
         }
      }

      if (syncDeadlineExcName != null) {
         finishImproperlyAndNotifyProcess(shandle, syncDeadlineExcName);
      } else {
         if (excNames.size() > 0) {
            actsToAsyncExcNames.put(this, excNames);
         }
         int type = getActivityDefinition(shandle).getActivityType();
         // if this is block activity, handle its content deadlines
         if (type == XPDLConstants.ACTIVITY_TYPE_BLOCK) {
            List actActs = process.getAllActiveActivitiesForBlockActivity(shandle, key);
            Iterator it = actActs.iterator();
            while (it.hasNext()) {
               Map ataens = new HashMap();
               WfActivityInternal act = (WfActivityInternal) it.next();
               boolean syncDeadlineHappened = act.checkDeadlines(shandle,
                                                                 timeLimitBoundary,
                                                                 ataens);
               if (syncDeadlineHappened) {
                  continue;
               }
               if (ataens.size() > 0) {
                  actsToAsyncExcNames.putAll(ataens);
               }
            }
         }
      }
      return (syncDeadlineExcName != null);
   }

   protected List reevaluateDeadlines(WMSessionHandle shandle) throws Exception {
      Iterator dls = getActivityDefinition(shandle).getDeadlines()
         .toElements()
         .iterator();

      deadlinesInfo = new ArrayList();
      while (dls.hasNext()) {
         Deadline dl = (Deadline) dls.next();
         String dc = dl.getDeadlineCondition();
         String en = dl.getExceptionName();
         boolean isSynchronous = dl.getExecution().equals(XPDLConstants.EXECUTION_SYNCHR);
         Map context = null;
         String useProcessContextStr = SharkEngineManager.getInstance()
            .getCallbackUtilities()
            .getProperty("Deadlines.useProcessContext", "false");

         if (Boolean.valueOf(useProcessContextStr).booleanValue()) {
            context = this.process.process_context(shandle);
         } else {
            context = this.process_context(shandle);
         }

         context.put(SharkConstants.PROCESS_STARTED_TIME,
                     new java.util.Date(process.getStartTime(shandle)));
         context.put(SharkConstants.ACTIVITY_ACCEPTED_TIME,
                     new java.util.Date(this.acceptedTime));
         context.put(SharkConstants.ACTIVITY_ACTIVATED_TIME,
                     new java.util.Date(this.activatedTime));
         long timeLimit = ((java.util.Date) evaluator(shandle).evaluateExpression(shandle,
                                                                                  processId,
                                                                                  key,
                                                                                  dc,
                                                                                  context,
                                                                                  java.util.Date.class)).getTime();
         DeadlineInfo dinfo = new DeadlineInfo(processId,
                                               key,
                                               false,
                                               timeLimit,
                                               en,
                                               isSynchronous);
         deadlinesInfo.add(dinfo);
         // System.out.println("Act "+this+" re-evaluated deadline "+dinfo);
      }
      return deadlinesInfo;
   }

   public Exception getException(WMSessionHandle shandle) {
      return exc;
   }

   public void setException(WMSessionHandle shandle, Exception tage) {
      this.exc = tage;
   }

   public String getExceptionName(WMSessionHandle shandle) {
      return exceptionName;
   }

   public void setExceptionName(WMSessionHandle shandle, String excName) {
      this.exceptionName = excName;
   }

   protected boolean performDeadlineReevaluation() {
      String reevalStr = SharkEngineManager.getInstance()
         .getCallbackUtilities()
         .getProperty("Deadlines.reevaluateDeadlines", "true");
      return Boolean.valueOf(reevalStr).booleanValue();
   }

   static class DeadlineComparator implements Comparator {
      public int compare(Object o1, Object o2) {
         DeadlinePersistenceObject dd1 = (DeadlinePersistenceObject) o1;
         DeadlinePersistenceObject dd2 = (DeadlinePersistenceObject) o2;
         String ui1 = dd1.getUniqueId();
         String ui2 = dd2.getUniqueId();

         return ui1.compareTo(ui2);
      }
   }

   public WfActivityInternal duplicate(WfProcessInternal proc) throws Exception {
      WfActivityImpl actImpl = (WfActivityImpl) SharkEngineManager.getInstance()
         .getObjectFactory()
         .createActivity(createAndFillPersistentObject(), proc);
      actImpl.lastStateEventAudit = this.lastStateEventAudit;
      actImpl.evaluator = this.evaluator;
      actImpl.activityDefinition = this.activityDefinition;
      actImpl.processDefinition = this.processDefinition;
      actImpl.startSubflowThread = this.startSubflowThread;
      if (this.contextInitialized) {
         try {
            actImpl.activitiesProcessContext = this.duplicateContext(activitiesProcessContext);
            actImpl.resultVariableIds = new HashSet(this.resultVariableIds);
            actImpl.contextInitialized = true;
         } catch (Exception ex) {
         }
      }

      return actImpl;
   }

   protected void checkReadOnly() throws Exception {
      if (process.isReadOnly()) {
         throw new Exception("Activity " + this + " is read-only!");
      }
   }

   protected boolean canCreateAssignments(WMSessionHandle shandle) throws Exception {
      boolean createAssignments = Boolean.valueOf(SharkEngineManager.getInstance()
         .getCallbackUtilities()
         .getProperty("SharkKernel.createAssignments", "true")).booleanValue();
      return createAssignments;
   }

   protected boolean createDefaultAssignment(WMSessionHandle shandle) throws Exception {
      boolean createDefaultAssignment = Boolean.valueOf(SharkEngineManager.getInstance()
         .getCallbackUtilities()
         .getProperty("SharkKernel.createDefaultAssignment", "true")).booleanValue();
      return createDefaultAssignment;
   }

   protected boolean deleteOtherAssignments(WMSessionHandle shandle) throws Exception {
      return Boolean.valueOf(SharkEngineManager.getInstance()
         .getCallbackUtilities()
         .getProperty("SharkKernel.deleteOtherAssignments", "true")).booleanValue();
   }

   protected AssignmentManager getAssignmentManager(WMSessionHandle shandle)
      throws Exception {
      return SharkEngineManager.getInstance().getAssignmentManager();
   }

   protected boolean handleAllAssignments(WMSessionHandle shandle) throws Exception {
      return false;
   }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.