package org.openlca.app.editors.graphical.action;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.commands.Command;
import org.eclipse.jface.viewers.ISelection;
import org.openlca.app.M;
import org.openlca.app.editors.graphical.model.Link;
import org.openlca.app.editors.graphical.model.ProcessNode;
import org.openlca.app.editors.graphical.model.ProductSystemNode;
import org.openlca.app.editors.graphical.search.MutableProcessLinkSearchMap;
import org.openlca.app.rcp.images.Icon;
import org.openlca.core.model.ProcessLink;
import org.openlca.core.model.ProductSystem;
class RemoveSupplyChainAction extends EditorAction {
private ProcessNode node;
private Set<Link> connections = new HashSet<>();
private Set<ProcessNode> nodes = new HashSet<>();
private Set<ProcessLink> links = new HashSet<>();
private Set<Long> processIds = new HashSet<>();
// only used in collectSupplyChain
private MutableProcessLinkSearchMap linkSearch;
RemoveSupplyChainAction() {
setId(ActionIds.REMOVE_SUPPLY_CHAIN);
setText(M.RemoveSupplyChain);
setImageDescriptor(Icon.REMOVE_SUPPLY_CHAIN.descriptor());
}
@Override
public void run() {
clear();
ProductSystem system = editor.getModel().getProductSystem();
long refId = system.getReferenceProcess().getId();
if (refId == node.process.getId()) {
for (ProcessNode node : editor.getModel().getChildren())
if (refId != node.process.getId()) {
nodes.add(node);
connections.addAll(node.links);
}
processIds.addAll(system.getProcesses());
processIds.remove(refId);
links.addAll(system.getProcessLinks());
} else {
linkSearch = new MutableProcessLinkSearchMap(
system.getProcessLinks());
collectSupplyChain(node.process.getId());
}
if (connections.size() > 0 || nodes.size() > 0 || links.size() > 0
|| processIds.size() > 0)
editor.getCommandStack().execute(new RemoveCommand());
}
private void clear() {
processIds.clear();
links.clear();
nodes.clear();
connections.clear();
}
private void collectSupplyChain(long processId) {
ProductSystemNode systemNode = editor.getModel();
ProcessNode node = systemNode.getProcessNode(processId);
List<ProcessLink> incomingLinks = linkSearch
.getIncomingLinks(processId);
for (ProcessLink link : incomingLinks) {
if (node != null) {
Link l = node.getLink(link);
if (l != null)
connections.add(l);
else
links.add(link);
} else {
links.add(link);
}
linkSearch.remove(link);
if (linkSearch.getOutgoingLinks(link.providerId).size() == 0) {
collectSupplyChain(link.providerId);
ProcessNode providerNode = editor.getModel().getProcessNode(link.providerId);
if (providerNode != null)
nodes.add(providerNode);
else
processIds.add(link.providerId);
}
}
}
@Override
protected boolean accept(ISelection selection) {
node = getSingleSelectionOfType(selection, ProcessNode.class);
return node != null;
}
private class RemoveCommand extends Command {
private Map<Long, Rectangle> layouts = new HashMap<>();
private Map<String, Boolean> visibility = new HashMap<>();
@Override
public boolean canExecute() {
return true;
}
@Override
public String getLabel() {
return M.RemoveSupplyChain;
}
@Override
public void execute() {
ProductSystemNode systemNode = node.parent();
ProductSystem system = systemNode.getProductSystem();
for (Link link : connections) {
visibility.put(getKey(link.processLink), link.isVisible());
link.unlink();
links.add(link.processLink);
}
system.getProcessLinks().removeAll(links);
systemNode.linkSearch.removeAll(links);
for (ProcessNode processNode : nodes) {
layouts.put(processNode.process.getId(), processNode.getXyLayoutConstraints());
systemNode.remove(processNode);
processIds.add(processNode.process.getId());
}
system.getProcesses().removeAll(processIds);
refresh();
}
@Override
public boolean canUndo() {
return true;
}
@Override
public void undo() {
ProductSystemNode systemNode = node.parent();
for (Long processId : processIds)
systemNode.getProductSystem().getProcesses().add(processId);
for (ProcessNode node : nodes) {
systemNode.add(node);
node.setXyLayoutConstraints(layouts.remove(node.process.getId()));
systemNode.getProductSystem().getProcesses().add(node.process.getId());
if (node.parent().editor.getOutline() == null)
continue;
node.parent().editor.getOutline().refresh();
}
for (ProcessLink link : links) {
systemNode.getProductSystem().getProcessLinks().add(link);
systemNode.linkSearch.put(link);
}
for (Link link : connections) {
systemNode.getProductSystem().getProcessLinks().add(link.processLink);
systemNode.linkSearch.put(link.processLink);
link.link();
link.setVisible(visibility.remove(getKey(link.processLink)));
}
refresh();
}
private void refresh() {
node.refresh();
editor.setDirty(true);
if (editor.getOutline() != null)
editor.getOutline().refresh();
}
@Override
public void redo() {
execute();
}
}
private String getKey(ProcessLink link) {
return link.providerId + "->" + link.flowId + "->" + link.processId + "->" + link.exchangeId;
}
}