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

org.ow2.bonita.util.GroovyBindingBuilder Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2009  BonitaSoft S.A.
 * BonitaSoft, 31 rue Gustave Eiffel - 38000 Grenoble
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation
 * version 2.1 of the License.
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA  02110-1301, USA.
 **/
package org.ow2.bonita.util;

import groovy.lang.Binding;
import groovy.lang.MissingPropertyException;

import java.io.IOException;
import java.io.NotSerializableException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.ow2.bonita.facade.APIAccessor;
import org.ow2.bonita.facade.QueryDefinitionAPI;
import org.ow2.bonita.facade.QueryRuntimeAPI;
import org.ow2.bonita.facade.def.InternalProcessDefinition;
import org.ow2.bonita.facade.def.majorElement.DataFieldDefinition;
import org.ow2.bonita.facade.def.majorElement.ProcessDefinition;
import org.ow2.bonita.facade.def.majorElement.impl.ProcessDefinitionImpl;
import org.ow2.bonita.facade.exception.ActivityDefNotFoundException;
import org.ow2.bonita.facade.exception.ActivityNotFoundException;
import org.ow2.bonita.facade.exception.DataFieldNotFoundException;
import org.ow2.bonita.facade.exception.InstanceNotFoundException;
import org.ow2.bonita.facade.exception.ProcessNotFoundException;
import org.ow2.bonita.facade.impl.StandardAPIAccessorImpl;
import org.ow2.bonita.facade.impl.StandardQueryAPIAccessorImpl;
import org.ow2.bonita.facade.runtime.ActivityInstance;
import org.ow2.bonita.facade.runtime.ActivityState;
import org.ow2.bonita.facade.runtime.AttachmentInstance;
import org.ow2.bonita.facade.runtime.ProcessInstance;
import org.ow2.bonita.facade.runtime.VariableUpdate;
import org.ow2.bonita.facade.runtime.impl.ActivityInstanceImpl;
import org.ow2.bonita.facade.runtime.impl.InternalProcessInstance;
import org.ow2.bonita.facade.runtime.impl.ObjectVariable;
import org.ow2.bonita.facade.runtime.impl.ProcessInstanceImpl;
import org.ow2.bonita.facade.uuid.ActivityDefinitionUUID;
import org.ow2.bonita.facade.uuid.ActivityInstanceUUID;
import org.ow2.bonita.facade.uuid.ProcessDefinitionUUID;
import org.ow2.bonita.facade.uuid.ProcessInstanceUUID;
import org.ow2.bonita.services.DocumentationManager;

/**
 * 
 * @author Charles Souillard
 * 
 */
public class GroovyBindingBuilder {

  public static Binding getSimpleBinding(final Map allVariables,
      final ProcessDefinitionUUID processUUID, final ProcessInstanceUUID instanceUUID,
      final ActivityInstanceUUID activityUUID) throws IOException, ClassNotFoundException, GroovyException,
      InstanceNotFoundException, ActivityNotFoundException {

    return new SimpleBinding(allVariables, processUUID, instanceUUID, activityUUID);

  }

  public static Binding getPropagateBinding(final Map allVariables,
      final ProcessDefinitionUUID processUUID, final ProcessInstanceUUID instanceUUID,
      final ActivityInstanceUUID activityInstanceUUID, final Map context) throws IOException,
      ClassNotFoundException, GroovyException, InstanceNotFoundException, ActivityNotFoundException {

    ActivityDefinitionUUID activityUUID = null;
    if (activityInstanceUUID != null) {
      final ActivityInstance activityInstance = EnvTool.getAllQueriers().getActivityInstance(activityInstanceUUID);
      activityUUID = activityInstance.getActivityDefinitionUUID();
    }
    final Set initialVariables = new HashSet();
    initialVariables.addAll(allVariables.keySet());
    if (context != null) {
      initialVariables.removeAll(context.keySet());
    }
    return new PropagateBinding(processUUID, activityUUID, instanceUUID, activityInstanceUUID, allVariables,
        initialVariables);
  }

  public static Binding getSimpleBinding(final ProcessDefinitionUUID processUUID,
      final ProcessInstanceUUID instanceUUID, final ActivityInstanceUUID activityUUID,
      final Map context, final boolean useActivityScope, final boolean useInitialVariableValues)
      throws IOException, ClassNotFoundException, GroovyException, InstanceNotFoundException, ActivityNotFoundException {

    final Map allVariables = getContext(context, processUUID, activityUUID, instanceUUID,
        useActivityScope, useInitialVariableValues);
    return new SimpleBinding(allVariables, processUUID, instanceUUID, activityUUID);

  }

  public static Binding getPropagateBinding(final ProcessDefinitionUUID processUUID,
      final ProcessInstanceUUID instanceUUID, final ActivityInstanceUUID activityInstanceUUID,
      final Map context, final boolean useActivityScope, final boolean useInitialVariableValues)
      throws IOException, ClassNotFoundException, GroovyException, InstanceNotFoundException, ActivityNotFoundException {

    final Map allVariables = getContext(context, processUUID, activityInstanceUUID, instanceUUID,
        useActivityScope, useInitialVariableValues);
    ActivityDefinitionUUID activityUUID = null;
    if (activityInstanceUUID != null) {
      final ActivityInstance activityInstance = EnvTool.getAllQueriers().getActivityInstance(activityInstanceUUID);
      activityUUID = activityInstance.getActivityDefinitionUUID();
    }
    final Set initialVariables = new HashSet();
    initialVariables.addAll(allVariables.keySet());
    if (context != null) {
      initialVariables.removeAll(context.keySet());
    }
    return new PropagateBinding(processUUID, activityUUID, instanceUUID, activityInstanceUUID, allVariables,
        initialVariables);
  }

  private static Map getActivityInstanceVariables(final ActivityInstanceUUID activityUUID)
      throws ActivityNotFoundException {
    final Map activityInstanceVariables = new HashMap();
    if (activityUUID != null) {
      final StandardQueryAPIAccessorImpl accessor = new StandardQueryAPIAccessorImpl();
      final QueryRuntimeAPI api = accessor.getQueryRuntimeAPI();
      activityInstanceVariables.putAll(api.getActivityInstanceVariables(activityUUID));
    }
    return activityInstanceVariables;
  }

  private static long getActivityScopeDate(final ActivityInstance activityInstance, final long defaultDate) {
    long maxDate = -1;
    if (!activityInstance.getState().equals(ActivityState.READY)
        && !activityInstance.getState().equals(ActivityState.SUSPENDED)
        && !activityInstance.getState().equals(ActivityState.EXECUTING)) {
      maxDate = activityInstance.getLastStateUpdate().getUpdatedDate().getTime();
    } else {
      maxDate = defaultDate;
    }
    return maxDate;
  }

  private static Map getProcessInstanceVariables(final ProcessInstanceUUID instanceUUID,
      final ActivityInstanceUUID activityUUID, final boolean useInitialVariableValues, final boolean useActivityScope)
      throws InstanceNotFoundException {
    final Map processInstanceVariables = new HashMap();
    if (instanceUUID != null) {
      final StandardQueryAPIAccessorImpl accessor = new StandardQueryAPIAccessorImpl();
      final QueryRuntimeAPI api = accessor.getQueryRuntimeAPI();

      final ProcessInstance instance = EnvTool.getAllQueriers().getProcessInstance(instanceUUID);
      if (useInitialVariableValues) {
        processInstanceVariables.putAll(instance.getInitialVariableValues());
      } else {
        processInstanceVariables.putAll(api.getProcessInstanceVariables(instanceUUID));
      }
    }
    if (activityUUID != null) {
      final ActivityInstance activityInstance = EnvTool.getAllQueriers().getActivityInstance(activityUUID);

      final ProcessInstance instance = EnvTool.getAllQueriers().getProcessInstance(
          activityInstance.getProcessInstanceUUID());
      long maxDate = new Date().getTime();
      if (useActivityScope) {
        maxDate = getActivityScopeDate(activityInstance, maxDate);
      }
      final List instanceVarUpdates = instance.getVariableUpdates();
      final Map tmp = new HashMap();

      for (final VariableUpdate varUpdate : instanceVarUpdates) {
        if (varUpdate.getDate().getTime() <= maxDate) {
          tmp.put(varUpdate.getName(), varUpdate);
        }
      }
      processInstanceVariables.putAll(instance.getInitialVariableValues());
      for (final VariableUpdate varUpdate : tmp.values()) {
        processInstanceVariables.put(varUpdate.getName(), varUpdate.getValue());
      }
    }

    return processInstanceVariables;
  }

  private static Map getProcessDatafieldsVariables(final ProcessDefinitionUUID processUUID,
      final Set variablesToIgnore) throws InstanceNotFoundException, GroovyException {
    final Map processDatafieldsVariables = new HashMap();
    if (processUUID != null) {
      final InternalProcessDefinition process = EnvTool.getAllQueriers().getProcess(processUUID);
      final Set datafields = process.getDataFields();
      processDatafieldsVariables.putAll(getMissingProcessDefinitionDataFields(datafields, variablesToIgnore,
          processUUID));
    }
    return processDatafieldsVariables;
  }

  private static Map getProcessInstanceAttachments(final ProcessInstanceUUID instanceUUID,
      final ActivityInstanceUUID activityInstanceUUID) {
    final Map processInstanceAttachments = new HashMap();
    // The history queriers are also needed because we want to be able to
    // evaluate expressions on terminated instances

    InternalProcessInstance instance = null;
    ProcessInstanceUUID processInstanceUUID = instanceUUID;
    if (instanceUUID != null) {
      instance = EnvTool.getAllQueriers().getProcessInstance(instanceUUID);
    } else if (activityInstanceUUID != null) {
      final ActivityInstance activityInstance = EnvTool.getAllQueriers().getActivityInstance(activityInstanceUUID);
      processInstanceUUID = activityInstance.getProcessInstanceUUID();
      instance = EnvTool.getAllQueriers().getProcessInstance(processInstanceUUID);
    }
    if (instance != null) {
      if (instance.getNbOfAttachments() > 0) {
        final DocumentationManager manager = EnvTool.getDocumentationManager();
        final List attachments = DocumentService.getLastAttachments(manager, processInstanceUUID);
        if (attachments != null) {
          for (final AttachmentInstance attachment : attachments) {
            processInstanceAttachments.put(attachment.getName(), attachment);
          }
        }
      }
    }
    return processInstanceAttachments;
  }

  public static Map getContext(final Map context,
      final ProcessDefinitionUUID processUUID, final ActivityInstanceUUID activityUUID,
      final ProcessInstanceUUID instanceUUID, final boolean useActivityScope, final boolean useInitialVariableValues)
      throws GroovyException, InstanceNotFoundException, ActivityNotFoundException {

    final Map allVariables = new HashMap();
    final Map processInstanceVariables = getProcessInstanceVariables(instanceUUID, activityUUID,
        useInitialVariableValues, useActivityScope);
    final Map activityInstanceVariables = getActivityInstanceVariables(activityUUID);

    allVariables.putAll(processInstanceVariables);
    allVariables.putAll(activityInstanceVariables);

    final Map processDatafieldsVariables = getProcessDatafieldsVariables(processUUID,
        allVariables.keySet());
    allVariables.putAll(processDatafieldsVariables);
    if (context != null) {
      allVariables.putAll(context);
    }
    return allVariables;
  }

  private static Map getMissingProcessDefinitionDataFields(final Set datafields,
      final Set variablesToIgnore, final ProcessDefinitionUUID processDefinitionUUID) throws GroovyException {
    final Map processDatafieldsVariables = new HashMap();

    if (datafields != null) {
      final List variables = new ArrayList();
      for (final DataFieldDefinition datafield : datafields) {
        if (!variablesToIgnore.contains(datafield.getName())) {
          final Object value = datafield.getInitialValue();
          final String script = datafield.getScriptingValue();
          if (value == null && script != null) {
            variables.add(datafield);
          } else {
            processDatafieldsVariables.put(datafield.getName(), value);
          }
        }
      }

      int size = variables.size();
      int index = 0;
      int errors = 0;
      while (size > 0 && index < size) {
        final DataFieldDefinition variable = variables.get(index);
        try {
          final Object value = GroovyUtil.evaluate(variable.getScriptingValue(), processDatafieldsVariables);
          processDatafieldsVariables.put(variable.getName(), value);
          variables.remove(index);
          size = variables.size();
          index = 0;
          errors = 0;
        } catch (final GroovyException e) {
          errors++;
          if (errors == size) {
            final StringBuilder stb = new StringBuilder("Unable to evaluate: '");
            stb.append(variable.getScriptingValue());
            stb.append("' on variable: '");
            stb.append(variable.getName());
            stb.append("' in process: '");
            stb.append(processDefinitionUUID);
            stb.append("' ");

            throw new GroovyException(stb.toString(), e);
          }
          index++;
        }
      }
    }

    return processDatafieldsVariables;
  }

  public static class SimpleBinding extends Binding {
    Map allVariables = new HashMap();

