blob: 3b390899b94b6b0c85e39e3f4e756c8517b0f7fd [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2004, 2007 Boeing
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Boeing - initial API and implementation
**********************************************************************/
package org.eclipse.osee.ats.ide.workflow;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.eclipse.osee.ats.api.IAtsWorkItem;
import org.eclipse.osee.ats.api.ai.IAtsActionableItem;
import org.eclipse.osee.ats.api.config.WorkType;
import org.eclipse.osee.ats.api.data.AtsAttributeTypes;
import org.eclipse.osee.ats.api.user.AtsCoreUsers;
import org.eclipse.osee.ats.api.user.AtsUser;
import org.eclipse.osee.ats.api.util.AtsUtil;
import org.eclipse.osee.ats.api.util.IAtsChangeSet;
import org.eclipse.osee.ats.api.workdef.IAtsStateDefinition;
import org.eclipse.osee.ats.api.workdef.IAtsWorkDefinition;
import org.eclipse.osee.ats.api.workdef.IStateToken;
import org.eclipse.osee.ats.api.workdef.model.RuleDefinitionOption;
import org.eclipse.osee.ats.api.workflow.IAtsAction;
import org.eclipse.osee.ats.api.workflow.IAtsTeamWorkflow;
import org.eclipse.osee.ats.api.workflow.log.IAtsLog;
import org.eclipse.osee.ats.api.workflow.log.IAtsLogItem;
import org.eclipse.osee.ats.api.workflow.log.LogType;
import org.eclipse.osee.ats.api.workflow.state.IAtsStateManager;
import org.eclipse.osee.ats.core.util.AtsObjects;
import org.eclipse.osee.ats.ide.internal.Activator;
import org.eclipse.osee.ats.ide.internal.AtsApiService;
import org.eclipse.osee.ats.ide.workflow.review.AbstractReviewArtifact;
import org.eclipse.osee.ats.ide.workflow.teamwf.TeamWorkFlowArtifact;
import org.eclipse.osee.framework.core.data.ArtifactTypeToken;
import org.eclipse.osee.framework.core.data.BranchToken;
import org.eclipse.osee.framework.core.data.TransactionId;
import org.eclipse.osee.framework.core.enums.PermissionEnum;
import org.eclipse.osee.framework.core.util.IGroupExplorerProvider;
import org.eclipse.osee.framework.core.util.Result;
import org.eclipse.osee.framework.jdk.core.result.XResultData;
import org.eclipse.osee.framework.jdk.core.type.OseeArgumentException;
import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
import org.eclipse.osee.framework.jdk.core.util.Conditions;
import org.eclipse.osee.framework.jdk.core.util.Lib;
import org.eclipse.osee.framework.jdk.core.util.Strings;
import org.eclipse.osee.framework.logging.OseeLevel;
import org.eclipse.osee.framework.logging.OseeLog;
import org.eclipse.osee.framework.skynet.core.artifact.Artifact;
import org.eclipse.osee.framework.skynet.core.artifact.Attribute;
import org.eclipse.osee.framework.skynet.core.relation.RelationManager;
/**
* @author Donald G. Dunne
*/
public abstract class AbstractWorkflowArtifact extends AbstractAtsArtifact implements IAtsWorkItem, IGroupExplorerProvider {
private Collection<AtsUser> transitionAssignees;
protected AbstractWorkflowArtifact parentAwa;
protected TeamWorkFlowArtifact parentTeamArt;
protected IAtsAction parentAction;
private IAtsLog atsLog;
private TransactionId atsLogTx;
public AbstractWorkflowArtifact(Long id, String guid, BranchToken branch, ArtifactTypeToken artifactType) {
super(id, guid, branch, artifactType);
}
@Override
public List<AtsUser> getImplementers() {
return AtsApiService.get().getImplementerService().getImplementers(this);
}
public AbstractWorkflowArtifact getParentAWA() {
return parentAwa;
}
@Override
public IAtsTeamWorkflow getParentTeamWorkflow() {
return parentTeamArt;
}
@Override
public IAtsAction getParentAction() {
Artifact actionArt = (Artifact) parentAction;
if (actionArt != null) {
return AtsApiService.get().getWorkItemService().getAction(actionArt);
}
return null;
}
public String getEditorTitle() {
return getArtifactType() + ": " + getName();
}
@Override
public void clearCaches() {
implementersStr = null;
parentAction = null;
parentAwa = null;
parentTeamArt = null;
AtsApiService.get().getStateFactory().clearStateManager(this);
atsLog = null;
AtsApiService.get().getWorkDefinitionService().internalClearWorkDefinition(this);
}
public String getCurrentStateName() {
return getStateMgr().getCurrentStateName();
}
@Override
public boolean isInState(IStateToken state) {
return getStateMgr().getCurrentStateName().equals(state.getName());
}
public String implementersStr = null;
public double getManHrsPerDayPreference() {
return AtsUtil.DEFAULT_HOURS_PER_WORK_DAY;
}
/**
* Return true if this artifact, it's ATS relations and any of the other side artifacts are dirty
*
* @return true if any object in SMA tree is dirty
*/
public XResultData isWfeDirty(XResultData rd) {
try {
Set<Artifact> artifacts = new HashSet<>();
getSmaArtifactsOneLevel(this, artifacts);
for (Artifact artifact : artifacts) {
if (artifact instanceof AbstractWorkflowArtifact) {
AbstractWorkflowArtifact awa = (AbstractWorkflowArtifact) artifact;
if (awa.getStateMgr() == null) {
rd.errorf("StateManager can not be null for %s", artifact.toStringWithId());
}
awa.getStateMgr().isDirty();
if (awa.getLog().isDirty()) {
rd.error("Log is dirty");
}
}
if (artifact.isDirty()) {
for (Attribute<?> attribute : artifact.internalGetAttributes()) {
if (attribute.isDirty()) {
rd.errorf("Dirty Attribute: " + attribute.getNameValueDescription() + "\n");
}
}
String rString = RelationManager.reportHasDirtyLinks(artifact);
if (Strings.isValid(rString)) {
rd.errorf("Dirty Relation Tab: " + rString + " \n");
}
}
}
} catch (Exception ex) {
OseeLog.log(Activator.class, Level.SEVERE, "Unable to determine if artifact is dirty " + getAtsId(), ex);
rd.errorf("Exception in isWfeDirty [%s]", Lib.exceptionToString(ex));
}
return rd;
}
public void save(IAtsChangeSet changes) {
try {
Set<Artifact> artifacts = new HashSet<>();
getSmaArtifactsOneLevel(this, artifacts);
for (Artifact artifact : artifacts) {
if (artifact instanceof AbstractWorkflowArtifact) {
changes.add(artifact);
}
}
} catch (Exception ex) {
OseeLog.log(Activator.class, OseeLevel.SEVERE_POPUP, "Can't save artifact " + getAtsId(), ex);
}
}
public void revert() {
try {
Set<Artifact> artifacts = new HashSet<>();
getSmaArtifactsOneLevel(this, artifacts);
for (Artifact artifact : artifacts) {
artifact.reloadAttributesAndRelations();
if (artifact instanceof IAtsWorkItem) {
AtsApiService.get().getStateFactory().load((IAtsWorkItem) artifact, getStateMgr());
}
}
} catch (Exception ex) {
OseeLog.log(Activator.class, OseeLevel.SEVERE_POPUP, "Can't revert artifact " + getAtsId(), ex);
}
}
public void getSmaArtifactsOneLevel(AbstractWorkflowArtifact smaArtifact, Set<Artifact> artifacts) {
artifacts.add(smaArtifact);
}
@Override
public Artifact getParentAtsArtifact() {
return getParentAWA();
}
/**
* Return Percent Complete ONLY on tasks related to stateName. Total Percent / # Tasks
*/
public int getPercentCompleteSMAStateTasks(IStateToken state) {
if (!(this instanceof TeamWorkFlowArtifact)) {
return 0;
}
return AtsApiService.get().getEarnedValueService().getPercentCompleteFromTasks(this, state);
}
@Override
public String getGroupExplorerName() {
return String.format("[%s] %s", getStateMgr().getCurrentStateName(), getName());
}
@Override
public IAtsLog getLog() {
if (atsLog == null || !getTransaction().equals(atsLogTx)) {
atsLog = AtsApiService.get().getLogFactory().getLogLoaded(this, AtsApiService.get().getAttributeResolver());
atsLogTx = getTransaction();
}
return atsLog;
}
public Result getUserInputNeeded() {
return Result.FalseResult;
}
@Override
public IAtsWorkDefinition getWorkDefinition() {
try {
return AtsApiService.get().getWorkDefinitionService().getWorkDefinition(this);
} catch (Exception ex) {
OseeLog.log(Activator.class, Level.SEVERE, ex);
}
return null;
}
@Override
public IAtsStateDefinition getStateDefinition() {
if (getStateMgr().getCurrentStateName() == null) {
return null;
}
return getWorkDefinition().getStateByName(getStateMgr().getCurrentStateName());
}
public IAtsStateDefinition getStateDefinitionByName(String name) {
return getWorkDefinition().getStateByName(name);
}
public boolean isAccessControlWrite() {
return AtsApiService.get().getAccessControlService().hasArtifactPermission(this, PermissionEnum.WRITE,
null).isSuccess();
}
/**
* Return true if workItem is TeamWorkflowArtifact or review of a team workflow and it's IAtsTeamDefinition has rule
* set
*/
public boolean teamDefHasRule(RuleDefinitionOption option) {
TeamWorkFlowArtifact teamArt = null;
if (isTeamWorkflow()) {
teamArt = (TeamWorkFlowArtifact) this;
}
if (this instanceof AbstractReviewArtifact) {
teamArt = (TeamWorkFlowArtifact) ((AbstractReviewArtifact) this).getParentTeamWorkflow();
}
if (teamArt == null) {
return false;
}
try {
return AtsApiService.get().getTeamDefinitionService().hasRule(teamArt.getTeamDefinition(), option.name());
} catch (Exception ex) {
OseeLog.log(Activator.class, OseeLevel.SEVERE_POPUP, ex);
return false;
}
}
@Override
public Date getCreatedDate() {
return getSoleAttributeValue(AtsAttributeTypes.CreatedDate, null);
}
@Override
public Date getCancelledDate() {
return getSoleAttributeValue(AtsAttributeTypes.CancelledDate, null);
}
@Override
public AtsUser getCreatedBy() {
String userId = getSoleAttributeValue(AtsAttributeTypes.CreatedBy, null);
if (Strings.isValid(userId)) {
return AtsApiService.get().getUserService().getUserByUserId(userId);
}
return null;
}
public Date internalGetCancelledDate() {
return getSoleAttributeValue(AtsAttributeTypes.CancelledDate, null);
}
@Override
public AtsUser getCancelledBy() {
String userId = getSoleAttributeValue(AtsAttributeTypes.CancelledBy, null);
if (Strings.isValid(userId)) {
return AtsApiService.get().getUserService().getUserByUserId(userId);
}
return null;
}
@Override
public String getCancelledReason() {
String reason = getSoleAttributeValue(AtsAttributeTypes.CancelledReason, null);
if (!Strings.isValid(reason)) {
reason = getSoleAttributeValue(AtsAttributeTypes.CancelledReasonEnum, null);
}
if (!Strings.isValid(reason)) {
reason = getLog().internalGetCancelledReason();
}
return reason;
}
@Override
public String getCancelledFromState() {
return getSoleAttributeValue(AtsAttributeTypes.CancelledFromState, null);
}
@Override
public Date getCompletedDate() {
return getSoleAttributeValue(AtsAttributeTypes.CompletedDate, null);
}
@Override
public AtsUser getCompletedBy() {
String userId = getSoleAttributeValue(AtsAttributeTypes.CompletedBy, null);
if (Strings.isValid(userId)) {
return AtsApiService.get().getUserService().getUserByUserId(userId);
}
return null;
}
public IAtsLogItem getStateCompletedData(IStateToken state) {
return getStateCompletedData(state.getName());
}
public IAtsLogItem getStateCompletedData(String stateName) {
return getLog().getStateEvent(LogType.StateComplete, stateName);
}
public IAtsLogItem getStateCancelledData(IStateToken state) {
return getStateCancelledData(state.getName());
}
public IAtsLogItem getStateCancelledData(String stateName) {
return getLog().getStateEvent(LogType.StateCancelled, stateName);
}
@Override
public String getCompletedFromState() {
String fromState = getSoleAttributeValue(AtsAttributeTypes.CompletedFromState, null);
if (!Strings.isValid(fromState)) {
return getLog().internalGetCompletedFromState();
}
return fromState;
}
public void setTransitionAssignees(Collection<AtsUser> assignees) {
if (assignees.contains(AtsCoreUsers.SYSTEM_USER) || assignees.contains(AtsCoreUsers.ANONYMOUS_USER)) {
throw new OseeArgumentException("Can not assign workflow to OseeSystem or Anonymous");
}
if (assignees.size() > 1 && assignees.contains(AtsCoreUsers.UNASSIGNED_USER)) {
throw new OseeArgumentException("Can not assign to user and UnAssigned");
}
transitionAssignees = assignees;
}
public boolean isAssigneeMe() {
return getStateMgr().getAssignees().contains(AtsApiService.get().getUserService().getCurrentUser());
}
/*
* getTransitionAssignees() is a method that is ONLY to be used in the WETransitionComposition class. Eventually this
* method needs to be incorporated into WETransitionComposition.
*/
public Collection<AtsUser> getTransitionAssignees() {
if (transitionAssignees != null) {
if (!transitionAssignees.isEmpty() && transitionAssignees.contains(AtsCoreUsers.UNASSIGNED_USER)) {
transitionAssignees.remove(AtsCoreUsers.UNASSIGNED_USER);
}
if (!transitionAssignees.isEmpty()) {
return transitionAssignees;
}
}
return getStateMgr().getAssignees();
}
public String getTransitionAssigneesStr() {
return AtsObjects.toString("; ", getTransitionAssignees());
}
@Override
public IAtsStateManager getStateMgr() {
return AtsApiService.get().getStateFactory().getStateManager(this);
}
public void clearImplementersCache() {
implementersStr = null;
}
@Override
public List<AtsUser> getAssignees() {
return getStateMgr().getAssignees();
}
@Override
public String getAtsId() {
String toReturn = getGuid();
try {
toReturn = getSoleAttributeValueAsString(AtsAttributeTypes.AtsId, toReturn);
} catch (OseeCoreException ex) {
OseeLog.log(Activator.class, Level.WARNING, ex);
}
return toReturn;
}
@Override
public void setStateMgr(IAtsStateManager stateMgr) {
Conditions.assertNotNull(stateMgr, "StateManager");
AtsApiService.get().getStateFactory().setStateMgr(this, stateMgr);
}
@Override
public Collection<WorkType> getWorkTypes() {
Set<WorkType> workTypes = new HashSet<>();
IAtsTeamWorkflow teamWf = getParentTeamWorkflow();
if (teamWf != null) {
for (IAtsActionableItem ai : AtsApiService.get().getActionableItemService().getActionableItems(
teamWf.getTeamDefinition())) {
Collection<String> workTypeStrs =
AtsApiService.get().getAttributeResolver().getAttributeValues(ai, AtsAttributeTypes.WorkType);
for (String workTypeStr : workTypeStrs) {
try {
WorkType workType = WorkType.valueOfOrNone(workTypeStr);
workTypes.add(workType);
} catch (Exception ex) {
// do nothing
}
}
}
}
return workTypes;
}
public void setWorkTypes(List<WorkType> workTypes) {
throw new UnsupportedOperationException();
}
@Override
public boolean isWorkType(WorkType workType) {
return getWorkTypes().contains(workType);
}
@Override
public void setTags(List<String> tags) {
throw new UnsupportedOperationException();
}
}