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.persistence.entity;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.List;
  import org.activiti.engine.delegate.event.ActivitiEventType;
  import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
  import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
  import org.activiti.engine.impl.persistence.CountingExecutionEntity;
  import org.activiti.engine.impl.persistence.entity.data.DataManager;
  import org.activiti.engine.impl.persistence.entity.data.IdentityLinkDataManager;
  import org.activiti.engine.task.IdentityLinkType;
  
  /**
  
  
  
   */
  public class IdentityLinkEntityManagerImpl
      extends AbstractEntityManager<IdentityLinkEntity>
      implements IdentityLinkEntityManager {
  
      protected IdentityLinkDataManager identityLinkDataManager;
  
      public IdentityLinkEntityManagerImpl(
          ProcessEngineConfigurationImpl processEngineConfiguration,
          IdentityLinkDataManager identityLinkDataManager
      ) {
          super(processEngineConfiguration);
          this.identityLinkDataManager = identityLinkDataManager;
      }
  
      @Override
      protected DataManager<IdentityLinkEntity> getDataManager() {
          return identityLinkDataManager;
      }
  
      @Override
      public void insert(IdentityLinkEntity entity, boolean fireCreateEvent) {
          super.insert(entity, fireCreateEvent);
          getHistoryManager().recordIdentityLinkCreated(entity);
  
          if (entity.getProcessInstanceId() != null && isExecutionRelatedEntityCountEnabledGlobally()) {
              CountingExecutionEntity executionEntity = (CountingExecutionEntity) getExecutionEntityManager().findById(
                  entity.getProcessInstanceId()
              );
              if (isExecutionRelatedEntityCountEnabled(executionEntity)) {
                  executionEntity.setIdentityLinkCount(executionEntity.getIdentityLinkCount() + 1);
              }
          }
      }
  
      @Override
      public void deleteIdentityLink(IdentityLinkEntity identityLink, boolean cascadeHistory) {
          delete(identityLink, false);
          if (cascadeHistory) {
              getHistoryManager().deleteHistoricIdentityLink(identityLink.getId());
          }
  
          if (identityLink.getProcessInstanceId() != null && isExecutionRelatedEntityCountEnabledGlobally()) {
              CountingExecutionEntity executionEntity = (CountingExecutionEntity) getExecutionEntityManager().findById(
                  identityLink.getProcessInstanceId()
              );
              if (isExecutionRelatedEntityCountEnabled(executionEntity)) {
                  executionEntity.setIdentityLinkCount(executionEntity.getIdentityLinkCount() - 1);
              }
          }
  
          if (getEventDispatcher().isEnabled()) {
              getEventDispatcher().dispatchEvent(
                  ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_DELETED, identityLink)
              );
          }
      }
  
      @Override
      public List<IdentityLinkEntity> findIdentityLinksByTaskId(String taskId) {
          return identityLinkDataManager.findIdentityLinksByTaskId(taskId);
      }
  
      @Override
      public List<IdentityLinkEntity> findIdentityLinksByProcessInstanceId(String processInstanceId) {
          return identityLinkDataManager.findIdentityLinksByProcessInstanceId(processInstanceId);
      }
  
      @Override
      public List<IdentityLinkEntity> findIdentityLinksByProcessDefinitionId(String processDefinitionId) {
          return identityLinkDataManager.findIdentityLinksByProcessDefinitionId(processDefinitionId);
      }
  
      @Override
      public List<IdentityLinkEntity> findIdentityLinkByTaskUserGroupAndType(
          String taskId,
          String userId,
          String groupId,
          String type
      ) {
          return identityLinkDataManager.findIdentityLinkByTaskUserGroupAndType(taskId, userId, groupId, type);
      }
  
      @Override
      public List<IdentityLinkEntity> findIdentityLinkByProcessInstanceUserGroupAndType(
          String processInstanceId,
          String userId,
          String groupId,
          String type
      ) {
          return identityLinkDataManager.findIdentityLinkByProcessInstanceUserGroupAndType(
              processInstanceId,
              userId,
              groupId,
              type
          );
      }
  
      @Override
      public List<IdentityLinkEntity> findIdentityLinkByProcessDefinitionUserAndGroup(
          String processDefinitionId,
          String userId,
          String groupId
      ) {
          return identityLinkDataManager.findIdentityLinkByProcessDefinitionUserAndGroup(
              processDefinitionId,
              userId,
              groupId
          );
      }
  
      @Override
      public IdentityLinkEntity addIdentityLink(
          ExecutionEntity executionEntity,
          String userId,
          String groupId,
          String type
      ) {
          return addIdentityLink(executionEntity, userId, groupId, type, null);
      }
  
      @Override
      public IdentityLinkEntity addIdentityLink(
          ExecutionEntity executionEntity,
          String userId,
          String groupId,
          String type,
          byte[] details
      ) {
          IdentityLinkEntity identityLinkEntity = identityLinkDataManager.create();
          executionEntity.getIdentityLinks().add(identityLinkEntity);
          identityLinkEntity.setProcessInstance(
              executionEntity.getProcessInstance() != null ? executionEntity.getProcessInstance() : executionEntity
          );
          identityLinkEntity.setUserId(userId);
          identityLinkEntity.setGroupId(groupId);
          identityLinkEntity.setType(type);
          identityLinkEntity.setDetails(details);
          insert(identityLinkEntity);
          return identityLinkEntity;
      }
  
      @Override
      public IdentityLinkEntity addIdentityLink(TaskEntity taskEntity, String userId, String groupId, String type) {
          return addIdentityLink(taskEntity, userId, groupId, type, null);
      }
  
      @Override
      public IdentityLinkEntity addIdentityLink(
          TaskEntity taskEntity,
          String userId,
          String groupId,
          String type,
          byte[] details
      ) {
          IdentityLinkEntity identityLinkEntity = identityLinkDataManager.create();
          taskEntity.getIdentityLinks().add(identityLinkEntity);
          identityLinkEntity.setTask(taskEntity);
          identityLinkEntity.setUserId(userId);
          identityLinkEntity.setGroupId(groupId);
          identityLinkEntity.setType(type);
          identityLinkEntity.setDetails(details);
          insert(identityLinkEntity);
          if (userId != null && taskEntity.getProcessInstanceId() != null) {
              involveUser(taskEntity.getProcessInstance(), userId, IdentityLinkType.PARTICIPANT);
          }
          return identityLinkEntity;
      }
  
      @Override
      public IdentityLinkEntity addIdentityLink(
          ProcessDefinitionEntity processDefinitionEntity,
          String userId,
          String groupId
      ) {
          IdentityLinkEntity identityLinkEntity = identityLinkDataManager.create();
          processDefinitionEntity.getIdentityLinks().add(identityLinkEntity);
          identityLinkEntity.setProcessDef(processDefinitionEntity);
          identityLinkEntity.setUserId(userId);
          identityLinkEntity.setGroupId(groupId);
          identityLinkEntity.setType(IdentityLinkType.CANDIDATE);
          insert(identityLinkEntity);
          return identityLinkEntity;
      }
  
      /**
       * Adds an IdentityLink for the given user id with the specified type,
       * but only if the user is not associated with the execution entity yet.
       **/
      @Override
      public IdentityLinkEntity involveUser(ExecutionEntity executionEntity, String userId, String type) {
          for (IdentityLinkEntity identityLink : executionEntity.getIdentityLinks()) {
              if (identityLink.isUser() && identityLink.getUserId().equals(userId)) {
                  return identityLink;
              }
          }
          return addIdentityLink(executionEntity, userId, null, type);
      }
  
      @Override
      public void addCandidateUser(TaskEntity taskEntity, String userId) {
          addIdentityLink(taskEntity, userId, null, IdentityLinkType.CANDIDATE);
      }
  
      @Override
      public void addCandidateUsers(TaskEntity taskEntity, Collection<String> candidateUsers) {
          for (String candidateUser : candidateUsers) {
              addCandidateUser(taskEntity, candidateUser);
          }
      }
  
      @Override
      public void addCandidateGroup(TaskEntity taskEntity, String groupId) {
          addIdentityLink(taskEntity, null, groupId, IdentityLinkType.CANDIDATE);
      }
  
      @Override
      public void addCandidateGroups(TaskEntity taskEntity, Collection<String> candidateGroups) {
          for (String candidateGroup : candidateGroups) {
              addCandidateGroup(taskEntity, candidateGroup);
          }
      }
  
      @Override
      public void addGroupIdentityLink(TaskEntity taskEntity, String groupId, String identityLinkType) {
          addIdentityLink(taskEntity, null, groupId, identityLinkType);
      }
  
      @Override
      public void addUserIdentityLink(TaskEntity taskEntity, String userId, String identityLinkType) {
          addIdentityLink(taskEntity, userId, null, identityLinkType);
      }
  
      @Override
      public void addUserIdentityLink(TaskEntity taskEntity, String userId, String identityLinkType, byte[] details) {
          addIdentityLink(taskEntity, userId, null, identityLinkType, details);
      }
  
      @Override
      public void deleteIdentityLink(ExecutionEntity executionEntity, String userId, String groupId, String type) {
          String id = executionEntity.getProcessInstanceId() != null
              ? executionEntity.getProcessInstanceId()
              : executionEntity.getId();
          List<IdentityLinkEntity> identityLinks = findIdentityLinkByProcessInstanceUserGroupAndType(
              id,
              userId,
              groupId,
              type
          );
  
          for (IdentityLinkEntity identityLink : identityLinks) {
              deleteIdentityLink(identityLink, true);
          }
  
          executionEntity.getIdentityLinks().removeAll(identityLinks);
      }
  
      @Override
      public void deleteIdentityLink(TaskEntity taskEntity, String userId, String groupId, String type) {
          List<IdentityLinkEntity> identityLinks = findIdentityLinkByTaskUserGroupAndType(
              taskEntity.getId(),
              userId,
              groupId,
              type
          );
  
          List<String> identityLinkIds = new ArrayList<String>();
          for (IdentityLinkEntity identityLink : identityLinks) {
              deleteIdentityLink(identityLink, true);
              identityLinkIds.add(identityLink.getId());
          }
  
          // fix deleteCandidate() in create TaskListener
          List<IdentityLinkEntity> removedIdentityLinkEntities = new ArrayList<IdentityLinkEntity>();
          for (IdentityLinkEntity identityLinkEntity : taskEntity.getIdentityLinks()) {
              if (
                  IdentityLinkType.CANDIDATE.equals(identityLinkEntity.getType()) &&
                  identityLinkIds.contains(identityLinkEntity.getId()) == false
              ) {
                  if (
                      (userId != null && userId.equals(identityLinkEntity.getUserId())) ||
                      (groupId != null && groupId.equals(identityLinkEntity.getGroupId()))
                  ) {
                      deleteIdentityLink(identityLinkEntity, true);
                      removedIdentityLinkEntities.add(identityLinkEntity);
                  }
              }
          }
  
          taskEntity.getIdentityLinks().removeAll(removedIdentityLinkEntities);
      }
  
      @Override
      public void deleteIdentityLink(ProcessDefinitionEntity processDefinitionEntity, String userId, String groupId) {
          List<IdentityLinkEntity> identityLinks = findIdentityLinkByProcessDefinitionUserAndGroup(
              processDefinitionEntity.getId(),
              userId,
              groupId
          );
          for (IdentityLinkEntity identityLink : identityLinks) {
              deleteIdentityLink(identityLink, false);
          }
      }
  
      @Override
      public void deleteIdentityLinksByTaskId(String taskId) {
          List<IdentityLinkEntity> identityLinks = findIdentityLinksByTaskId(taskId);
          for (IdentityLinkEntity identityLink : identityLinks) {
              deleteIdentityLink(identityLink, false);
          }
      }
  
      @Override
      public void deleteIdentityLinksByProcDef(String processDefId) {
          identityLinkDataManager.deleteIdentityLinksByProcDef(processDefId);
      }
  
      public IdentityLinkDataManager getIdentityLinkDataManager() {
          return identityLinkDataManager;
      }
  
      public void setIdentityLinkDataManager(IdentityLinkDataManager identityLinkDataManager) {
          this.identityLinkDataManager = identityLinkDataManager;
      }
  }
  