    private ProcessDefinitionUUID processUUID;
    private ProcessDefinition clientProcessDefinition;
    private ProcessInstanceUUID instanceUUID;
    private ProcessInstance clientProcessInstance;
    private final ActivityInstanceUUID activityInstanceUUID;
    private ActivityInstance clientActivityInstance;
    private APIAccessor apiAccessor;
    private String initiator;
    private boolean attachmentsWasLoaded;

    public SimpleBinding(final Map variables, final ProcessDefinitionUUID processUUID,
        final ProcessInstanceUUID instanceUUID, final ActivityInstanceUUID activityInstanceUUID) throws IOException,
        ClassNotFoundException {
      super();
      attachmentsWasLoaded = false;
      if (variables != null) {
        for (final Map.Entry variable : variables.entrySet()) {
          Object value = variable.getValue();
          if (value instanceof ObjectVariable) {
            value = ((ObjectVariable) value).getValue();
          }
          allVariables.put(variable.getKey(), value);
        }
      }
      if (processUUID != null) {
        this.processUUID = processUUID;
      } else if (instanceUUID != null) {
        this.processUUID = EnvTool.getAllQueriers().getProcessInstance(instanceUUID).getProcessDefinitionUUID();
      } else if (activityInstanceUUID != null) {
        this.processUUID = EnvTool.getAllQueriers().getActivityInstance(activityInstanceUUID)
            .getProcessDefinitionUUID();
      }

      if (instanceUUID != null) {
        this.instanceUUID = instanceUUID;
      } else if (activityInstanceUUID != null) {
        this.instanceUUID = EnvTool.getAllQueriers().getActivityInstance(activityInstanceUUID).getProcessInstanceUUID();
      }
      this.activityInstanceUUID = activityInstanceUUID;
    }

    @Override
    public Object getVariable(final String name) {
      if (BonitaConstants.PROCESS_DEFINITION.equals(name)) {
        if (clientProcessDefinition == null && processUUID != null) {
          clientProcessDefinition = new ProcessDefinitionImpl(EnvTool.getAllQueriers().getProcess(processUUID));
        }
        return clientProcessDefinition;
      }
      if (BonitaConstants.PROCESS_INSTANCE.equals(name)) {
        if (clientProcessInstance == null && instanceUUID != null) {
          clientProcessInstance = new ProcessInstanceImpl(EnvTool.getAllQueriers().getProcessInstance(instanceUUID));
        }
        return clientProcessInstance;
      }
      if (BonitaConstants.ACTIVITY_INSTANCE.equals(name)) {
        if (clientActivityInstance == null && activityInstanceUUID != null) {
          clientActivityInstance = new ActivityInstanceImpl(EnvTool.getAllQueriers().getActivityInstance(
              activityInstanceUUID));
        }
        return clientActivityInstance;
      }
      if (BonitaConstants.LOGGED_USER.equals(name)) {
        try {
          return EnvTool.getUserId();
        } catch (final Throwable e) {
          return null;
        }
      }
      if (BonitaConstants.API_ACCESSOR.equals(name)) {
        if (apiAccessor == null) {
          apiAccessor = new StandardAPIAccessorImpl();
        }
        return apiAccessor;
      }
      if (BonitaConstants.PROCESS_INSTANCE_INITIATOR.equals(name)) {
        if (initiator == null) {
          if (instanceUUID != null) {
            final InternalProcessInstance processInstance = EnvTool.getAllQueriers().getProcessInstance(instanceUUID);
            initiator = processInstance.getStartedBy();
          }
        }
        return initiator;
      }
      if (allVariables.containsKey(name)) {
        return allVariables.get(name);
      }
      try {
        return super.getVariable(name);
      } catch (final MissingPropertyException e) {
        if (!attachmentsWasLoaded) {
          final Map attachments = getProcessInstanceAttachments(instanceUUID,
              activityInstanceUUID);
          allVariables.putAll(attachments);
          attachmentsWasLoaded = true;
          if (allVariables.containsKey(name)) {
            return allVariables.get(name);
          } else {
            throw e;
          }
        } else {
          throw e;
        }

      }
    }

    @Override
    public void setVariable(final String name, final Object value) {
      allVariables.put(name, value);
    }

    @Override
    public Map getVariables() {
      return allVariables;
    }
  }

