package org.jbpm.pvm.impl;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.jbpm.PvmException;
import org.jbpm.env.Environment;
import org.jbpm.pvm.VariableScope;
import org.jbpm.pvm.type.Variable;
import org.jbpm.pvm.type.variable.NullVariable;
import org.jbpm.pvm.type.variable.UnpersistableVariable;
/** maintains a map of named objects. Internally, the objects are
* wrapped and stored as {@link Variable}-objects so that this
* map can be persisted with hibernate in the database.
*/
public class VariableMap implements VariableScope, Serializable {
private static final long serialVersionUID = 1L;
private static Logger log = Logger.getLogger(VariableMap.class.getName());
protected long dbid;
protected Map<String, Variable> variables = null;
protected ExecutionImpl execution;
protected ExecutionImpl processInstance;
public VariableMap() {
}
public VariableMap(ExecutionImpl execution) {
this.execution = execution;
}
public boolean isEmpty() {
return ( (variables==null)
|| (variables.isEmpty())
);
}
public boolean has(String key) {
return ( (variables!=null)
&& (variables.containsKey(key))
);
}
public Set<String> keys() {
return (variables!=null ? variables.keySet() : null);
}
/**
* all the variables. A new HashMap is created for each invocation.
* @return a Map of variables or null if there are no variables.
*/
public Map<String, Object> getAll() {
Map<String, Object> values = null;
if (! isEmpty()) {
values = new HashMap<String, Object>();
for (Map.Entry<String, Variable> entry: variables.entrySet()) {
String name = (String) entry.getKey();
Variable variable = entry.getValue();
values.put(name, variable.getValue());
}
}
return values;
}
public Object get(String key) {
Object value = null;
if (has(key)) {
value = getVariable(key).getValue();
}
return value;
}
public boolean remove(String key) {
return removeVariable(key);
}
public void set(String key, Object value) {
if (key==null) {
throw new PvmException("name is null");
}
Variable variable = getVariable(key);
// if there is already a variable instance and it doesn't support the current type...
if ( (variable!=null)
&& (!variable.supports(value))
) {
// delete the old variable instance
log.fine("variable type change. deleting '"+key+"' from '"+this+"'");
removeVariable(key);
variable = null;
}
if (variable==null) {
log.fine("create variable '"+key+"' in '"+this+"' with value '"+value+"'");
variable = createVariable(key, value);
setVariable(variable);
} else {
log.fine("update variable '"+key+"' in '"+this+"' to value '"+value+"'");
variable.setValue(value);
}
}
// internal methods /////////////////////////////////////////////////////////
protected Variable createVariable(String key, Object value) {
Variable variable = null;
if (value==null) {
log.finest("creating null variable for "+key);
variable = new NullVariable();
} else {
Environment environment = Environment.getCurrent();
if (environment!=null) {
VariableTypeResolver variableTypeResolver = environment.get(VariableTypeResolver.class);
if (variableTypeResolver!=null) {
variable = variableTypeResolver.createVariable(key, value, this);
}
}
if (variable==null) {
log.finest("creating new unpersistable variable for "+key);
variable = new UnpersistableVariable();
}
}
variable.setName(key);
variable.setExecution(execution);
variable.setProcessInstance(processInstance);
variable.setValue(value);
// TODO add create-variable-log
return variable;
}
public Variable getVariable(String key) {
return (variables!=null ? (Variable) variables.get(key) : null);
}
/**
* @return true if a variable was actually deleted.
*/
protected boolean removeVariable(String key) {
if (variables!=null) {
return (variables.remove(key) != null);
}
return false;
}
protected void setVariable(Variable variable) {
if (variables==null) {
variables = new HashMap<String, Variable>();
}
variables.put(variable.getName(), variable);
}
}