All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jbpm.context.exe.VariableContainer Maven / Gradle / Ivy

The newest version!
package org.jbpm.context.exe;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
import org.jbpm.context.log.VariableDeleteLog;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.jbpm.logging.db.DbLoggingService;

public abstract class VariableContainer implements Serializable {

  protected Map variableInstances;

  private static final long serialVersionUID = 520258491083406913L;

  protected abstract VariableContainer getParentVariableContainer();

  public abstract Token getToken();

  // variables ////////////////////////////////////////////////////////////////

  public Object getVariable(String name) {
    Object value = null;
    if (hasVariableLocally(name)) {
      value = getVariableLocally(name);
    }
    else {
      VariableContainer parent = getParentVariableContainer();
      if (parent != null) {
        // check upwards in the token hierarchy
        value = parent.getVariable(name);
      }
    }
    return value;
  }

  public void setVariable(String name, Object value) {
    VariableContainer parent = getParentVariableContainer();
    if (hasVariableLocally(name) || parent == null) {
      setVariableLocally(name, value);
    }
    else {
      // propagate to parent variable container
      parent.setVariable(name, value);
    }
  }

  public boolean hasVariable(String name) {
    // if the variable is present in the variable instances
    if (hasVariableLocally(name)) return true;

    // search in parent variable container
    VariableContainer parent = getParentVariableContainer();
    if (parent != null) return parent.hasVariable(name);

    return false;
  }

  public void deleteVariable(String name) {
    if (name == null) throw new JbpmException("variable name is null");
    if (hasVariableLocally(name)) deleteVariableLocally(name);
  }

  /**
   * adds all the given variables to this variable container. The method
   * {@link #setVariables(Map)} is the same as this method, but it was added for naming
   * consistency.
   */
  public void addVariables(Map variables) {
    setVariables(variables);
  }

  /**
   * adds all the given variables to this variable container. It doesn't remove any existing
   * variables unless they are overwritten by the given variables. This method is the same as
   * {@link #addVariables(Map)} and this method was added for naming consistency.
   */
  public void setVariables(Map variables) {
    if (variables != null) {
      for (Iterator iter = variables.entrySet().iterator(); iter.hasNext();) {
        Map.Entry entry = (Map.Entry) iter.next();
        setVariable((String) entry.getKey(), entry.getValue());
      }
    }
  }

  public Map getVariables() {
    Map variables = getVariablesLocally();
    VariableContainer parent = getParentVariableContainer();
    if (parent != null) {
      Map parentVariables = parent.getVariablesLocally();
      parentVariables.putAll(variables);
      variables = parentVariables;
    }
    return variables;
  }

  public Map getVariablesLocally() {
    Map variables = new HashMap();
    if (variableInstances != null) {
      for (Iterator iter = variableInstances.entrySet().iterator(); iter.hasNext();) {
        Map.Entry entry = (Map.Entry) iter.next();
        String name = (String) entry.getKey();
        VariableInstance variableInstance = (VariableInstance) entry.getValue();
        if (!variables.containsKey(name)) {
          variables.put(name, variableInstance.getValue());
        }
      }
    }
    return variables;
  }

  // local variable methods ///////////////////////////////////////////////////

  public boolean hasVariableLocally(String name) {
    return variableInstances != null && variableInstances.containsKey(name);
  }

  public Object getVariableLocally(String name) {
    Object value = null;

    // if the variable is present in the variable instances
    if (hasVariableLocally(name)) {
      value = getVariableInstance(name).getValue();
    }

    return value;
  }

  public void deleteVariableLocally(String name) {
    deleteVariableInstance(name);
  }

  public void setVariableLocally(String name, Object value) {
    if (name == null) {
      throw new IllegalArgumentException("variable name is null");
    }

    VariableInstance variableInstance = getVariableInstance(name);
    // if variable instance already exists and it does not support the new value
    if (variableInstance != null && !variableInstance.supports(value)) {
      // delete the old variable instance
      if (log.isDebugEnabled()) {
        log.debug(variableInstance.getToken() + " unsets '" + name + "' due to type change");
      }
      deleteVariableInstance(name);
      variableInstance = null;
    }

    if (variableInstance != null) {
      if (log.isDebugEnabled()) {
        log.debug(variableInstance.getToken() + " sets '" + name + "' to " + value);
      }
      variableInstance.setValue(value);
    }
    else {
      Token token = getToken();
      if (log.isDebugEnabled()) {
        log.debug(token + " initializes '" + name + "' to " + value);
      }
      addVariableInstance(VariableInstance.create(token, name, value));
    }
  }

  // local variable instances /////////////////////////////////////////////////

  public VariableInstance getVariableInstance(String name) {
    return variableInstances != null ? (VariableInstance) variableInstances.get(name) : null;
  }

  public Map getVariableInstances() {
    return variableInstances;
  }

  public void addVariableInstance(VariableInstance variableInstance) {
    if (variableInstances == null) variableInstances = new HashMap();
    variableInstances.put(variableInstance.getName(), variableInstance);
    // only register additions in the updated variable containers
    // because the registry is only used to check for non-persistable variables
    ContextInstance contextInstance = getContextInstance();
    if (contextInstance != null) contextInstance.addUpdatedVariableContainer(this);
  }

  public void deleteVariableInstance(String name) {
    if (variableInstances != null) {
      VariableInstance variableInstance = (VariableInstance) variableInstances.remove(name);
      if (variableInstance != null) {
        // unlink variable
        variableInstance.removeReferences();
        // log variable deletion
        getToken().addLog(new VariableDeleteLog(variableInstance));

        // if a context is present and its logging service is not connected to the database 
        JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();
        if (jbpmContext != null
          && !(jbpmContext.getServices().getLoggingService() instanceof DbLoggingService)) {
          // delete variable instance here before all references to it are lost
          Session session = jbpmContext.getSession();
          if (session != null) session.delete(variableInstance);
        }
      }
    }
  }

  public ContextInstance getContextInstance() {
    Token token = getToken();
    return token != null ? token.getProcessInstance().getContextInstance() : null;
  }

  /** @deprecated call {@link ContextInstance#getUpdatedVariableContainers()} instead */
  public static Collection getUpdatedVariableContainers(ProcessInstance processInstance) {
    return processInstance.getContextInstance().updatedVariableContainers;
  }

  private static final Log log = LogFactory.getLog(VariableContainer.class);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy