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

org.camunda.bpm.engine.impl.persistence.entity.VariableInstanceEntity Maven / Gradle / Ivy

There is a newer version: 7.22.0-alpha1
Show newest version
/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. Camunda licenses this file to you under the Apache License,
 * Version 2.0; 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.
 */
package org.camunda.bpm.engine.impl.persistence.entity;

import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;

import org.camunda.bpm.application.InvocationContext;
import org.camunda.bpm.application.ProcessApplicationReference;
import org.camunda.bpm.engine.delegate.VariableScope;
import org.camunda.bpm.engine.impl.ProcessEngineLogger;
import org.camunda.bpm.engine.impl.cmmn.entity.runtime.CaseExecutionEntity;
import org.camunda.bpm.engine.impl.context.Context;
import org.camunda.bpm.engine.impl.context.ProcessApplicationContextUtil;
import org.camunda.bpm.engine.impl.core.variable.CoreVariableInstance;
import org.camunda.bpm.engine.impl.db.DbEntity;
import org.camunda.bpm.engine.impl.db.DbEntityLifecycleAware;
import org.camunda.bpm.engine.impl.db.EnginePersistenceLogger;
import org.camunda.bpm.engine.impl.db.HasDbReferences;
import org.camunda.bpm.engine.impl.db.HasDbRevision;
import org.camunda.bpm.engine.impl.persistence.entity.util.ByteArrayField;
import org.camunda.bpm.engine.impl.persistence.entity.util.TypedValueField;
import org.camunda.bpm.engine.impl.persistence.entity.util.TypedValueUpdateListener;
import org.camunda.bpm.engine.impl.pvm.runtime.LegacyBehavior;
import org.camunda.bpm.engine.impl.variable.serializer.TypedValueSerializer;
import org.camunda.bpm.engine.impl.variable.serializer.ValueFields;
import org.camunda.bpm.engine.repository.ResourceTypes;
import org.camunda.bpm.engine.runtime.VariableInstance;
import org.camunda.bpm.engine.variable.value.TypedValue;

/**
 * @author Tom Baeyens
 */
