| /******************************************************************************* |
| * Copyright (c) 2004, 2007 Boeing. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Boeing - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.osee.ats.core.client.artifact; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.osee.ats.api.ai.IAtsActionableItem; |
| import org.eclipse.osee.ats.api.data.AtsArtifactTypes; |
| import org.eclipse.osee.ats.api.data.AtsAttributeTypes; |
| import org.eclipse.osee.ats.api.data.AtsRelationTypes; |
| import org.eclipse.osee.ats.api.workflow.IAtsAction; |
| import org.eclipse.osee.ats.api.workflow.IAtsTask; |
| import org.eclipse.osee.ats.api.workflow.IAtsTeamWorkflow; |
| import org.eclipse.osee.ats.core.client.internal.Activator; |
| import org.eclipse.osee.ats.core.client.internal.AtsClientService; |
| import org.eclipse.osee.ats.core.client.search.UserRelatedToAtsObjectSearch; |
| import org.eclipse.osee.ats.core.client.util.AtsUtilClient; |
| import org.eclipse.osee.ats.core.client.workflow.AbstractWorkflowArtifact; |
| import org.eclipse.osee.ats.core.util.AtsUtilCore; |
| import org.eclipse.osee.framework.core.data.IRelationType; |
| import org.eclipse.osee.framework.jdk.core.type.OseeCoreException; |
| import org.eclipse.osee.framework.jdk.core.util.Strings; |
| import org.eclipse.osee.framework.skynet.core.User; |
| import org.eclipse.osee.framework.skynet.core.artifact.Artifact; |
| import org.eclipse.osee.framework.skynet.core.artifact.ArtifactCheck; |
| import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactQuery; |
| |
| /** |
| * Check for certain conditions that must be met to delete an ATS object or User artifact. |
| * |
| * @author Donald G. Dunne |
| */ |
| public class AtsArtifactChecks extends ArtifactCheck { |
| |
| private static final List<Long> Admin_Only_Relation_Type_Ids = |
| org.eclipse.osee.framework.jdk.core.util.Collections.getAggregate( |
| AtsRelationTypes.TeamWorkflowToReview_Review.getGuid(), AtsRelationTypes.ActionToWorkflow_Action.getGuid()); |
| private static boolean deletionChecksEnabled = !AtsUtilCore.isInTest(); |
| |
| @Override |
| public IStatus isDeleteableRelation(Artifact artifact, IRelationType relationType) throws OseeCoreException { |
| if (deletionChecksEnabled) { |
| boolean isAtsAdmin = AtsUtilClient.isAtsAdmin(); |
| if (!isAtsAdmin && Admin_Only_Relation_Type_Ids.contains(relationType.getGuid())) { |
| return createStatus( |
| String.format("Deletion of relation type [%s] off artifact [%s] is only permitted by ATS Admin", |
| relationType, artifact)); |
| } |
| } |
| return Status.OK_STATUS; |
| } |
| |
| @Override |
| public IStatus isDeleteable(Collection<Artifact> artifacts) throws OseeCoreException { |
| boolean isAtsAdmin = AtsUtilClient.isAtsAdmin(); |
| |
| IStatus result = Status.OK_STATUS; |
| |
| if (deletionChecksEnabled) { |
| Set<Artifact> allArtifacts = getAllArtifacts(artifacts, new HashSet<>()); |
| |
| if (result.isOK()) { |
| result = checkActionableItems(isAtsAdmin, allArtifacts); |
| } |
| |
| if (result.isOK()) { |
| result = checkTeamDefinitions(isAtsAdmin, allArtifacts); |
| } |
| |
| if (result.isOK()) { |
| result = checkAtsWorkDefinitions(isAtsAdmin, allArtifacts); |
| } |
| |
| if (result.isOK()) { |
| result = checkUsers(allArtifacts); |
| } |
| |
| if (result.isOK()) { |
| result = checkActions(isAtsAdmin, allArtifacts); |
| } |
| |
| if (result.isOK()) { |
| result = checkWorkPackages(isAtsAdmin, allArtifacts); |
| } |
| } |
| |
| return result; |
| } |
| |
| // Get all artifacts and recurse down default hierarchy |
| private Set<Artifact> getAllArtifacts(Collection<Artifact> artifacts, Set<Artifact> allArtifacts) { |
| for (Artifact art : artifacts) { |
| if (art.isOnBranch(AtsUtilCore.getAtsBranch())) { |
| allArtifacts.addAll(art.getDescendants()); |
| } |
| } |
| return allArtifacts; |
| } |
| |
| private IStatus checkActions(boolean isAtsAdmin, Collection<Artifact> artifacts) { |
| for (Artifact art : artifacts) { |
| if (!isAtsAdmin && isWorkflowOrAction(art) && !isTask(art)) { |
| return createStatus(String.format("Deletion of [%s] is only permitted by ATS Admin; %s invalid", |
| art.getArtifactTypeName(), art.toStringWithId())); |
| } |
| String error = isWorkflowOrActionPermittedByAnyone(art, artifacts); |
| if (Strings.isValid(error)) { |
| return createStatus(String.format("Deletion of artifact type [%s] object %s is not permitted. Error: [%s]", |
| art.getArtifactTypeName(), art.toStringWithId(), error)); |
| } |
| } |
| return Status.OK_STATUS; |
| } |
| |
| private String isWorkflowOrActionPermittedByAnyone(Artifact art, Collection<Artifact> allArtifacts) { |
| if (art.isOfType(AtsArtifactTypes.Action)) { |
| for (IAtsTeamWorkflow teamWf : AtsClientService.get().getWorkItemService().getTeams((IAtsAction) art)) { |
| if (!allArtifacts.contains(teamWf)) { |
| return String.format("Can't delete action %s without deleting workflow %s, use ATS World Editor", |
| art.toStringWithId(), teamWf.toStringWithId()); |
| } |
| } |
| } |
| if (art.isOfType(AtsArtifactTypes.TeamWorkflow)) { |
| IAtsTeamWorkflow teamWf = AtsClientService.get().getWorkItemFactory().getTeamWf(art); |
| if (!allArtifacts.contains(teamWf.getParentAction())) { |
| return String.format("Can't delete workflow %s without deleting action %s, use ATS World Editor", |
| teamWf.toStringWithId(), teamWf.getParentAction().toStringWithId()); |
| } |
| } |
| return null; |
| } |
| |
| private boolean isWorkflowOrAction(Artifact art) { |
| return art instanceof AbstractWorkflowArtifact || art instanceof IAtsAction; |
| } |
| |
| private boolean isTask(Artifact art) { |
| return art instanceof IAtsTask; |
| } |
| |
| private IStatus createStatus(String message) { |
| return new Status(IStatus.ERROR, Activator.PLUGIN_ID, message); |
| } |
| |
| private IStatus checkActionableItems(boolean isAtsAdmin, Collection<Artifact> artifacts) throws OseeCoreException { |
| Set<String> aiaGuids = getActionableItemGuidsWithRecurse(new HashSet<String>(), artifacts); |
| if (!aiaGuids.isEmpty()) { |
| List<Artifact> teamWfsRelatedToAis = ArtifactQuery.getArtifactListFromTypeAndAttribute( |
| AtsArtifactTypes.TeamWorkflow, AtsAttributeTypes.ActionableItem, aiaGuids, AtsUtilCore.getAtsBranch(), 10); |
| if (!teamWfsRelatedToAis.isEmpty()) { |
| return createStatus(String.format( |
| "Actionable Items (or children AIs) [%s] selected to delete have related Team Workflows; Delete or re-assign Team Workflows first.", |
| aiaGuids)); |
| } |
| if (!isAtsAdmin) { |
| return createStatus("Deletion of Actionable Items is only permitted by ATS Admin."); |
| } |
| } |
| return Status.OK_STATUS; |
| } |
| |
| private Set<String> getActionableItemGuidsWithRecurse(HashSet<String> aiaGuids, Collection<Artifact> artifacts) { |
| for (Artifact art : artifacts) { |
| if (art.isOfType(AtsArtifactTypes.ActionableItem)) { |
| IAtsActionableItem aia = |
| AtsClientService.get().getCache().getByUuid(art.getUuid(), IAtsActionableItem.class); |
| if (aia != null) { |
| aiaGuids.add(AtsUtilCore.getGuid(aia)); |
| Collection<Artifact> childArts = art.getChildren(); |
| if (!aia.getChildrenActionableItems().isEmpty()) { |
| getActionableItemGuidsWithRecurse(aiaGuids, childArts); |
| } |
| } |
| } |
| } |
| return aiaGuids; |
| } |
| |
| private IStatus checkTeamDefinitions(boolean isAtsAdmin, Collection<Artifact> artifacts) throws OseeCoreException { |
| List<String> guids = new ArrayList<>(); |
| for (Artifact art : artifacts) { |
| if (art.isOfType(AtsArtifactTypes.TeamDefinition)) { |
| guids.add(art.getGuid()); |
| } |
| } |
| if (!guids.isEmpty()) { |
| List<Artifact> artifactListFromIds = ArtifactQuery.getArtifactListFromAttributeValues( |
| AtsAttributeTypes.TeamDefinition, guids, AtsUtilCore.getAtsBranch(), 5); |
| if (artifactListFromIds.size() > 0) { |
| return createStatus(String.format( |
| "Team Definition (or children Team Definitions) [%s] selected to delete have related Team Workflows; Delete or re-assign Team Workflows first.", |
| guids)); |
| } |
| if (!isAtsAdmin) { |
| return createStatus("Deletion of Team Definitions is only permitted by ATS Admin."); |
| } |
| } |
| return Status.OK_STATUS; |
| } |
| |
| private IStatus checkWorkPackages(boolean isAtsAdmin, Collection<Artifact> artifacts) throws OseeCoreException { |
| List<String> guids = new ArrayList<>(); |
| for (Artifact art : artifacts) { |
| if (art.isOfType(AtsArtifactTypes.WorkPackage)) { |
| guids.add(art.getGuid()); |
| } |
| } |
| if (!guids.isEmpty()) { |
| List<Artifact> artifactListFromIds = ArtifactQuery.getArtifactListFromAttributeValues( |
| AtsAttributeTypes.WorkPackageGuid, guids, AtsUtilCore.getAtsBranch(), 5); |
| if (artifactListFromIds.size() > 0) { |
| return createStatus(String.format( |
| "Work Packages [%s] selected to delete have related Work Items; Delete or re-assign Work Packages first.", |
| guids)); |
| } |
| } |
| return Status.OK_STATUS; |
| } |
| |
| private IStatus checkAtsWorkDefinitions(boolean isAtsAdmin, Collection<Artifact> artifacts) throws OseeCoreException { |
| for (Artifact art : artifacts) { |
| if (art.isOfType(AtsArtifactTypes.WorkDefinition)) { |
| List<Artifact> artifactListFromTypeAndAttribute = |
| ArtifactQuery.getArtifactListFromTypeAndAttribute(AtsArtifactTypes.WorkDefinition, |
| AtsAttributeTypes.WorkflowDefinition, art.getName(), AtsUtilCore.getAtsBranch()); |
| if (artifactListFromTypeAndAttribute.size() > 0) { |
| return createStatus(String.format( |
| "ATS WorkDefinition [%s] selected to delete has ats.WorkDefinition attributes set to it's name in %d artifact. These must be changed first.", |
| art, artifactListFromTypeAndAttribute.size())); |
| } |
| if (!isAtsAdmin) { |
| return createStatus("Deletion of Work Definitions is only permitted by ATS Admin."); |
| } |
| } |
| } |
| return Status.OK_STATUS; |
| } |
| |
| private IStatus checkUsers(Collection<Artifact> artifacts) throws OseeCoreException { |
| Set<User> users = new HashSet<>(); |
| for (Artifact art : artifacts) { |
| if (art instanceof User) { |
| users.add((User) art); |
| } |
| } |
| for (User user : users) { |
| UserRelatedToAtsObjectSearch srch = new UserRelatedToAtsObjectSearch( |
| AtsClientService.get().getUserServiceClient().getUserFromOseeUser(user), false); |
| if (srch.getResults().size() > 0) { |
| return createStatus(String.format( |
| "User name: \"%s\" userId: \"%s\" selected to delete has related ATS Objects; Un-relate to ATS first before deleting.", |
| user.getName(), user.getUserId())); |
| } |
| } |
| return Status.OK_STATUS; |
| } |
| |
| public static void setDeletionChecksEnabled(boolean deletionChecksEnabled) { |
| AtsArtifactChecks.deletionChecksEnabled = deletionChecksEnabled; |
| } |
| } |