  public static Object getInjectedVariable(final String variable, final ProcessDefinitionUUID processUUID,
      final ProcessInstanceUUID instanceUUID, final ActivityInstanceUUID activityInstanceUUID) {
    if (BonitaConstants.PROCESS_DEFINITION.equals(variable) && processUUID != null) {
      return new ProcessDefinitionImpl(EnvTool.getAllQueriers().getProcess(processUUID));
    }
    if (BonitaConstants.PROCESS_INSTANCE.equals(variable) && instanceUUID != null) {
      return new ProcessInstanceImpl(EnvTool.getAllQueriers().getProcessInstance(instanceUUID));
    }
    if (BonitaConstants.ACTIVITY_INSTANCE.equals(variable) && activityInstanceUUID != null) {
      return new ActivityInstanceImpl(EnvTool.getAllQueriers().getActivityInstance(activityInstanceUUID));
    }
    if (BonitaConstants.LOGGED_USER.equals(variable)) {
      try {
        return EnvTool.getUserId();
      } catch (final Throwable e) {
        return null;
      }
    }
    if (BonitaConstants.API_ACCESSOR.equals(variable)) {
      return new StandardAPIAccessorImpl();
    }
    if (BonitaConstants.PROCESS_INSTANCE_INITIATOR.equals(variable)) {
      if (instanceUUID != null) {
        final InternalProcessInstance processInstance = EnvTool.getAllQueriers().getProcessInstance(instanceUUID);
        return processInstance.getStartedBy();
      }
    }

    return null;
  }

  public static class PropagateBinding extends SimpleBinding {
    private final Collection varToPropagate = new HashSet();
    private final Collection initialProcessVariableKeys = new HashSet();
    private final Collection initialObjectVariables = new HashSet();
    private final Collection initialNullVariables = new HashSet();
    private final ActivityDefinitionUUID activityUUID;
    private final ProcessDefinitionUUID processUUID;

    public PropagateBinding(final ProcessDefinitionUUID processUUID, final ActivityDefinitionUUID activityUUID,
        final ProcessInstanceUUID instanceUUID, final ActivityInstanceUUID activityInstanceUUID,
        final Map variables, final Set initialProcessVariableKeys) throws IOException,
        ClassNotFoundException {

      super(variables, processUUID, instanceUUID, activityInstanceUUID);

      this.initialProcessVariableKeys.addAll(initialProcessVariableKeys);
      if (variables != null) {
        for (final Map.Entry variable : variables.entrySet()) {
          Object value = variable.getValue();
          final String varName = variable.getKey();
          if (value instanceof ObjectVariable && initialProcessVariableKeys.contains(varName)) {
            value = ((ObjectVariable) value).getValue();
            initialObjectVariables.add(varName);
          }
          if (value == null) {
            initialNullVariables.add(varName);
          }
        }
      }
      this.activityUUID = activityUUID;
      this.processUUID = processUUID;
    }

    @Override
    public Object getVariable(final String name) {
      varToPropagate.add(name);
      return super.getVariable(name);
    }

    @Override
    public void setVariable(final String name, final Object value) {
      super.setVariable(name, value);
      if (initialProcessVariableKeys.contains(name)) {
        varToPropagate.add(name);
      }
    }

    public Map getVariablesToPropagate() throws NotSerializableException, IOException,
        ClassNotFoundException, ActivityDefNotFoundException, DataFieldNotFoundException, ProcessNotFoundException {
      final Map variablesToPropagate = new HashMap();
      for (final String varName : varToPropagate) {
        if (initialProcessVariableKeys.contains(varName)) {
          Object value = allVariables.get(varName);
          if (initialObjectVariables.contains(varName)) {
            value = new ObjectVariable(value);
          } else if (initialNullVariables.contains(varName)) {
            // try to get the type from definition
            final StandardQueryAPIAccessorImpl accessor = new StandardQueryAPIAccessorImpl();
            final QueryDefinitionAPI queryDefinitionAPI = accessor
                .getQueryDefinitionAPI(AccessorUtil.QUERYLIST_JOURNAL_KEY);
            DataFieldDefinition datafield = null;
            if (activityUUID != null) {
              try {
                datafield = queryDefinitionAPI.getActivityDataField(activityUUID, varName);
              } catch (final DataFieldNotFoundException e) {
                datafield = queryDefinitionAPI.getProcessDataField(processUUID, varName);
              }
            }
            if (datafield == null && processUUID != null) {
              datafield = queryDefinitionAPI.getProcessDataField(processUUID, varName);
            }
            if (datafield != null && datafield.getDataTypeClassName().equals(ObjectVariable.class.getName())) {
              value = new ObjectVariable(value);
            }
          }
          variablesToPropagate.put(varName, value);
        }
      }
      return variablesToPropagate;
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy