blob: 9b80a0141a5c84ce50759a5130f8fca213283cc5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 20013 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.operation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.osee.ats.AtsImage;
import org.eclipse.osee.ats.actions.DuplicateWorkflowAction;
import org.eclipse.osee.ats.api.ai.IAtsActionableItem;
import org.eclipse.osee.ats.api.team.CreateTeamData;
import org.eclipse.osee.ats.api.user.IAtsUser;
import org.eclipse.osee.ats.api.workflow.IAtsTeamWorkflow;
import org.eclipse.osee.ats.core.ai.ModifyActionableItems;
import org.eclipse.osee.ats.core.client.action.ActionManager;
import org.eclipse.osee.ats.core.client.team.TeamWorkFlowArtifact;
import org.eclipse.osee.ats.core.client.util.AtsChangeSet;
import org.eclipse.osee.ats.core.config.ActionableItems;
import org.eclipse.osee.ats.core.config.TeamDefinitionUtility;
import org.eclipse.osee.ats.internal.Activator;
import org.eclipse.osee.ats.internal.AtsClientService;
import org.eclipse.osee.ats.util.AtsObjectLabelProvider;
import org.eclipse.osee.ats.util.AtsUtil;
import org.eclipse.osee.ats.util.widgets.dialog.AITreeContentProvider;
import org.eclipse.osee.ats.util.widgets.dialog.AtsObjectNameSorter;
import org.eclipse.osee.framework.core.enums.Active;
import org.eclipse.osee.framework.core.operation.AbstractOperation;
import org.eclipse.osee.framework.core.operation.OperationLogger;
import org.eclipse.osee.framework.core.operation.Operations;
import org.eclipse.osee.framework.core.util.XResultData;
import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
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.ui.plugin.util.AWorkbench;
import org.eclipse.osee.framework.ui.plugin.util.ArrayTreeContentProvider;
import org.eclipse.osee.framework.ui.skynet.FrameworkImage;
import org.eclipse.osee.framework.ui.skynet.blam.AbstractBlam;
import org.eclipse.osee.framework.ui.skynet.blam.VariableMap;
import org.eclipse.osee.framework.ui.skynet.results.XResultDataUI;
import org.eclipse.osee.framework.ui.skynet.widgets.XListDropViewer;
import org.eclipse.osee.framework.ui.skynet.widgets.XModifiedListener;
import org.eclipse.osee.framework.ui.skynet.widgets.XText;
import org.eclipse.osee.framework.ui.skynet.widgets.XWidget;
import org.eclipse.osee.framework.ui.skynet.widgets.dialog.FilteredCheckboxTree;
import org.eclipse.osee.framework.ui.skynet.widgets.util.SwtXWidgetRenderer;
import org.eclipse.osee.framework.ui.swt.Displays;
import org.eclipse.osee.framework.ui.swt.ImageManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.forms.widgets.FormToolkit;
/**
* @author Donald G. Dunne
*/
public class ModifyActionableItemsBlam extends AbstractBlam {
private final static String TEAM_WORKFLOW = "Team Workflow (drop here)";
private TeamWorkFlowArtifact defaultTeamWorkflow;
private FilteredCheckboxTree wfTree;
private FilteredCheckboxTree otherTree;
private FilteredCheckboxTree newTree;
private XListDropViewer dropViewer;
private XText resultsText;
private Set<IAtsActionableItem> currAIsForAllWfs;
private List<IAtsActionableItem> currWorkflowDesiredAIs;
private List<IAtsActionableItem> newAIs;
public ModifyActionableItemsBlam() {
// do nothing
}
@Override
public void widgetCreated(XWidget xWidget, FormToolkit toolkit, Artifact art, SwtXWidgetRenderer dynamicXWidgetLayout, XModifiedListener modListener, boolean isEditable) throws OseeCoreException {
super.widgetCreated(xWidget, toolkit, art, dynamicXWidgetLayout, modListener, isEditable);
if (xWidget.getLabel().equals(TEAM_WORKFLOW)) {
createTreeViewers(xWidget.getControl().getParent());
dropViewer = (XListDropViewer) xWidget;
dropViewer.addXModifiedListener(new DropListener());
Control control = dropViewer.getControl();
GridData data = new GridData(SWT.FILL, SWT.NONE, true, false);
data.heightHint = 20;
control.setLayoutData(data);
if (xWidget.getLabel().equals(TEAM_WORKFLOW) && defaultTeamWorkflow != null) {
dropViewer.setInput(defaultTeamWorkflow);
}
}
}
private void createTreeViewers(Composite parent) {
Composite treeComp = new Composite(parent, SWT.BORDER);
treeComp.setLayout(new GridLayout(3, true));
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.heightHint = 300;
treeComp.setLayoutData(data);
Label wfLabel = new Label(treeComp, SWT.BOLD | SWT.CENTER);
wfLabel.setText("This Workflow's Actionable Items\n(select to add to this workflow)");
Label otherLabel = new Label(treeComp, SWT.BOLD | SWT.CENTER);
otherLabel.setText("Actionable Items in other Team Workflows\n(readonly)");
Label newLabel = new Label(treeComp, SWT.BOLD | SWT.CENTER);
newLabel.setText("New Workflows\n(select to create new workflows)");
wfTree = new FilteredCheckboxTree(treeComp, SWT.CHECK | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
wfTree.getViewer().setContentProvider(new WorkflowsActiveAisContentProvider(defaultTeamWorkflow, Active.Active));
wfTree.getViewer().setLabelProvider(new AtsObjectLabelProvider());
wfTree.getViewer().setSorter(new AtsObjectNameSorter());
wfTree.setLayoutData(data);
wfTree.getViewer().addPostSelectionChangedListener(new ModificationListener());
otherTree = new FilteredCheckboxTree(treeComp, SWT.READ_ONLY | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
otherTree.getViewer().setContentProvider(new ArrayTreeContentProvider());
otherTree.getViewer().setLabelProvider(new AtsObjectLabelProvider());
otherTree.getViewer().setSorter(new AtsObjectNameSorter());
otherTree.setLayoutData(data);
otherTree.setEnabled(false);
newTree = new FilteredCheckboxTree(treeComp, SWT.CHECK | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
newTree.getViewer().setContentProvider(new AITreeContentProvider(Active.Active));
newTree.getViewer().setLabelProvider(new AtsObjectLabelProvider());
newTree.getViewer().setSorter(new AtsObjectNameSorter());
newTree.setLayoutData(data);
newTree.getViewer().addPostSelectionChangedListener(new ModificationListener());
resultsText = new XText("Results if run");
resultsText.setVerticalLabel(true);
GridData data2 = new GridData(SWT.FILL, SWT.NONE, true, false);
data2.heightHint = 100;
resultsText.setFillHorizontally(true);
resultsText.setFillVertically(true);
resultsText.createWidgets(parent, 1);
resultsText.getStyledText().setLayoutData(data2);
Composite buttonComp = new Composite(parent, SWT.NONE);
buttonComp.setLayout(new GridLayout(2, true));
buttonComp.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
Button executeButton = new Button(buttonComp, SWT.PUSH | SWT.LEFT);
executeButton.setText("Run");
executeButton.setImage(ImageManager.getImage(FrameworkImage.RUN_EXC));
executeButton.setLayoutData(new GridData(SWT.NONE, SWT.NONE, true, false));
executeButton.addListener(SWT.MouseUp, new Listener() {
@Override
public void handleEvent(Event event) {
runOperation(null, null);
}
});
Button advancedDuplicate = new Button(buttonComp, SWT.PUSH | SWT.RIGHT);
advancedDuplicate.setText("Open Advanced Duplicate Workflow");
advancedDuplicate.setImage(ImageManager.getImage(FrameworkImage.DUPLICATE));
advancedDuplicate.setLayoutData(new GridData(SWT.NONE, SWT.NONE, true, false));
advancedDuplicate.addListener(SWT.MouseUp, new Listener() {
@Override
public void handleEvent(Event event) {
TeamWorkFlowArtifact teamWf = getDroppedTeamWf();
List<TeamWorkFlowArtifact> teams = new ArrayList<TeamWorkFlowArtifact>();
if (teamWf != null) {
teams.add(teamWf);
}
new DuplicateWorkflowAction(teams).run();
}
});
if (defaultTeamWorkflow != null) {
refreshTables(defaultTeamWorkflow);
}
}
private class ModificationListener implements ISelectionChangedListener {
@Override
public void selectionChanged(SelectionChangedEvent event) {
refreshResultsArea(getDroppedTeamWf());
}
}
private class DropListener implements XModifiedListener {
@Override
public void widgetModified(XWidget widget) {
refreshTables(getDroppedTeamWf());
}
}
private void refreshTables(final TeamWorkFlowArtifact teamWf) {
Displays.ensureInDisplayThread(new Runnable() {
@Override
public void run() {
if (teamWf == null) {
clearTables();
} else {
try {
wfTree.getViewer().setInput(teamWf);
Set<IAtsActionableItem> actionableItems = teamWf.getActionableItems();
wfTree.setInitalChecked(Arrays.asList(actionableItems.toArray()));
Set<IAtsActionableItem> ais = new HashSet<IAtsActionableItem>();
for (TeamWorkFlowArtifact team : teamWf.getParentActionArtifact().getTeams()) {
if (!team.equals(teamWf)) {
ais.addAll(team.getActionableItems());
}
}
otherTree.getViewer().setInput(ais);
newTree.getViewer().setInput(
ActionableItems.getTopLevelActionableItems(Active.Active, AtsClientService.get().getConfig()));
} catch (OseeCoreException ex) {
OseeLog.log(Activator.class, OseeLevel.SEVERE_POPUP, ex);
}
}
refreshResultsArea(teamWf);
}
});
}
private void clearTables() {
List<Object> emptyList = Collections.emptyList();
wfTree.getViewer().setInput(emptyList);
wfTree.clearChecked();
otherTree.getViewer().setInput(emptyList);
newTree.getViewer().setInput(emptyList);
newTree.clearChecked();
}
private void refreshResultsArea(TeamWorkFlowArtifact teamWf) {
XResultData results = new XResultData(false);
performModification(teamWf, results, true);
resultsText.setText(results.toString());
}
private TeamWorkFlowArtifact getDroppedTeamWf() {
TeamWorkFlowArtifact teamWf = null;
List<Artifact> artifacts = dropViewer.getArtifacts();
if (artifacts.size() == 1) {
teamWf = (TeamWorkFlowArtifact) artifacts.iterator().next();
}
return teamWf;
}
private void performModification(TeamWorkFlowArtifact teamWf, XResultData results, boolean logOnly) {
if (teamWf == null) {
AWorkbench.popup("Must drop a Team Workflow to modify");
return;
}
try {
currAIsForAllWfs = new HashSet<IAtsActionableItem>();
for (TeamWorkFlowArtifact team : teamWf.getParentActionArtifact().getTeams()) {
currAIsForAllWfs.addAll(team.getActionableItems());
}
currWorkflowDesiredAIs = org.eclipse.osee.framework.jdk.core.util.Collections.castAll(wfTree.getChecked());
newAIs = org.eclipse.osee.framework.jdk.core.util.Collections.castAll(newTree.getChecked());
IAtsUser modifiedBy = AtsClientService.get().getUserService().getCurrentUser();
ModifyActionableItems job =
new ModifyActionableItems(results, teamWf, currAIsForAllWfs, currWorkflowDesiredAIs, newAIs, modifiedBy,
new TeamDefinitionUtility());
job.performModification();
if (!logOnly) {
if (results.isErrors()) {
AWorkbench.popup("Must resolve all errors before running");
return;
}
ModifyActionableItemOperation op = new ModifyActionableItemOperation(teamWf, results, job);
Operations.executeAsJob(op, false, Job.SHORT, new ModifyActionableItemListener(op));
}
} catch (OseeCoreException ex) {
OseeLog.log(Activator.class, OseeLevel.SEVERE_POPUP, ex);
}
}
public class ModifyActionableItemListener extends JobChangeAdapter {
private final ModifyActionableItemOperation op;
public ModifyActionableItemListener(ModifyActionableItemOperation op) {
this.op = op;
}
@Override
public void done(IJobChangeEvent event) {
super.done(event);
List<TeamWorkFlowArtifact> newTeamWfs = op.getNewTeamWfs();
refreshTables(op.getTeamWf());
if (!newTeamWfs.isEmpty()) {
AtsUtil.openInAtsWorldEditor("New Team Workflows", newTeamWfs);
}
}
}
public class ModifyActionableItemOperation extends AbstractOperation {
private final ModifyActionableItems job;
List<TeamWorkFlowArtifact> newTeamWfs = new ArrayList<TeamWorkFlowArtifact>();
private final TeamWorkFlowArtifact teamWf;
public TeamWorkFlowArtifact getTeamWf() {
return teamWf;
}
private final XResultData results;
public ModifyActionableItemOperation(TeamWorkFlowArtifact teamWf, XResultData results, ModifyActionableItems job) {
super("Modify Actionable Items", Activator.PLUGIN_ID);
this.teamWf = teamWf;
this.results = results;
this.job = job;
}
@Override
protected void doWork(IProgressMonitor monitor) throws Exception {
AtsChangeSet changes = new AtsChangeSet(getName());
Date createdDate = new Date();
for (CreateTeamData data : job.getTeamDatas()) {
TeamWorkFlowArtifact teamArt =
ActionManager.createTeamWorkflow(teamWf.getParentActionArtifact(), data.getTeamDef(),
data.getActionableItems(), new LinkedList<IAtsUser>(data.getAssignees()), changes, createdDate,
data.getCreatedBy(), null, data.getCreateTeamOption());
newTeamWfs.add(teamArt);
}
for (IAtsActionableItem checkedAi : job.getAddAis()) {
results.logWithFormat("Actionable Item [%s] will be added to this workflow\n", checkedAi);
teamWf.getActionableItemsDam().addActionableItem(checkedAi);
changes.add(teamWf);
}
for (IAtsActionableItem currAi : job.getRemoveAis()) {
results.logWithFormat("Actionable Item [%s] will be removed from this workflow\n", currAi);
teamWf.getActionableItemsDam().removeActionableItem(currAi);
changes.add(teamWf);
}
if (!changes.isEmpty()) {
changes.execute();
}
}
public List<TeamWorkFlowArtifact> getNewTeamWfs() {
return newTeamWfs;
}
}
@Override
public void runOperation(final VariableMap variableMap, IProgressMonitor monitor) {
Displays.ensureInDisplayThread(new Runnable() {
@Override
public void run() {
try {
List<Artifact> artifacts = dropViewer.getArtifacts();
if (artifacts.isEmpty()) {
AWorkbench.popup("ERROR", "Must drag in a Team Workflow to duplicate.");
return;
} else if (artifacts.size() != 1 || !(artifacts.iterator().next() instanceof IAtsTeamWorkflow)) {
AWorkbench.popup("ERROR", "Only one Team Workflow can be processed at a time");
}
XResultData data = new XResultData(false);
TeamWorkFlowArtifact teamWf = (TeamWorkFlowArtifact) artifacts.iterator().next();
performModification(teamWf, data, false);
if (data.isErrors()) {
XResultDataUI.report(data, getName());
}
clearTables();
refreshTables(teamWf);
} catch (Exception ex) {
OseeLog.log(Activator.class, OseeLevel.SEVERE_POPUP, ex);
}
};
});
}
@Override
public boolean showExecuteSection() {
return false;
}
@Override
public String getXWidgetsXml() {
return "<xWidgets>"
//
+ "<XWidget xwidgetType=\"XListDropViewer\" displayName=\"" + TEAM_WORKFLOW + "\" />" +
//
"</xWidgets>";
}
@Override
public String getDescriptionUsage() {
return "Add, remove or modify actionable items impacted in this Action.";
}
public void setDefaultTeamWorkflow(TeamWorkFlowArtifact team) {
this.defaultTeamWorkflow = team;
}
@Override
public String getName() {
return "Modify Actionable Items";
}
@Override
public Collection<String> getCategories() {
return Arrays.asList("ATS");
}
@Override
public void execute(OperationLogger logger, VariableMap variableMap, IJobChangeListener jobChangeListener) {
runOperation(null, null);
}
@Override
public String getTabTitle() {
return getName();
}
@Override
public String getTitle() {
return getName();
}
@Override
public Image getImage() {
return ImageManager.getImage(AtsImage.ACTIONABLE_ITEM);
}
@Override
public ImageDescriptor getImageDescriptor() {
return ImageManager.getImageDescriptor(AtsImage.ACTIONABLE_ITEM);
}
public int getWorkflowTreeItemCount() {
return wfTree.getViewer().getTree().getItemCount();
}
public int getOtherTreeItemCount() {
return otherTree.getViewer().getTree().getItemCount();
}
public int getNewTreeItemCount() {
return newTree.getViewer().getTree().getItemCount();
}
}