ExecutionVariableCollectionResource.java 8.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

D
Dimitri Hautot 已提交
14
package org.activiti.rest.service.api.runtime.process;
15 16 17 18 19 20 21 22 23 24

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.runtime.Execution;
D
Dimitri Hautot 已提交
25 26 27 28 29
import org.activiti.rest.common.api.ActivitiUtil;
import org.activiti.rest.service.api.RestResponseFactory;
import org.activiti.rest.service.api.engine.variable.RestVariable;
import org.activiti.rest.service.api.engine.variable.RestVariable.RestVariableScope;
import org.activiti.rest.service.application.ActivitiRestServicesApplication;
30 31 32 33 34 35
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
36
import org.restlet.resource.Put;
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
import org.restlet.resource.ResourceException;


/**
 * @author Frederik Heremans
 */
public class ExecutionVariableCollectionResource extends BaseExecutionVariableResource {

  @Get
  public List<RestVariable> getVariables() {
    if (authenticate() == false)
      return null;
    
    Execution execution = getExecutionFromRequest();
    
    List<RestVariable> result = new ArrayList<RestVariable>();
    Map<String, RestVariable> variableMap = new HashMap<String, RestVariable>();
    
    // Check if it's a valid execution to get the variables for
    RestVariableScope variableScope = RestVariable.getScopeFromString(getQueryParameter("scope", getQuery()));
    
    if(variableScope == null) {
      // Use both local and global variables
      addLocalVariables(execution, variableMap);
      addGlobalVariables(execution, variableMap);
    } else if(variableScope == RestVariableScope.GLOBAL) {
      addGlobalVariables(execution, variableMap);
    } else if(variableScope == RestVariableScope.LOCAL) {
      addLocalVariables(execution, variableMap);
    }
    
    // Get unique variables from map
    result.addAll(variableMap.values());
    return result;
  }
  
73 74
  @Put
  public Object createOrUpdateExecutionVariable(Representation representation) {
75 76
  	if(!authenticate()) { return null; }
  	
77 78 79 80
    return createExecutionVariable(representation, true);
  }
  
  
81 82
  @Post
  public Object createExecutionVariable(Representation representation) {
83 84
  	if(!authenticate()) { return null; }
  	
85 86 87 88 89
   return createExecutionVariable(representation, false);
  }
  
  @Delete
  public void deleteAllLocalVariables() {
90 91
  	if(!authenticate()) { return; }
  	
92 93 94 95 96 97 98 99
    Execution execution = getExecutionFromRequest();
    Collection<String> currentVariables = ActivitiUtil.getRuntimeService().getVariablesLocal(execution.getId()).keySet();
    ActivitiUtil.getRuntimeService().removeVariablesLocal(execution.getId(), currentVariables);
    
    setStatus(Status.SUCCESS_NO_CONTENT);
  }
  
  protected Object createExecutionVariable(Representation representation, boolean override) {
100 101 102 103 104 105 106 107 108 109 110 111
    if (authenticate() == false)
      return null;
    
    Execution execution = getExecutionFromRequest();
    
    Object result = null;
    if(MediaType.MULTIPART_FORM_DATA.isCompatible(representation.getMediaType())) {
      result = setBinaryVariable(representation, execution, true);
    } else {
      // Since we accept both an array of RestVariables and a single RestVariable, we need to inspect the
      // body before passing on to the converterService
      try {
112
        
113 114 115 116 117
        List<RestVariable> variables = new ArrayList<RestVariable>();
        result = variables;
        
        RestVariable[] restVariables = getConverterService().toObject(representation, RestVariable[].class, this);
        if(restVariables == null || restVariables.length == 0) {
118
          throw new ActivitiIllegalArgumentException("Request didn't contain a list of variables to create.");
119
        }
120 121 122 123 124 125
        
        RestVariableScope sharedScope = null;
        RestVariableScope varScope = null;
        Map<String, Object> variablesToSet = new HashMap<String, Object>();
        
        RestResponseFactory factory = getApplication(ActivitiRestServicesApplication.class).getRestResponseFactory();
126
        for(RestVariable var : restVariables) {
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
          // Validate if scopes match
          varScope = var.getVariableScope();
          if(var.getName() == null) {
            throw new ActivitiIllegalArgumentException("Variable name is required");
          }
          
          if(varScope == null) {
            varScope = RestVariableScope.LOCAL;
          }
          if(sharedScope == null) {
            sharedScope = varScope;
          }
          if(varScope != sharedScope) {
            throw new ActivitiIllegalArgumentException("Only allowed to update multiple variables in the same scope.");
          }
          
143
          if(!override && hasVariableOnScope(execution, var.getName(), varScope)) {
144 145 146 147 148 149
            throw new ResourceException(new Status(Status.CLIENT_ERROR_CONFLICT.getCode(), "Variable '" + var.getName() + "' is already present on execution '" + execution.getId() + "'.", null, null));
          }
          
          Object actualVariableValue = getApplication(ActivitiRestServicesApplication.class).getRestResponseFactory()
                  .getVariableValue(var);
          variablesToSet.put(var.getName(), actualVariableValue);
150
          variables.add(factory.createRestVariable(this, var.getName(), actualVariableValue, varScope, execution.getId(), RestResponseFactory.VARIABLE_EXECUTION, false));
151 152 153 154 155 156 157 158 159 160 161 162 163 164
        }
        
        if(variablesToSet.size() > 0) {
          if(sharedScope == RestVariableScope.LOCAL) {
            ActivitiUtil.getRuntimeService().setVariablesLocal(execution.getId(), variablesToSet);
          } else {
            if(execution.getParentId() != null) {
              // Explicitly set on parent, setting non-local variables on execution itself will override local-variables if exists
              ActivitiUtil.getRuntimeService().setVariables(execution.getParentId(), variablesToSet);
            } else {
              // Standalone task, no global variables possible
              throw new ActivitiIllegalArgumentException("Cannot set global variables on execution '" + execution.getId() +"', task is not part of process.");
            }
          }
165 166 167 168 169 170 171 172 173 174 175 176
        }
      } catch (IOException ioe) {
        throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, ioe);
      }
    }
    setStatus(Status.SUCCESS_CREATED);
    return result;
  }
  
  protected void addGlobalVariables(Execution execution, Map<String, RestVariable> variableMap) {
    Map<String, Object> rawVariables = ActivitiUtil.getRuntimeService().getVariables(execution.getId());
    List<RestVariable> globalVariables = getApplication(ActivitiRestServicesApplication.class)
177
            .getRestResponseFactory().createRestVariables(this, rawVariables, execution.getId(), RestResponseFactory.VARIABLE_EXECUTION, RestVariableScope.GLOBAL);
178 179 180 181 182 183 184 185 186 187 188 189 190 191
    
    // Overlay global variables over local ones. In case they are present the values are not overridden, 
    // since local variables get precedence over global ones at all times.
    for(RestVariable var : globalVariables) {
      if(!variableMap.containsKey(var.getName())) {
        variableMap.put(var.getName(), var);
      }
    }
  }

  
  protected void addLocalVariables(Execution execution, Map<String, RestVariable> variableMap) {
    Map<String, Object> rawLocalvariables = ActivitiUtil.getRuntimeService().getVariablesLocal(execution.getId());
    List<RestVariable> localVariables = getApplication(ActivitiRestServicesApplication.class)
192
            .getRestResponseFactory().createRestVariables(this, rawLocalvariables, execution.getId(), RestResponseFactory.VARIABLE_EXECUTION, RestVariableScope.LOCAL);
193 194 195 196 197 198
    
    for(RestVariable var : localVariables) {
      variableMap.put(var.getName(), var);
    }
  }
}