Package org.uengine.kernel

Source Code of org.uengine.kernel.EJBProcessInstance

package org.uengine.kernel;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.uengine.contexts.ComplexType;
import org.uengine.persistence.dao.UniqueKeyGenerator;
import org.uengine.persistence.processinstance.ProcessInstanceDAO;
import org.uengine.persistence.processinstance.ProcessInstanceDAOType;
import org.uengine.persistence.processvariable.ProcessVariableDAO;
import org.uengine.persistence.processvariable.ProcessVariableDAOType;
import org.uengine.persistence.rolemapping.RoleMappingDAO;
import org.uengine.persistence.rolemapping.RoleMappingDAOType;
import org.uengine.processmanager.ProcessTransactionContext;
import org.uengine.processmanager.SimulatorTransactionContext;
import org.uengine.processmanager.TransactionContext;
import org.uengine.util.MeasuringContext;
import org.uengine.util.UEngineUtil;
import org.uengine.webservices.worklist.WorkList;
import org.uengine.webservices.worklist.WorkListServiceLocator;
//

/**
* @author Jinyoung Jang
*/

public class EJBProcessInstance extends DefaultProcessInstance implements TransactionListener {
 
  private static final long serialVersionUID = org.uengine.kernel.GlobalContext.SERIALIZATION_UID;

  protected final static int TYPE_NULL   = -2;
  protected final static int TYPE_ANY   = -1;
  protected final static int TYPE_STRING   = 1;
  protected final static int TYPE_INTEGER = 2;
  protected final static int TYPE_LONG   = 3;
  protected final static int TYPE_BOOLEAN = 4;
  protected final static int TYPE_DATE   = 5;
  protected final static int TYPE_CALENDAR= 6;
//  protected final static int TYPE_FORMCONTEXT= 7;

  //dirty field list for synchronizing when endCaching()
  Map modifiedKeyMap;
  Map modifiedRoleMappings;
  Map cachedRoleMappings;
  //
 
  //for caching
  boolean caching;
    public boolean isCaching() {
      return caching;
    }
    public void setCaching(boolean b) {
      caching = b;
    }
 
  boolean processVariablesAreCached = false;
  boolean roleMappingsAreCached = false;
  boolean isNew = false;
  //
 
//  ProcessInstanceRepositoryLocal processInstanceRepositoryLocal;
//  public ProcessInstanceRepositoryLocal getProcessInstanceRepositoryLocal() throws Exception{
//    if(processInstanceRepositoryLocal == null){
//      ProcessInstanceRepositoryHomeLocal pirh = GlobalContext.createProcessInstanceRepositoryHomeLocal();
//      processInstanceRepositoryLocal = pirh.findByPrimaryKey(new Long(getInstanceId()));
//    }
//   
//    return processInstanceRepositoryLocal;     
//  }

  ProcessInstanceDAO processInstanceDAO;
  public ProcessInstanceDAO getProcessInstanceDAO() throws Exception{
    if(processInstanceDAO == null){
      ProcessInstanceDAOType pidt = ProcessInstanceDAOType.getInstance(getProcessTransactionContext());
      processInstanceDAO = pidt.findByPrimaryKey(new Long(getInstanceId()));
      processInstanceDAO.getImplementationObject().setTableName("BPM_PROCINST");
      processInstanceDAO.getImplementationObject().setKeyField("INSTID");
      processInstanceDAO.getImplementationObject().createUpdateSql();
    }
   
    return processInstanceDAO;
  }

  ProcessVariableDAOType pvdf;
  public ProcessVariableDAOType getProcessVariableDAOFacade() {
    if(pvdf==null){
      pvdf = ProcessVariableDAOType.getInstance(ptc);
    }
   
    return pvdf;
  }
   
  public EJBProcessInstance (ProcessDefinition procDef, String name, Map options) throws Exception{
    setCaching(true);
   
    //isNew field is for recognizing the instance is just initiated in the transaction.
    // when the argument procDef is provided, it means also initiation stage.
    if(procDef != null)
      isNew = true;
   
    //creates an instance for the use of factory logic if definition is null
    if(procDef==null) return;     
   
    if ( (getProcessTransactionContext()==null || (getProcessTransactionContext() instanceof SimulatorTransactionContext)) && options != null && options.get("ptc") != null ) {
      super.setProcessTransactionContext( (ProcessTransactionContext)options.get("ptc") );
    }
   
    getProcessTransactionContext().addTransactionListener(this);
   
    Long instanceId = UniqueKeyGenerator.issueProcessInstanceKey(getProcessTransactionContext());
   
    ProcessInstanceDAOType pidt = ProcessInstanceDAOType.getInstance(getProcessTransactionContext());
    processInstanceDAO = pidt.createDAOImpl(null);
       
    processInstanceDAO.setStatus(Activity.STATUS_READY);
    processInstanceDAO.setDefName(procDef.getName().getText());
    processInstanceDAO.setInstId(instanceId);
    processInstanceDAO.setDefModDate(procDef.getModifiedDate().getTime());
   
    setInstanceId(""+processInstanceDAO.getInstId());
 
    if(!UEngineUtil.isNotEmpty(name))
      name = procDef.getName().getText() + instanceId;
     
    processInstanceDAO.setName(name);
    setName(name);
   
    Date now = GlobalContext.getNow(getProcessTransactionContext()).getTime();
    processInstanceDAO.setStartedDate(now);
   
    boolean isSubProcess =
      options!=null
        && options.containsKey("isSubProcess")
        && options.get("isSubProcess").equals("yes")
      );
     
    if(isSubProcess){
      processInstanceDAO.setIsSubProcess(true);     
      processInstanceDAO.setMainInstId(new Long((String)options.get(DefaultProcessInstance.RETURNING_PROCESS)));
      processInstanceDAO.setMainActTrcTag((String)options.get(DefaultProcessInstance.RETURNING_TRACINGTAG));
      processInstanceDAO.setMainExecScope((String)options.get(DefaultProcessInstance.RETURNING_EXECSCOPE));
      processInstanceDAO.setDontReturn(((Boolean)options.get(DefaultProcessInstance.DONT_RETURN)).booleanValue());
      processInstanceDAO.setIsEventHandler(options.containsKey("isEventHandler"));
    }
   
    if(options.containsKey(DefaultProcessInstance.ROOT_PROCESS)){
      processInstanceDAO.setRootInstId(new Long((String)options.get(DefaultProcessInstance.ROOT_PROCESS)));
    }else{
      processInstanceDAO.setRootInstId(instanceId);
    }

    processInstanceDAO.setDefVerId(new Long(procDef.getId()));
    processInstanceDAO.setDefId(new Long(procDef.getBelongingDefinitionId()));
   
    getProcessTransactionContext().registerProcessInstance(this);
  }

  public EJBProcessInstance () throws Exception{
    setInstanceId(null);
  }
 
  public String getMainActivityTracingTag(){
    try {
      return getProcessInstanceDAO().getMainActTrcTag();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public ProcessInstance getInstance(String instanceId) throws Exception{
    return this.getInstance(instanceId, null);
  }
 
  //TODO hotspot
  public ProcessInstance getInstance(String instanceId, Map options) throws Exception{

    if(!UEngineUtil.isNotEmpty(instanceId)){
      throw new UEngineException("Check your parameter! Instance Id is null");
     
/*      EJBProcessInstance tempInst =  new EJBProcessInstance();
      tempInst.setCaching(true);
      tempInst.setInstanceId( null);
      if (options != null && options.get("ptc") != null ) {
        tempInst.setProcessTransactionContext( (TransactionContext)options.get("ptc") );
      }
     
      return tempInst;
*/    }
   
    ProcessTransactionContext ptc = getProcessTransactionContext();
    if (options != null && options.containsKey("ptc")) {
      ptc = (ProcessTransactionContext)options.get("ptc");
    }
   
    if(ptc==null)
      throw new UEngineException("TransactionContext should be provided.");
   
    setProcessTransactionContext(ptc);

    if(isCaching()){
      ProcessInstance instance = ptc.getProcessInstanceInTransaction(instanceId);
      if(instance!=null)
        return instance;
    }
   
    try{
addDebugInfo("EJBProcessInstance: instanceId is set by " + instanceId);


      setInstanceId(instanceId);
      boolean isArchive = getProcessInstanceDAO().getIsArchive();
     
      if(GlobalContext.logLevelIsDebug){
        addDebugInfo("Definition administration url",GlobalContext.WEB_CONTEXT_ROOT + "/processmanager/viewProcessFlowChart.jsp?processDefinition=" + getProcessInstanceDAO().getDefId() + "&processDefinitionVersionID=" + getProcessInstanceDAO().getDefVerId());
        addDebugInfo("Process Designer launch url",GlobalContext.WEB_CONTEXT_ROOT + "/processmanager/ProcessDesigner.jnlp?defVerId=" + getProcessInstanceDAO().getDefVerId() + "&defId=" + getProcessInstanceDAO().getDefId());
        addDebugInfo("Instance administration url", GlobalContext.WEB_CONTEXT_ROOT + "/processmanager/viewProcessInformation.jsp?instanceId=" + getInstanceId());
      }
     
     
      //if the instance is archived, the instance would be loaded from a serialized XML file.
      if(isArchive){
        return FileProcessArchive.load(instanceId, ptc);
      }
//      ProcessInstance inst = create();
//      inst.setInstanceId(instanceId);
//   
//      return inst;
      getProcessTransactionContext().addTransactionListener(this);
      ptc.registerProcessInstance(this);
     
      //if the instance has been retreived by instanceId, it tells us it is not newly initiated status.
      isNew = false;
     
      return this;
     
    //The case that there's no such instance record in bpm_procinst. Perhaps the instance is archived.
    }catch(javax.ejb.ObjectNotFoundException onfe){
     
      //try to find in file system
      try{
        return FileProcessArchive.load(instanceId, ptc);
      }catch(Exception e){
        throw new UEngineException("No such process instance.");
      }     
    }
  }
 
  public void applyChanges() throws Exception{
    MeasuringContext mc = new MeasuringContext("EJBProcessInstance:applyChanges()");
   
    ProcessInstanceDAO procInsDAO = getProcessInstanceDAO();
    procInsDAO.getImplementationObject().setTableName("BPM_PROCINST");
    procInsDAO.getImplementationObject().setKeyField("INSTID");
    procInsDAO.setModDate(GlobalContext.getNow(getProcessTransactionContext()).getTime());
   
    if(isNew){
      procInsDAO.getImplementationObject().createInsertSql();
    }else{
      procInsDAO.getImplementationObject().createUpdateSql();
    }
   
   
    //TODO Checking for dirty field is needed
    procInsDAO.update();

    mc.printElapsedTime(this);

    if(modifiedKeyMap!=null){
      //System.out.println("modifiedKeyMap.size() ===========================> " + modifiedKeyMap.size());
//changed to let the variable/property values persist so that the history of data change can be stored
      if(modifiedKeyMap.size() > 0)
        getProcessVariableDAOFacade().deleteValue(getInstanceId(), modifiedKeyMap.keySet().iterator());

      ProcessVariableDAO pvd = getProcessVariableDAOFacade().createProcessVariableDAOForBatchInsert();
      for(Iterator iterator = modifiedKeyMap.keySet().iterator(); iterator.hasNext();){
        String fullKey = (String)iterator.next();
       
        String[] scopeAndKey = (String[])modifiedKeyMap.get(fullKey);
        String scope = scopeAndKey[0];
        String key = scopeAndKey[1];
       
        boolean isProperty = isProperty(fullKey);
       
        Serializable cachedValue = (isProperty ? this.getProperty(scope, key) : this.getSourceValue(scope, key));
        if(cachedValue instanceof IndexedProcessVariableMap){
          ProcessVariableValue multipleValue = (ProcessVariableValue)getMultiple(scope, key);
          multipleValue.beforeFirst();
          int i=0;
          do{
            setImpl(scope, key, multipleValue.getValue(), i, true, false, true, pvd, false);
            i++;
          }while(multipleValue.next());
        }
        else
          setImpl(scope, key, cachedValue, 0, false, false, true, pvd, isProperty);
      }
     
      pvd.updateBatch();
    }

    mc.printElapsedTime(this);

    setCaching(false);
   
    if(modifiedRoleMappings!=null){
      RoleMappingDAOType rmDAOFacade = RoleMappingDAOType.getInstance(ptc);

      if(modifiedRoleMappings.size() > 0)       
        rmDAOFacade.removeRoleMappings(getInstanceId(), modifiedRoleMappings.keySet().iterator());
               
      RoleMappingDAO roleMappingDAO = rmDAOFacade.createDAOForInsertRoleMappingBatch();
     
      for(Iterator iterator = modifiedRoleMappings.keySet().iterator(); iterator.hasNext();){
        String roleName = (String)iterator.next();
        RoleMapping rm = (RoleMapping)cachedRoleMappings.get(roleName);
       
//(new Exception("[EJBProcessInstance:putRoleMappingImpl] instanceId = " + instanceId + "; RoleName = " + roleName)).printStackTrace();

        putRoleMappingImpl(roleName, rm, true, roleMappingDAO);
      }
     
      roleMappingDAO.updateBatch();
    }
   
    mc.printElapsedTime(this);

  }
 

  protected int getDataType(Object value){
    if(value==null) return TYPE_NULL; //null
   
    if(value instanceof String)   return TYPE_STRING;
    if(value instanceof Integer)   return TYPE_INTEGER;
    if(value instanceof Long)     return TYPE_LONG;
    if(value instanceof Booleanreturn TYPE_BOOLEAN;
    if(value instanceof Date)     return TYPE_DATE;
    if(value instanceof Calendar)   return TYPE_CALENDAR;
   
    return TYPE_ANY;//means any type (xml serialization)
  }

  public void set(String scopeByTracingTag, String key, Serializable val) throws Exception{
   
    if(val instanceof ProcessVariableValue){
      ProcessVariableValue pvv = (ProcessVariableValue)val;
      pvv.setName(key);
      set(scopeByTracingTag, pvv);
     
      getProcessDefinition().firePropertyChangeEventToActivityFilters(this, "variable", pvv);

      return;
    }
   
    setImpl(scopeByTracingTag, key, val, 0, false, isCaching(), false, null, false);

    ProcessVariableValue pvv = new ProcessVariableValue();
    pvv.setName(key);
    pvv.setValue(val);
    getProcessDefinition().firePropertyChangeEventToActivityFilters(this, "variable", pvv);
  }

  public void setProperty(String scopeByTracingTag, String key, Serializable val) throws Exception{
   
    //If the activity where the scopeByTracingTag is under an execution scope, the property space should be devided.
    ExecutionScopeContext esc = getExecutionScopeContext();
    if(esc!=null){
      Activity activity = getProcessDefinition().getActivity(scopeByTracingTag);
   
      if(activity == esc.getRootActivityInTheScope() || esc.getRootActivityInTheScope().isAncestorOf(activity)){
        scopeByTracingTag = scopeByTracingTag + "." + esc.getExecutionScope();
      }
    }
   
    setImpl(scopeByTracingTag, key, val, 0, false, isCaching(), false, null, true);
  }
 
  public void add(String scopeByTracingTag, String key, Serializable val, int index) throws Exception{
    if(isCaching()){
      super.add(scopeByTracingTag, key, val, index);
     
      if(modifiedKeyMap==null)
        modifiedKeyMap = new Hashtable();
     
      modifiedKeyMap.put(createFullKey(scopeByTracingTag, key, false), new String[]{scopeByTracingTag, key});

    }else

      setImpl(scopeByTracingTag, key, val, index, true, isCaching(), false, null, false);
  }

  private void setImpl(String scopeByTracingTag, String key, Serializable val, int index, boolean append, boolean toCache, boolean isBatch, ProcessVariableDAO pvd, boolean isProperty) throws Exception{
   
    if(!isProperty && getProcessDefinition()!=null){
      ProcessVariable pv = getProcessDefinition().getProcessVariable(key);

      if(pv==null) throw new UEngineException("[ProcessInstance.set] Process [" + getProcessDefinition() + "] tries to set value for an UNDECLARED PROCESS VARIABLE [" + key + "]. Check whether the spell is correct.");

      addDebugInfo(" --- [Set Variable] --------------------\n  * name : "+pv.getName()+"\n  * value : " + (GlobalContext.logLevelIsDebug ? "\n"+GlobalContext.serialize(val, String.class) : val +"'"));
      addDebugInfo(" ---------------------------------------");
   
      if(pv!=null && pv.shouldAccessValueInSpecializedWay()){
        pv.set(this, scopeByTracingTag, val);
        return;
      }
     
      if(key.indexOf('.') > -1 && ProcessVariablePartResolver.class.isAssignableFrom(pv.getType()) ){
        String [] wholePartPath = key.replace('.','@').split("@");
        /*String [] partPath = new String[wholePartPath.length-1];
        for(int i=0; i<partPath.length; i++){
          partPath[i] = wholePartPath[i+1];
        }*/

        Object sourceValue = get("", wholePartPath[0]);

        ProcessVariablePartResolver variableDelegator = (ProcessVariablePartResolver)sourceValue;
        variableDelegator.setPart(this, wholePartPath, val);
       
        return;
      }
     
      /**
       * if the process variable is volatile, never stores it in persisting storage.
       */
      if(pv.isVolatile()) toCache = true;
    }

    if(toCache){
//System.out.println("The value in the cach is used: set ================================");
     
      if(val instanceof ProcessVariableValue){
        throw new UEngineException("Object ProcessVariableValue cannot be set by method 'set(String scope, String variableName, Serializable value)' but 'set(String scope, ProcessVariableValue value)' rather.");
      }
     
      if(isProperty)
        super.setProperty(scopeByTracingTag, key, val);
      else
        super.set(scopeByTracingTag, key, val);
     
      //check the values became dirty so that they can be updated into database later
      if(modifiedKeyMap==null)
        modifiedKeyMap = new Hashtable();
     
      modifiedKeyMap.put(createFullKey(scopeByTracingTag, key, isProperty), new String[]{scopeByTracingTag/*, new Boolean(isInserted)*/, key});

      return;
    }   
   
    int dataType =getDataType(val);

    if(dataType==TYPE_ANY){
      //try{
      //TODO: type-sensitive serialization is enabled now. You may let this disabled for the performance issue           
      ProcessVariable pd = null;{
        pd = getProcessDefinition() 
          .getProcessVariable(key);
      }
                     
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
     
      GlobalContext.serialize(val, bos, pd);
                  //encoding
      String xml = bos.toString(GlobalContext.DATABASE_ENCODING);
           
      //TODO: [serious] value should be very short if you use oracle.. how to?
      //if(xml.length() > GlobalContext.DATABASE_MAXSTRLENGTH)
      //  xml = xml.substring(GlobalContext.DATABASE_MAXSTRLENGTH);

      val = xml;
//
//      }catch(Exception e){
//        e.printStackTrace();
//      } 
    }   
   
    String fullKey = createFullKey(scopeByTracingTag, key, isProperty);
   
    if(isBatch){     
      getProcessVariableDAOFacade().insertValueBatch(pvd, getInstanceId(), scopeByTracingTag, key, isProperty, fullKey, val, dataType, index);
    }else{
      if(!append){
        getProcessVariableDAOFacade().updateValue(getInstanceId(), scopeByTracingTag, key, isProperty, fullKey, val, dataType);
      }else{
        getProcessVariableDAOFacade().insertValue(getInstanceId(), scopeByTracingTag, key, isProperty, fullKey, val, dataType, index);
      }
    }
   
  }


 
  private void beginCaching(String scopeByTracingTag, String key, boolean isProperty) throws Exception{
    if(!processVariablesAreCached && !variables.containsKey(createFullKey(scopeByTracingTag, key, isProperty))){
      try{
        if(!isNew){
         
          ProcessVariable[] vars = getProcessDefinition().getProcessVariables();
          if(vars!=null)
          for(int i=0; i<vars.length; i++){
            ProcessVariable var = vars[i];
            if(var.getDefaultValue() instanceof ComplexType){
              ((ComplexType)var.getDefaultValue()).getTypeClass(getProcessTransactionContext().getProcessManager());
            }
          }
         
          DefaultProcessInstance shotProcessInstance = getProcessVariableDAOFacade().getAllVariablesAsDefaultProcessInstance(getInstanceId());
          shotProcessInstance.variables.putAll(variables);
          variables = shotProcessInstance.variables;

          if(GlobalContext.logLevelIsDebug){
            addDebugInfo("");

            if(vars!=null)
            for(int i=0; i<vars.length; i++){
              ProcessVariable var = vars[i];
              Serializable data = super.get("", var.getName());
              String dataInStr = (String)GlobalContext.serialize(data, String.class);
             
              addDebugInfo("Initial Variable '" + var.getName() + "'", dataInStr);
            }
           
            addDebugInfo("");

            Role[] roles = getProcessDefinition().getRoles();
            if(roles!=null)
              for(int i=0; i<roles.length; i++){
                Role role = roles[i];
                RoleMapping rm = getRoleMapping(role.getName());
                String dataInStr = (String)GlobalContext.serialize(rm, String.class);
               
                addDebugInfo("Initial RoleMapping '" + role.getName() + "'", dataInStr);
              }
             
           
           
          }else
            addDebugInfo("Initial Variable Values", variables);

        }
       
       
        processVariablesAreCached = true;
      }catch(Exception e){
        throw new UEngineException("Error when caching process instance data: "+e.getMessage(), e);
      }
    }
  }

  public Serializable get(String scopeByTracingTag, String key) throws Exception{
    return getImpl(scopeByTracingTag, key, false);
  }

  public Serializable getProperty(String scopeByTracingTag, String key) throws Exception {
    //If the activity where the scopeByTracingTag is under an execution scope, the property space should be devided.
    ExecutionScopeContext esc = getExecutionScopeContext();
    if(esc!=null){
      if(scopeByTracingTag.indexOf('.')==-1){     
   
        Activity activity = getProcessDefinition().getActivity(scopeByTracingTag);
     
        if(activity == esc.getRootActivityInTheScope() || esc.getRootActivityInTheScope().isAncestorOf(activity)){
          scopeByTracingTag = scopeByTracingTag + "." + esc.getExecutionScope();
        }
      }
    }

    return getImpl(scopeByTracingTag, key, true);
  }
 

   public Serializable getImpl(String scopeByTracingTag, String key, boolean isProperty)
    throws Exception
  {
       try{
    
       String firstPart = key;
       if(key.indexOf('.') > 0){
        String [] wholePartPath = key.replace('.','@').split("@");
        firstPart = wholePartPath [0];
       }
      
      if(getProcessDefinition()!=null){
        ProcessVariable pv = getProcessDefinition().getProcessVariable(firstPart);
        if(pv!=null && pv.shouldAccessValueInSpecializedWay()){
          return pv.get(this, scopeByTracingTag);
        }
      }
 
      Serializable sourceValue = null;
     
      if(isCaching()){
        beginCaching(scopeByTracingTag, firstPart, isProperty);
 
  //System.out.println("The value in the cache is used================================");
        if(isProperty)
          return super.getProperty(scopeByTracingTag, firstPart);
        else
          sourceValue = super.get(scopeByTracingTag, firstPart);
      }
      
      if(sourceValue==null)
        sourceValue = getProcessVariableDAOFacade().get(getInstanceId(), scopeByTracingTag, firstPart);
     
      if(sourceValue == null){
        ProcessDefinition pd = getProcessDefinition();
        if(pd != null){
          ProcessVariable pv = pd.getProcessVariable(firstPart);
          if(pv!=null)
            sourceValue = (Serializable)pv.getDefaultValue();
        }
      }
     
 
     
      return resolveParts(sourceValue, key);
     }catch(Exception e){
       throw new UEngineException("Error to get variable [" + key + "]: " + e.getMessage(), e);
     }
  }
  

   public ProcessVariableValue getMultiple(String scopeByTracingTag, String key)
   throws Exception
  {
     if(key.indexOf(".") > -1){
       Serializable orgValue = get(scopeByTracingTag, key);
       if(orgValue instanceof ProcessVariableValue){
         return (ProcessVariableValue)orgValue;
       }else{
         ProcessVariableValue pvv = new ProcessVariableValue();
        
         if(orgValue instanceof BeanPropertyResolver){
           key = key.substring(key.indexOf("."));
          
           ((BeanPropertyResolver)orgValue).getBeanProperty(key);
         }else if (orgValue instanceof ProcessVariablePartResolver){
          orgValue = resolveParts(orgValue, key);
         }
        
         pvv.setValue(orgValue);
         pvv.beforeFirst();
        
         return pvv;
       }
     }
    
    if(isCaching()){
      if(!processVariablesAreCached && !variables.containsKey(createFullKey(scopeByTracingTag, key, false))){
        try{
          if(!isNew){
            variables.putAll(getAll()); // there may be some extra values
          }
         
          processVariablesAreCached = true;
        }catch(Exception e){
          throw new UEngineException("Error when caching process instance data: "+e.getMessage(), e);
        }
      }

      return super.getMultiple(scopeByTracingTag, key);
    }
   
    return getProcessVariableDAOFacade().getAsProcessVariableValue(getInstanceId(), scopeByTracingTag, key)
  }

  public Map getAll(String scope) throws Exception {
    return getProcessVariableDAOFacade().getAll(getInstanceId());
  }
 
  public String getStatus(String scope) throws Exception{   
    return getProcessDefinition().getActivity(scope).getStatus(this);   
  }
 
  protected void setStatus(String scope, String status) throws Exception{
    super.setStatus(scope, status);
   
    ProcessInstanceDAO piDAO = null;
    //forward status of pi to processinstance
    if(scope.equals("")){
      //remove if this instance doesn't need to be archived       
      if(status.equals(Activity.STATUS_COMPLETED) && !getProcessDefinition().isArchive())
        remove()
      else{
        piDAO = getProcessInstanceDAO();
        piDAO.setStatus(status);
      }
     
      //when the instance is completed or stopped.
      if(status.equals(Activity.STATUS_COMPLETED) || status.equals(Activity.STATUS_STOPPED)){
        if(piDAO==null){         
          piDAO = getProcessInstanceDAO();
        }
         
        piDAO.setFinishedDate(GlobalContext.getNow(getProcessTransactionContext()).getTime());
       
        archive();
      }
    }

  }
 
  public void archive() throws Exception{
    if("false".equals(GlobalContext.getPropertyString("server.archive.completed.processes", "false"))) return;
   
    FileProcessArchive processArchive = new FileProcessArchive();{         
      Map pvMap = getAll();
      processArchive.setInstanceId(getInstanceId());
      processArchive.variables = pvMap;
   
      ProcessDefinition definition = getProcessDefinition();
     
      if(definition==null) throw new UEngineException("There's no definition found for the instance ("+ getInstanceId() +")");
     
      Role[] roles = definition.getRoles();
      for(int i=0; i<roles.length; i++){
        RoleMapping rm = getRoleMapping(roles[i].getName());
        if(rm!=null)
          processArchive.putRoleMapping(rm);     
      }
     
      processArchive.setProcessDefinition(getProcessDefinition());     
    }
   
    final String archivePath = processArchive.save(getProcessTransactionContext())
    //should be invoked after applyChanges() of this ProcessInstance
    getProcessTransactionContext().addTransactionListener(new TransactionListener(){

      public void beforeCommit(TransactionContext tx) throws Exception{
        ProcessInstanceDAOType pidt = ProcessInstanceDAOType.getInstance(getProcessTransactionContext());
        pidt.archiveInstance(new Long(getInstanceId()), archivePath);
      }

      public void beforeRollback(TransactionContext tx) throws Exception{
        // TODO Auto-generated method stub
       
      }

      public void afterCommit(TransactionContext tx) throws Exception {
        // TODO Auto-generated method stub
       
      }

      public void afterRollback(TransactionContext tx) throws Exception {
        // TODO Auto-generated method stub
       
      }
     
    });
 
  }

  public void setProcessDefinition(ProcessDefinition value) {
    if(value!=processDefinition){
      String generatedPath = UEngineUtil.getCalendarDir();
      generatedPath = generatedPath + "/" + getInstanceId() + ".upd";
     
      try {
        ProcessDefinitionFactory.getInstance(getProcessTransactionContext()).storeProcessDefinition(generatedPath, value);
        getProcessInstanceDAO().setDefPath(generatedPath);
        getProcessInstanceDAO().setIsAdhoc(true);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
   
    super.setProcessDefinition(value);
  }
 
  public ProcessDefinition getProcessDefinition() throws Exception {
    //TODO if pd can't be cached since it is an ad-hoc, this may cause some decrease of performance
    if(processDefinition==null){
      if(getInstanceId()==null) return null;
//      try{
        ProcessDefinition procDef;
       
        if(isAdhocProcess()){
          procDef = ProcessDefinitionFactory.getInstance(getProcessTransactionContext()).getDefinitionWithPath(getProcessInstanceDAO().getDefPath());
        }else
          procDef = ProcessDefinitionFactory.getInstance(getProcessTransactionContext()).getDefinition(getProcessInstanceDAO().getDefVerId().toString());
       
/*        if(procDef.isAdhoc()){
          //TODO reload if adhoc.. bad performance?
          procDef = ProcessDefinitionFactory.getDefinition(piRemote.getDefinition(), true);
        }*/
        /*  return procDef; //probihit caching
        }else{
          setProcessDefinition(procDef);
        }*/
       
        //if(!procDef.isAdhoc()) //TODO: check-me-if-error: maintain same definition during same transation
        processDefinition = procDef;
        //else
        //  return procDef;
                 
//      }catch(javax.ejb.ObjectNotFoundException onfe){
//System.out.println("EJBActivityInstance::getProcessDefinition(): can't find process instance!");
//       
//      }catch(Exception e){
//        e.printStackTrace();
//        setProcessDefinition(null);
//      }
    }
   
    return processDefinition;
  }   
 
 

  public void remove() throws Exception{
/*    ProcessInstanceDAO piDAO = getProcessInstanceDAO();
    piDAO.setIsDeleted(true);
    if(piDAO.getFinishedDate()==null){
      piDAO.setFinishedDate(GlobalContext.getNow(getProcessTransactionContext()).getTime());
    }
*/
    ProcessInstanceDAOType.getInstance(getProcessTransactionContext()).removeProcessInstance(new Long(getRootProcessInstanceId()));
  }
 
  public ProcessInstance createSnapshot() throws Exception {
    final DefaultProcessInstance shotProcessInstance = getProcessVariableDAOFacade().getAllVariablesAsDefaultProcessInstance(getInstanceId());
    shotProcessInstance.setInstanceId(getInstanceId());
   
    Role[] roles = getProcessDefinition().getRoles();
    for(int i=0; i<roles.length; i++){
      RoleMapping rm = getRoleMapping(roles[i].getName());
      if(rm!=null){
        rm.setName(roles[i].getName());
        shotProcessInstance.putRoleMapping(rm)
      }
    }
   
    shotProcessInstance.setProcessTransactionContext(getProcessTransactionContext());
   
    return shotProcessInstance;
  }


////////////// private methods ////////////////////
 
  public String getInfo() throws Exception{
   
    return getProcessInstanceDAO().getInfo();
  }

  public void setInfo(String info) throws Exception{
    getProcessInstanceDAO().setInfo(info);
  }


  public String getName() {
    if(name==null){
      try{
        name = getProcessInstanceDAO().getName();     
      }catch(Exception e){
      }
    }
   
    return name;
  }
 
  public boolean isSubProcess() throws Exception {
    return getProcessInstanceDAO().getIsSubProcess();     
  }

  Boolean isSubProcess = null;
  public boolean isAdhocProcess() throws Exception {
    if(isSubProcess==null){
      try{
        ProcessInstanceDAO piDAO = getProcessInstanceDAO();
        isSubProcess = Boolean.valueOf(piDAO.getIsAdhoc());                   
      }catch(Exception e){
        isSubProcess = Boolean.valueOf(false);
      }
    }
   
    return isSubProcess.booleanValue();
  }

  public Vector getRunningOrCompletedActivityTracingTags() throws Exception{
    Map statusMap = getAll();
    Vector finding = new Vector();
   
    Set keys = statusMap.keySet();
    for(Iterator iter = keys.iterator(); iter.hasNext();){
      String key = (String)iter.next();
      if(key.endsWith("_status")){
        String val = (String)statusMap.get(key);
        if(!val.equals(Activity.STATUS_READY)){
          //TODO: It is required to add a field for scope (tracingtag) into BPM_PROCVAR
          String tracingTag = key.substring(0, key.length() - "_status".length() - 1);         
          finding.add(tracingTag);
        }
      }
    }
 
    return finding;
  }


  public void setProcessTransactionContext(ProcessTransactionContext ptc) {
    this.ptc = ptc;
  }

  public String getMainProcessInstanceId() {
    try{
      String mainProcessInstanceIdInStr = (getProcessInstanceDAO().getMainInstId() != null ? getProcessInstanceDAO().getMainInstId().toString() : null);
      return (mainProcessInstanceIdInStr.equals("-1") ? null : mainProcessInstanceIdInStr);
     
    }catch(Exception e){
      return null;
    }
  }

  public String getRootProcessInstanceId() {
    try{
      return (getProcessInstanceDAO().getRootInstId() != null ? getProcessInstanceDAO().getRootInstId().toString() : null);
    }catch(Exception e){
      return null;
    }
  }

  public boolean isDontReturn() {
    try{
      return (getProcessInstanceDAO().getDontReturn());
    }catch(Exception e){
      return false;
    }
  }

  public ProcessInstance getSubProcessInstance(String absoluteTracingTag) throws Exception {
    ProcessDefinition definition = getProcessDefinition();
    ProcessInstance findingProcessInstance = this;
   
    if(absoluteTracingTag.indexOf("@")>0){
      String[] scopesByTracingTag = absoluteTracingTag.split("@");
      for(int i=0; i<scopesByTracingTag.length-1; i++){
        String scope = scopesByTracingTag[i];
        SubProcessActivity spAct = (SubProcessActivity)definition.getActivity(scope);
        List spInstanceIds = spAct.getSubprocessIds(findingProcessInstance);
        if(spInstanceIds.size() == 0){
          throw new UEngineException("Activity in the subprocess ["+ absoluteTracingTag +"] cannot be found.");
        }
       
        String spInstanceId = (String)spInstanceIds.get(0);
       
       
        findingProcessInstance = ProcessInstance.create().getInstance(spInstanceId);
        definition = findingProcessInstance.getProcessDefinition();
      }
     
      absoluteTracingTag = scopesByTracingTag[scopesByTracingTag.length-1];
    }
   
    return findingProcessInstance;
  }
 
  public Calendar calculateDueDate(Calendar startDate, int duration) {
    startDate.setTimeInMillis(startDate.getTimeInMillis() + (long)duration * 86400000L);
    return startDate;
  }
 
  public void beforeCommit(TransactionContext tx) throws Exception{
    applyChanges();
  }
 
  public void beforeRollback(TransactionContext tx) throws Exception{
  }
 
  public ProcessInstance getMainProcessInstance() throws Exception {
    if(getMainProcessInstanceId() == null) return null;
   
    return getProcessTransactionContext().getProcessManager().getProcessInstance(getMainProcessInstanceId());
  }
 
  public ProcessInstance getRootProcessInstance() throws Exception {
    if(getRootProcessInstanceId() == null) return null;
   
    return getProcessTransactionContext().getProcessManager().getProcessInstance(getRootProcessInstanceId());
  }

 
  public RoleMapping getRoleMapping(String roleName) throws Exception{
    if(isCaching() && cachedRoleMappings!=null && cachedRoleMappings.containsKey(roleName)){
      return (RoleMapping)((RoleMapping)cachedRoleMappings.get(roleName)).clone();
    }
   
    if(isCaching() && modifiedRoleMappings!=null && modifiedRoleMappings.containsKey(roleName)) return null;
   
    RoleMappingDAOType rmDAOFacade = RoleMappingDAOType.getInstance(ptc);
    RoleMappingDAO roleMappingDAO = rmDAOFacade.findByInstanceIdAndRoleName(new Long(getInstanceId()), roleName);
   
    if ( roleMappingDAO.size() < 1 ) return null;
   
    RoleMapping making;
   
    if(roleMappingDAO.size()==1){
      making = rmDAOFacade.createRoleMapping(roleMappingDAO); //(RoleMapping)GlobalContext.deserialize(roleMappingDAO.getValue(), RoleMapping.class);
    }else{
      making = RoleMapping.create();
      making.setName(roleName);
     
      int i = roleMappingDAO.size();
      do{
        //RoleMapping mapping = (RoleMapping)GlobalContext.deserialize(roleMappingDAO.getValue(), RoleMapping.class);
        RoleMapping mapping = rmDAOFacade.createRoleMapping(roleMappingDAO);
        making.replaceCurrentRoleMapping(mapping)
       
        if(making.getCursor() == 0){
          making.setDispatchingOption(mapping.getDispatchingOption());
          making.setDispatchingParameters(mapping.getDispatchingParameters());
        }
       
        if ((--i)>0) making.moveToAdd()
      }while(roleMappingDAO.next());
    }
   
    making.beforeFirst();
   
    if(isCaching()){
      if(cachedRoleMappings == null)
        cachedRoleMappings = new HashMap();
   
      cachedRoleMappings.put(roleName, making);
    }
   
    return making;
  }
 
  public void putRoleMapping(String roleName, RoleMapping roleMapping) throws Exception{   
    putRoleMappingImpl(roleName, roleMapping, false, null);
  }
   
  public void putRoleMappingImpl(String roleName, RoleMapping roleMapping, boolean isBatch, RoleMappingDAO roleMappingDAO) throws Exception{   
    addDebugInfo("   --- [Set Role] --------------------\n    * name : "+roleName+"\n    * value : " + (GlobalContext.logLevelIsDebug ? GlobalContext.serialize(roleMapping, String.class) : roleMapping.getEndpoint() +"'"));
    addDebugInfo("   -----------------------------------");
   
    if(isCaching()){
      if(modifiedRoleMappings == null)
        modifiedRoleMappings = new HashMap();

      if(cachedRoleMappings == null)
        cachedRoleMappings = new HashMap();
     

      modifiedRoleMappings.put(roleName, roleName);

      if(roleMapping==null){
        cachedRoleMappings.remove(roleName);
      }else{
        roleMapping.setName(roleName);
        cachedRoleMappings.put(roleName, roleMapping);
      }
     
      getProcessDefinition().firePropertyChangeEventToActivityFilters(this, "roleMapping", roleMapping);

      return;
    }   

    RoleMappingDAOType rmDAOType = RoleMappingDAOType.getInstance(ptc);
   
    int count = 0;

    if(!isBatch){
      rmDAOType.removeRoleMapping(getInstanceId(), roleName);
      roleMappingDAO = rmDAOType.createDAOForInsertRoleMappingBatch();
    }

    if(roleMapping==null){
      return; //to clear the rolemapping, simply skip inserting to database
    }

    roleMapping.beforeFirst();

    do{
      RoleMapping currMapping = roleMapping.getCurrentRoleMapping();
      if(currMapping==null)
        continue;
     
      currMapping.makeSingle();
     
      if(roleMapping.getCurrentRoleMapping().resourceName == null){
        roleMapping.fill(this);
      }
     
      boolean verifyOK = true;
      switch ( currMapping.getAssignType() ) {
      case Role.ASSIGNTYPE_USER:
        if(currMapping.getEndpoint() == null ){
          if(currMapping.size()-1 != currMapping.getCursor())
            throw new UEngineException("One of rolemapping value has null endpoint.");
         
          verifyOK = false;         
        }
        break;
      }
     
      if(verifyOK){
        rmDAOType.insertRoleMappingBatch(roleMappingDAO, new Long(getInstanceId()), new Long(getRootProcessInstanceId()), roleName, currMapping);
        count++;
      }
     
    }while(roleMapping.next());
    roleMapping.beforeFirst();
   
    if(count>0 && !isBatch)
      roleMappingDAO.updateBatch();


  }

  public boolean isParticipant(RoleMapping rm) throws Exception{
    RoleMappingDAOType rmDAOType = RoleMappingDAOType.getInstance(ptc);
    return rmDAOType.findByRootInstanceIdAndEndpoint(new Long(getRootProcessInstanceId()), rm.getEndpoint()).size() > 0;
  }
 
  public void setDueDate(Calendar date) throws Exception {
    super.setDueDate(date);
    getProcessInstanceDAO().setDueDate(date.getTime());
  }
 
  public void setName(String value) {
    // TODO Auto-generated method stub
    super.setName(value);
    try {
      getProcessInstanceDAO().setName(value);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
 
  public void setDefinitionVersionId(String verId) throws Exception {
    getProcessInstanceDAO().setDefVerId(new Long(verId));
  }
 
  public boolean isNew() {
    return isNew;
  }
 
  public void stop() throws Exception {
    stop(Activity.STATUS_STOPPED);
  }

  public void stop(String status) throws Exception {
    super.stop(status);
    getProcessInstanceDAO().setStatus(status);
  }
 
  public WorkList getWorkList() {
    return (new WorkListServiceLocator()).getWorkList();
  }
  public void afterCommit(TransactionContext tx) throws Exception {
   
   

  }
  public void afterRollback(TransactionContext tx) throws Exception {
    // TODO Auto-generated method stub
   
  }

  public String getMainExecutionScope() {
    try {
      return getProcessInstanceDAO().getMainExecScope();
    } catch (Exception e) {
      return null;
    }
  }


}
TOP

Related Classes of org.uengine.kernel.EJBProcessInstance

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.