public class VariableInstanceEntity implements VariableInstance, CoreVariableInstance, ValueFields, DbEntity, DbEntityLifecycleAware, TypedValueUpdateListener, HasDbRevision,
  HasDbReferences, Serializable {

  protected static final EnginePersistenceLogger LOG = ProcessEngineLogger.PERSISTENCE_LOGGER;

  private static final long serialVersionUID = 1L;

  protected String id;
  protected int revision;

  protected String name;

  protected String processDefinitionId;
  protected String processInstanceId;
  protected String executionId;
  protected String taskId;
  protected String batchId;
  protected String caseInstanceId;
  protected String caseExecutionId;
  protected String activityInstanceId;
  protected String tenantId;

  protected Long longValue;
  protected Double doubleValue;
  protected String textValue;
  protected String textValue2;
  protected String variableScopeId;

  protected ByteArrayField byteArrayField = new ByteArrayField(this, ResourceTypes.RUNTIME);

  protected TypedValueField typedValueField = new TypedValueField(this, true);

  boolean forcedUpdate;

  protected String configuration;

  protected long sequenceCounter = 1;

  /**
   * 

Determines whether this variable is supposed to be a local variable * in case of concurrency in its scope. This affects *

* *
    *
  • tree expansion (not evaluated yet by the engine) *
  • activity instance IDs of variable instances: concurrentLocal * variables always receive the activity instance id of their execution * (which may not be the scope execution), while non-concurrentLocal variables * always receive the activity instance id of their scope (which is set in the * parent execution) *
* *

* In the future, this field could be used for restoring the variable distribution * when the tree is expanded/compacted multiple times. * On expansion, the goal would be to keep concurrentLocal variables always with * their concurrent replacing executions while non-concurrentLocal variables * stay in the scope execution *

*/ protected boolean isConcurrentLocal = false; /** * Determines whether this variable is stored in the data base. */ protected boolean isTransient = false; // transient properties protected ExecutionEntity execution; // Default constructor for SQL mapping public VariableInstanceEntity() { typedValueField.addImplicitUpdateListener(this); } public VariableInstanceEntity(String name, TypedValue value, boolean isTransient) { this(); this.name = name; this.isTransient = isTransient; typedValueField.setValue(value); } public static VariableInstanceEntity createAndInsert(String name, TypedValue value) { VariableInstanceEntity variableInstance = create(name, value, value.isTransient()); insert(variableInstance); return variableInstance; } public static void insert(VariableInstanceEntity variableInstance) { if (!variableInstance.isTransient()) { Context .getCommandContext() .getDbEntityManager() .insert(variableInstance); } } public static VariableInstanceEntity create(String name, TypedValue value, boolean isTransient) { return new VariableInstanceEntity(name, value, isTransient); } public void delete() { if (!isTransient()) { typedValueField.notifyImplicitValueUpdateIfEnabled(); } // clear value clearValueFields(); if (!isTransient) { // delete variable Context.getCommandContext().getDbEntityManager().delete(this); } } public Object getPersistentState() { Map persistentState = new HashMap<>(); if (typedValueField.getSerializerName() != null) { persistentState.put("serializerName", typedValueField.getSerializerName()); } if (longValue != null) { persistentState.put("longValue", longValue); } if (doubleValue != null) { persistentState.put("doubleValue", doubleValue); } if (textValue != null) { persistentState.put("textValue", textValue); } if (textValue2 != null) { persistentState.put("textValue2", textValue2); } if (byteArrayField.getByteArrayId() != null) { persistentState.put("byteArrayValueId", byteArrayField.getByteArrayId()); } persistentState.put("sequenceCounter", getSequenceCounter()); persistentState.put("concurrentLocal", isConcurrentLocal); persistentState.put("executionId", executionId); persistentState.put("taskId", taskId); persistentState.put("caseExecutionId", caseExecutionId); persistentState.put("caseInstanceId", caseInstanceId); persistentState.put("tenantId", tenantId); persistentState.put("processInstanceId", processInstanceId); persistentState.put("processDefinitionId", processDefinitionId); return persistentState; } public int getRevisionNext() { return revision+1; } // lazy initialized relations /////////////////////////////////////////////// public void setProcessInstanceId(String processInstanceId) { this.processInstanceId = processInstanceId; } public void setProcessDefinitionId(String processDefinitionId) { this.processDefinitionId = processDefinitionId; } public void setExecutionId(String executionId) { this.executionId = executionId; } public void setCaseInstanceId(String caseInstanceId) { this.caseInstanceId = caseInstanceId; } public void setCaseExecutionId(String caseExecutionId) { this.caseExecutionId = caseExecutionId; } public void setCaseExecution(CaseExecutionEntity caseExecution) { if (caseExecution != null) { this.caseInstanceId = caseExecution.getCaseInstanceId(); this.caseExecutionId = caseExecution.getId(); this.tenantId = caseExecution.getTenantId(); } else { this.caseInstanceId = null; this.caseExecutionId = null; this.tenantId = null; } } // byte array value ///////////////////////////////////////////////////////// // i couldn't find a easy readable way to extract the common byte array value logic // into a common class. therefor it's duplicated in VariableInstanceEntity, // HistoricVariableInstance and HistoricDetailVariableInstanceUpdateEntity public String getByteArrayValueId() { return byteArrayField.getByteArrayId(); } public void setByteArrayValueId(String byteArrayValueId) { this.byteArrayField.setByteArrayId(byteArrayValueId); } public byte[] getByteArrayValue() { return byteArrayField.getByteArrayValue(); } public void setByteArrayValue(byte[] bytes) { byteArrayField.setByteArrayValue(bytes, isTransient); } protected void deleteByteArrayValue() { byteArrayField.deleteByteArrayValue(); } // type ///////////////////////////////////////////////////////////////////// public Object getValue() { return typedValueField.getValue(); } public TypedValue getTypedValue() { return typedValueField.getTypedValue(isTransient); } public TypedValue getTypedValue(boolean deserializeValue) { return typedValueField.getTypedValue(deserializeValue, isTransient); } public void setValue(TypedValue value) { // clear value fields clearValueFields(); typedValueField.setValue(value); } public void clearValueFields() { this.longValue = null; this.doubleValue = null; this.textValue = null; this.textValue2 = null; typedValueField.clear(); if(byteArrayField.getByteArrayId() != null) { deleteByteArrayValue(); setByteArrayValueId(null); } } public String getTypeName() { return typedValueField.getTypeName(); } // entity lifecycle ///////////////////////////////////////////////////////// public void postLoad() { // make sure the serializer is initialized typedValueField.postLoad(); } // execution //////////////////////////////////////////////////////////////// protected void ensureExecutionInitialized() { if (execution == null && executionId != null) { execution = Context .getCommandContext() .getExecutionManager() .findExecutionById(executionId); } } public ExecutionEntity getExecution() { ensureExecutionInitialized(); return execution; } public void setExecution(ExecutionEntity execution) { this.execution = execution; if (execution == null) { this.executionId = null; this.processInstanceId = null; this.processDefinitionId = null; this.tenantId = null; } else { setExecutionId(execution.getId()); this.processDefinitionId = execution.getProcessDefinitionId(); this.processInstanceId = execution.getProcessInstanceId(); this.tenantId = execution.getTenantId(); } } // case execution /////////////////////////////////////////////////////////// public CaseExecutionEntity getCaseExecution() { if (caseExecutionId != null) { return Context .getCommandContext() .getCaseExecutionManager() .findCaseExecutionById(caseExecutionId); } return null; } // getters and setters ////////////////////////////////////////////////////// public String getId() { return id; } public void setId(String id) { this.id = id; } public String getTextValue() { return textValue; } public String getProcessInstanceId() { return processInstanceId; } public String getProcessDefinitionId() { return processDefinitionId; } public String getExecutionId() { return executionId; } public String getCaseInstanceId() { return caseInstanceId; } public String getCaseExecutionId() { return caseExecutionId; } public Long getLongValue() { return longValue; } public void setLongValue(Long longValue) { this.longValue = longValue; } public Double getDoubleValue() { return doubleValue; } public void setDoubleValue(Double doubleValue) { this.doubleValue = doubleValue; } public void setName(String name) { this.name = name; } public void setTextValue(String textValue) { this.textValue = textValue; } public String getName() { return name; } public int getRevision() { return revision; } public void setRevision(int revision) { this.revision = revision; } public void setSerializer(TypedValueSerializer serializer) { typedValueField.setSerializerName(serializer.getName()); } public void setSerializerName(String type) { typedValueField.setSerializerName(type); } public TypedValueSerializer getSerializer() { return typedValueField.getSerializer(); } public String getTextValue2() { return textValue2; } public void setTextValue2(String textValue2) { this.textValue2 = textValue2; } public String getTaskId() { return taskId; } public void setTaskId(String taskId) { this.taskId = taskId; } public String getBatchId() { return batchId; } public void setBatchId(String batchId) { this.batchId = batchId; } public void setTask(TaskEntity task) { if (task != null) { this.taskId = task.getId(); this.tenantId = task.getTenantId(); if (task.getExecution() != null) { setExecution(task.getExecution()); } if (task.getCaseExecution() != null) { setCaseExecution(task.getCaseExecution()); } } else { this.taskId = null; this.tenantId = null; setExecution(null); setCaseExecution(null); } } public String getActivityInstanceId() { return activityInstanceId; } public void setActivityInstanceId(String activityInstanceId) { this.activityInstanceId = activityInstanceId; } public String getSerializerName() { return typedValueField.getSerializerName(); } public String getErrorMessage() { return typedValueField.getErrorMessage(); } public String getVariableScopeId() { if (variableScopeId != null) { return variableScopeId; } if (taskId != null) { return taskId; } if (executionId != null) { return executionId; } return caseExecutionId; } public void setVariableScopeId(String variableScopeId) { this.variableScopeId = variableScopeId; } protected VariableScope getVariableScope() { if (taskId != null) { return getTask(); } else if (executionId != null) { return getExecution(); } else if (caseExecutionId != null) { return getCaseExecution(); } else { return null; } } protected TaskEntity getTask() { if (taskId != null) { return Context.getCommandContext().getTaskManager().findTaskById(taskId); } else { return null; } } //sequence counter /////////////////////////////////////////////////////////// public long getSequenceCounter() { return sequenceCounter; } public void setSequenceCounter(long sequenceCounter) { this.sequenceCounter = sequenceCounter; } public void incrementSequenceCounter() { sequenceCounter++; } public boolean isConcurrentLocal() { return isConcurrentLocal; } public void setConcurrentLocal(boolean isConcurrentLocal) { this.isConcurrentLocal = isConcurrentLocal; } @Override public void onImplicitValueUpdate(final TypedValue updatedValue) { // note: this implementation relies on the // behavior that the variable scope // of variable value can never become null ProcessApplicationReference targetProcessApplication = getContextProcessApplication(); if (targetProcessApplication != null) { Context.executeWithinProcessApplication(new Callable() { @Override public Void call() throws Exception { getVariableScope().setVariableLocal(name, updatedValue); return null; } }, targetProcessApplication, new InvocationContext(getExecution())); } else { if (!isTransient) { getVariableScope().setVariableLocal(name, updatedValue); } } } protected ProcessApplicationReference getContextProcessApplication() { if (taskId != null) { return ProcessApplicationContextUtil.getTargetProcessApplication(getTask()); } else if (executionId != null) { return ProcessApplicationContextUtil.getTargetProcessApplication(getExecution()); } else if (caseExecutionId != null) { return ProcessApplicationContextUtil.getTargetProcessApplication(getCaseExecution()); } else { return null; } } @Override public String toString() { return this.getClass().getSimpleName() + "[id=" + id + ", revision=" + revision + ", name=" + name + ", processDefinitionId=" + processDefinitionId + ", processInstanceId=" + processInstanceId + ", executionId=" + executionId + ", caseInstanceId=" + caseInstanceId + ", caseExecutionId=" + caseExecutionId + ", taskId=" + taskId + ", activityInstanceId=" + activityInstanceId + ", tenantId=" + tenantId + ", longValue=" + longValue + ", doubleValue=" + doubleValue + ", textValue=" + textValue + ", textValue2=" + textValue2 + ", byteArrayValueId=" + getByteArrayValueId() + ", configuration=" + configuration + ", isConcurrentLocal=" + isConcurrentLocal + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; VariableInstanceEntity other = (VariableInstanceEntity) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } /** * @param isTransient * true, if the variable is not stored in the data base. * Default is false. */ public void setTransient(boolean isTransient) { this.isTransient = isTransient; } /** * @return true, if the variable is transient. A transient * variable is not stored in the data base. */ public boolean isTransient() { return isTransient; } public String getTenantId() { return tenantId; } public void setTenantId(String tenantId) { this.tenantId = tenantId; } @Override public Set getReferencedEntityIds() { Set referencedEntityIds = new HashSet<>(); return referencedEntityIds; } @Override public Map getReferencedEntitiesIdAndClass() { Map referenceIdAndClass = new HashMap<>(); if (processInstanceId != null){ referenceIdAndClass.put(processInstanceId, ExecutionEntity.class); } if (executionId != null){ referenceIdAndClass.put(executionId, ExecutionEntity.class); } if (caseInstanceId != null){ referenceIdAndClass.put(caseInstanceId, CaseExecutionEntity.class); } if (caseExecutionId != null){ referenceIdAndClass.put(caseExecutionId, CaseExecutionEntity.class); } if (getByteArrayValueId() != null){ referenceIdAndClass.put(getByteArrayValueId(), ByteArrayEntity.class); } return referenceIdAndClass; } /** * * @return true processDefinitionId is introduced in 7.13, * the check is used to created missing history at {@link LegacyBehavior#createMissingHistoricVariables(org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl) LegacyBehavior#createMissingHistoricVariables} */ public boolean wasCreatedBefore713() { return this.getProcessDefinitionId() == null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy