content: /*
   * Copyright 2010-2025 Hyland Software, Inc. and its affiliates.
   *
   * 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.
   */
  package org.activiti.engine.impl;
  
  import com.fasterxml.jackson.databind.JsonNode;
  import com.fasterxml.jackson.databind.node.ArrayNode;
  import com.fasterxml.jackson.databind.node.ObjectNode;
  import org.activiti.engine.DynamicBpmnConstants;
  import org.activiti.engine.DynamicBpmnService;
  import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
  import org.activiti.engine.impl.cmd.GetProcessDefinitionInfoCmd;
  import org.activiti.engine.impl.cmd.SaveProcessDefinitionInfoCmd;
  import org.activiti.engine.repository.ProcessDefinition;
  
  /**
  
   */
  public class DynamicBpmnServiceImpl extends ServiceImpl implements DynamicBpmnService, DynamicBpmnConstants {
  
      public DynamicBpmnServiceImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
          super(processEngineConfiguration);
      }
  
      public ObjectNode getProcessDefinitionInfo(String processDefinitionId) {
          return commandExecutor.execute(new GetProcessDefinitionInfoCmd(processDefinitionId));
      }
  
      public ObjectNode getProcessDefinitionInfo(ProcessDefinition processDefinition) {
          return commandExecutor.execute(new GetProcessDefinitionInfoCmd(processDefinition));
      }
  
      public void saveProcessDefinitionInfo(String processDefinitionId, ObjectNode infoNode) {
          commandExecutor.execute(new SaveProcessDefinitionInfoCmd(processDefinitionId, infoNode));
      }
  
      public ObjectNode changeServiceTaskClassName(String id, String className) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeServiceTaskClassName(id, className, infoNode);
          return infoNode;
      }
  
      public void changeServiceTaskClassName(String id, String className, ObjectNode infoNode) {
          setElementProperty(id, SERVICE_TASK_CLASS_NAME, className, infoNode);
      }
  
      public ObjectNode changeServiceTaskExpression(String id, String expression) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeServiceTaskExpression(id, expression, infoNode);
          return infoNode;
      }
  
      public void changeServiceTaskExpression(String id, String expression, ObjectNode infoNode) {
          setElementProperty(id, SERVICE_TASK_EXPRESSION, expression, infoNode);
      }
  
      public ObjectNode changeServiceTaskDelegateExpression(String id, String expression) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeServiceTaskDelegateExpression(id, expression, infoNode);
          return infoNode;
      }
  
      public void changeServiceTaskDelegateExpression(String id, String expression, ObjectNode infoNode) {
          setElementProperty(id, SERVICE_TASK_DELEGATE_EXPRESSION, expression, infoNode);
      }
  
      public ObjectNode changeScriptTaskScript(String id, String script) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeScriptTaskScript(id, script, infoNode);
          return infoNode;
      }
  
      public void changeScriptTaskScript(String id, String script, ObjectNode infoNode) {
          setElementProperty(id, SCRIPT_TASK_SCRIPT, script, infoNode);
      }
  
      public ObjectNode changeUserTaskName(String id, String name) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeUserTaskName(id, name, infoNode);
          return infoNode;
      }
  
      public void changeUserTaskName(String id, String name, ObjectNode infoNode) {
          setElementProperty(id, USER_TASK_NAME, name, infoNode);
      }
  
      public ObjectNode changeUserTaskDescription(String id, String description) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeUserTaskDescription(id, description, infoNode);
          return infoNode;
      }
  
      public void changeUserTaskDescription(String id, String description, ObjectNode infoNode) {
          setElementProperty(id, USER_TASK_DESCRIPTION, description, infoNode);
      }
  
      public ObjectNode changeUserTaskDueDate(String id, String dueDate) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeUserTaskDueDate(id, dueDate, infoNode);
          return infoNode;
      }
  
      public void changeUserTaskDueDate(String id, String dueDate, ObjectNode infoNode) {
          setElementProperty(id, USER_TASK_DUEDATE, dueDate, infoNode);
      }
  
      public ObjectNode changeUserTaskPriority(String id, String priority) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeUserTaskPriority(id, priority, infoNode);
          return infoNode;
      }
  
      public void changeUserTaskPriority(String id, String priority, ObjectNode infoNode) {
          setElementProperty(id, USER_TASK_PRIORITY, priority, infoNode);
      }
  
      public ObjectNode changeUserTaskCategory(String id, String category) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeUserTaskCategory(id, category, infoNode);
          return infoNode;
      }
  
      public void changeUserTaskCategory(String id, String category, ObjectNode infoNode) {
          setElementProperty(id, USER_TASK_CATEGORY, category, infoNode);
      }
  
      public ObjectNode changeUserTaskFormKey(String id, String formKey) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeUserTaskFormKey(id, formKey, infoNode);
          return infoNode;
      }
  
      public void changeUserTaskFormKey(String id, String formKey, ObjectNode infoNode) {
          setElementProperty(id, USER_TASK_FORM_KEY, formKey, infoNode);
      }
  
      public ObjectNode changeUserTaskAssignee(String id, String assignee) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeUserTaskAssignee(id, assignee, infoNode);
          return infoNode;
      }
  
      public void changeUserTaskAssignee(String id, String assignee, ObjectNode infoNode) {
          setElementProperty(id, USER_TASK_ASSIGNEE, assignee, infoNode);
      }
  
      public ObjectNode changeUserTaskOwner(String id, String owner) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeUserTaskOwner(id, owner, infoNode);
          return infoNode;
      }
  
      public void changeUserTaskOwner(String id, String owner, ObjectNode infoNode) {
          setElementProperty(id, USER_TASK_OWNER, owner, infoNode);
      }
  
      public ObjectNode changeUserTaskCandidateUser(
          String id,
          String candidateUser,
          boolean overwriteOtherChangedEntries
      ) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeUserTaskCandidateUser(id, candidateUser, overwriteOtherChangedEntries, infoNode);
          return infoNode;
      }
  
      public void changeUserTaskCandidateUser(
          String id,
          String candidateUser,
          boolean overwriteOtherChangedEntries,
          ObjectNode infoNode
      ) {
          ArrayNode valuesNode = null;
          if (overwriteOtherChangedEntries) {
              valuesNode = processEngineConfiguration.getObjectMapper().createArrayNode();
          } else {
              if (doesElementPropertyExist(id, USER_TASK_CANDIDATE_USERS, infoNode)) {
                  valuesNode = (ArrayNode) infoNode.get(BPMN_NODE).get(id).get(USER_TASK_CANDIDATE_USERS);
              }
  
              if (valuesNode == null || valuesNode.isNull()) {
                  valuesNode = processEngineConfiguration.getObjectMapper().createArrayNode();
              }
          }
  
          valuesNode.add(candidateUser);
          setElementProperty(id, USER_TASK_CANDIDATE_USERS, valuesNode, infoNode);
      }
  
      public ObjectNode changeUserTaskCandidateGroup(
          String id,
          String candidateGroup,
          boolean overwriteOtherChangedEntries
      ) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeUserTaskCandidateGroup(id, candidateGroup, overwriteOtherChangedEntries, infoNode);
          return infoNode;
      }
  
      public void changeUserTaskCandidateGroup(
          String id,
          String candidateGroup,
          boolean overwriteOtherChangedEntries,
          ObjectNode infoNode
      ) {
          ArrayNode valuesNode = null;
          if (overwriteOtherChangedEntries) {
              valuesNode = processEngineConfiguration.getObjectMapper().createArrayNode();
          } else {
              if (doesElementPropertyExist(id, USER_TASK_CANDIDATE_GROUPS, infoNode)) {
                  valuesNode = (ArrayNode) infoNode.get(BPMN_NODE).get(id).get(USER_TASK_CANDIDATE_GROUPS);
              }
  
              if (valuesNode == null || valuesNode.isNull()) {
                  valuesNode = processEngineConfiguration.getObjectMapper().createArrayNode();
              }
          }
  
          valuesNode.add(candidateGroup);
          setElementProperty(id, USER_TASK_CANDIDATE_GROUPS, valuesNode, infoNode);
      }
  
      public ObjectNode changeDmnTaskDecisionTableKey(String id, String decisionTableKey) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeDmnTaskDecisionTableKey(id, decisionTableKey, infoNode);
          return infoNode;
      }
  
      public void changeDmnTaskDecisionTableKey(String id, String decisionTableKey, ObjectNode infoNode) {
          setElementProperty(id, DMN_TASK_DECISION_TABLE_KEY, decisionTableKey, infoNode);
      }
  
      public ObjectNode changeSequenceFlowCondition(String id, String condition) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeSequenceFlowCondition(id, condition, infoNode);
          return infoNode;
      }
  
      public void changeSequenceFlowCondition(String id, String condition, ObjectNode infoNode) {
          setElementProperty(id, SEQUENCE_FLOW_CONDITION, condition, infoNode);
      }
  
      public ObjectNode getBpmnElementProperties(String id, ObjectNode infoNode) {
          ObjectNode propertiesNode = null;
          ObjectNode bpmnNode = getBpmnNode(infoNode);
          if (bpmnNode != null) {
              propertiesNode = (ObjectNode) bpmnNode.get(id);
          }
          return propertiesNode;
      }
  
      public ObjectNode changeLocalizationName(String language, String id, String value) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeLocalizationName(language, id, value, infoNode);
          return infoNode;
      }
  
      public void changeLocalizationName(String language, String id, String value, ObjectNode infoNode) {
          setLocalizationProperty(language, id, LOCALIZATION_NAME, value, infoNode);
      }
  
      public ObjectNode changeLocalizationDescription(String language, String id, String value) {
          ObjectNode infoNode = processEngineConfiguration.getObjectMapper().createObjectNode();
          changeLocalizationDescription(language, id, value, infoNode);
          return infoNode;
      }
  
      public void changeLocalizationDescription(String language, String id, String value, ObjectNode infoNode) {
          setLocalizationProperty(language, id, LOCALIZATION_DESCRIPTION, value, infoNode);
      }
  
      public ObjectNode getLocalizationElementProperties(String language, String id, ObjectNode infoNode) {
          ObjectNode propertiesNode = null;
          ObjectNode localizationNode = getLocalizationNode(infoNode);
          if (localizationNode != null) {
              JsonNode languageNode = localizationNode.get(language);
              if (languageNode != null) {
                  propertiesNode = (ObjectNode) languageNode.get(id);
              }
          }
          return propertiesNode;
      }
  
      protected boolean doesElementPropertyExist(String id, String propertyName, ObjectNode infoNode) {
          boolean exists = false;
          if (
              infoNode.get(BPMN_NODE) != null &&
              infoNode.get(BPMN_NODE).get(id) != null &&
              infoNode.get(BPMN_NODE).get(id).get(propertyName) != null
          ) {
              JsonNode propNode = infoNode.get(BPMN_NODE).get(id).get(propertyName);
              if (!propNode.isNull()) {
                  exists = true;
              }
          }
          return exists;
      }
  
      protected void setElementProperty(String id, String propertyName, String propertyValue, ObjectNode infoNode) {
          ObjectNode bpmnNode = createOrGetBpmnNode(infoNode);
          if (!bpmnNode.has(id)) {
              bpmnNode.putObject(id);
          }
  
          ((ObjectNode) bpmnNode.get(id)).put(propertyName, propertyValue);
      }
  
      protected void setElementProperty(String id, String propertyName, JsonNode propertyValue, ObjectNode infoNode) {
          ObjectNode bpmnNode = createOrGetBpmnNode(infoNode);
          if (!bpmnNode.has(id)) {
              bpmnNode.putObject(id);
          }
  
          ((ObjectNode) bpmnNode.get(id)).set(propertyName, propertyValue);
      }
  
      protected ObjectNode createOrGetBpmnNode(ObjectNode infoNode) {
          if (!infoNode.has(BPMN_NODE)) {
              infoNode.putObject(BPMN_NODE);
          }
          return (ObjectNode) infoNode.get(BPMN_NODE);
      }
  
      protected ObjectNode getBpmnNode(ObjectNode infoNode) {
          return (ObjectNode) infoNode.get(BPMN_NODE);
      }
  
      protected void setLocalizationProperty(
          String language,
          String id,
          String propertyName,
          String propertyValue,
          ObjectNode infoNode
      ) {
          ObjectNode localizationNode = createOrGetLocalizationNode(infoNode);
          if (!localizationNode.has(language)) {
              localizationNode.putObject(language);
          }
  
          ObjectNode languageNode = (ObjectNode) localizationNode.get(language);
          if (!languageNode.has(id)) {
              languageNode.putObject(id);
          }
  
          ((ObjectNode) languageNode.get(id)).put(propertyName, propertyValue);
      }
  
      protected ObjectNode createOrGetLocalizationNode(ObjectNode infoNode) {
          if (!infoNode.has(LOCALIZATION_NODE)) {
              infoNode.putObject(LOCALIZATION_NODE);
          }
          return (ObjectNode) infoNode.get(LOCALIZATION_NODE);
      }
  
      protected ObjectNode getLocalizationNode(ObjectNode infoNode) {
          return (ObjectNode) infoNode.get(LOCALIZATION_NODE);
      }
  }
  