package org.openlca.app.editors.graphical.model;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.openlca.app.db.Cache;
import org.openlca.app.db.Database;
import org.openlca.app.editors.graphical.layout.LayoutManager;
import org.openlca.app.editors.graphical.layout.NodeLayoutInfo;
import org.openlca.app.editors.graphical.search.MutableProcessLinkSearchMap;
import org.openlca.core.database.ProcessDao;
import org.openlca.core.model.Exchange;
import org.openlca.core.model.FlowType;
import org.openlca.core.model.Location;
import org.openlca.core.model.Process;
import org.openlca.core.model.ProcessLink;
import org.openlca.core.model.descriptors.ProcessDescriptor;
import com.google.common.base.Objects;
public class ProcessNode extends Node {
public final ProcessDescriptor process;
public final List<Link> links = new ArrayList<>();
private Rectangle xyLayoutConstraints;
private boolean minimized = true;
private boolean marked = false;
public ProcessNode(ProcessDescriptor process) {
this.process = process;
}
@Override
public ProductSystemNode parent() {
return (ProductSystemNode) super.parent();
}
@SuppressWarnings("unchecked")
@Override
public List<IONode> getChildren() {
return (List<IONode>) super.getChildren();
}
void setFigure(IFigure figure) {
Dimension prefSize = figure.getPreferredSize(-1, -1);
if (xyLayoutConstraints == null)
xyLayoutConstraints = new Rectangle(0, 0, prefSize.width, prefSize.height);
this.figure = figure;
}
public void apply(NodeLayoutInfo layout) {
minimized = layout.isMinimized();
if (!minimized)
if (getChildren().isEmpty())
initializeExchangeNodes();
Dimension prefSize = figure.getPreferredSize(-1, -1);
xyLayoutConstraints = new Rectangle(layout.getLocation(), prefSize);
figure.setBounds(getXyLayoutConstraints());
figure().getLeftExpander().setExpanded(layout.isExpandedLeft());
figure().getRightExpander().setExpanded(layout.isExpandedRight());
figure().refresh();
}
public void add(Link link) {
if (links.contains(link))
return;
links.add(link);
if (equals(link.sourceNode))
editPart().refreshSourceConnections();
if (equals(link.targetNode))
editPart().refreshTargetConnections();
editPart.refresh();
}
ProcessPart editPart() {
return (ProcessPart) editPart;
}
public void remove(Link link) {
if (!links.contains(link))
return;
links.remove(link);
if (equals(link.sourceNode))
editPart().refreshSourceConnections();
if (equals(link.targetNode))
editPart().refreshTargetConnections();
editPart.refresh();
}
public Link getLink(ProcessLink link) {
for (Link l : links)
if (l.processLink.equals(link))
return l;
return null;
}
public void showLinks() {
for (Link link : links) {
ProcessNode otherNode = null;
boolean isSource = false;
if (link.sourceNode.equals(this)) {
otherNode = link.targetNode;
isSource = true;
} else if (link.targetNode.equals(this)) {
otherNode = link.sourceNode;
}
if (!otherNode.isVisible())
continue;
if (isSource && otherNode.isExpandedLeft())
link.setVisible(true);
else if (!isSource && otherNode.isExpandedRight())
link.setVisible(true);
}
}
@Override
public String getName() {
String text = process.getName();
if (process.getLocation() != null)
text += " [" + Cache.getEntityCache().get(Location.class, process.getLocation()).getCode() + "]";
return text;
}
public boolean isMinimized() {
return minimized;
}
public void minimize() {
this.minimized = true;
refresh();
}
public void maximize() {
this.minimized = false;
if (getChildren().isEmpty())
initializeExchangeNodes();
refresh();
}
public void mark() {
this.marked = true;
refresh();
}
public void unmark() {
this.marked = false;
refresh();
}
public boolean isMarked() {
return marked;
}
private void initializeExchangeNodes() {
Process process = new ProcessDao(Database.get()).getForId(this.process.getId());
List<Exchange> technologies = new ArrayList<>();
for (Exchange exchange : process.getExchanges())
if (exchange.getFlow().getFlowType() == FlowType.ELEMENTARY_FLOW)
continue;
else
technologies.add(exchange);
Exchange[] technologyArray = technologies.toArray(new Exchange[technologies.size()]);
add(new IONode(technologyArray));
}
public void refresh() {
Point location = figure().getLocation();
if (xyLayoutConstraints != null)
location = xyLayoutConstraints.getLocation();
xyLayoutConstraints = new Rectangle(location, figure.getPreferredSize());
figure().refresh();
}
public List<ExchangeNode> getInputs(long flowId) {
List<ExchangeNode> nodes = new ArrayList<>();
for (ExchangeNode node : getExchangeNodes())
if (!node.isDummy())
if (node.exchange.isInput())
if (node.exchange.getFlow().getId() == flowId)
nodes.add(node);
return nodes;
}
public ExchangeNode getOutput(long flowId) {
for (ExchangeNode node : getExchangeNodes())
if (!node.isDummy())
if (!node.exchange.isInput())
if (node.exchange.getFlow().getId() == flowId)
return node;
return null;
}
public ExchangeNode getNode(long exchangeId) {
for (ExchangeNode node : getExchangeNodes())
if (!node.isDummy())
if (node.exchange.getId() == exchangeId)
return node;
return null;
}
public ExchangeNode[] getExchangeNodes() {
List<ExchangeNode> exchangesNodes = new ArrayList<>();
for (IONode node : getChildren())
for (ExchangeNode node2 : node.getChildren())
exchangesNodes.add(node2);
ExchangeNode[] result = new ExchangeNode[exchangesNodes.size()];
exchangesNodes.toArray(result);
return result;
}
public ExchangeNode[] loadExchangeNodes() {
if (getChildren().isEmpty())
initializeExchangeNodes();
return getExchangeNodes();
}
public Rectangle getXyLayoutConstraints() {
return xyLayoutConstraints;
}
public void setXyLayoutConstraints(Rectangle xyLayoutConstraints) {
this.xyLayoutConstraints = xyLayoutConstraints;
editPart().revalidate();
}
public boolean hasIncoming(long exchangeId) {
MutableProcessLinkSearchMap linkSearch = parent().linkSearch;
for (ProcessLink link : linkSearch.getIncomingLinks(process.getId()))
if (link.exchangeId == exchangeId)
return true;
return false;
}
public int getMinimumHeight() {
if (isMinimized())
return ProcessFigure.MINIMUM_HEIGHT;
return figure().getMinimumHeight();
}
public int getMinimumWidth() {
return ProcessFigure.MINIMUM_WIDTH;
}
public boolean hasConnections() {
return links.size() > 0;
}
public int countOutgoing() {
int count = 0;
for (Link link : links)
if (link.sourceNode.equals(this))
count++;
return count;
}
public int countIncoming() {
int count = 0;
for (Link link : links)
if (link.targetNode.equals(this))
count++;
return count;
}
public void collapseLeft() {
if (!isExpandedLeft())
return;
figure().getLeftExpander().collapse(this);
}
public void collapseRight() {
if (!isExpandedRight())
return;
figure().getRightExpander().collapse(this);
}
/**
* Used to avoid removing the initial node while collapsing, should only be
* called from within ProcessExpander.collapse
*/
void collapseLeft(ProcessNode initialNode) {
if (!isExpandedLeft())
return;
figure().getLeftExpander().collapse(initialNode);
}
/**
* Used to avoid removing the initial node while collapsing, should only be
* called from within ProcessExpander.collapse
*/
void collapseRight(ProcessNode initialNode) {
if (!isExpandedRight())
return;
figure().getRightExpander().collapse(initialNode);
}
public void expandLeft() {
figure().getLeftExpander().expand();
}
public void expandRight() {
figure().getRightExpander().expand();
}
public boolean isExpandedLeft() {
return figure().getLeftExpander().isExpanded();
}
public boolean isExpandedRight() {
return figure().getRightExpander().isExpanded();
}
public void layout() {
LayoutManager layoutManager = (LayoutManager) parent().figure.getLayoutManager();
layoutManager.layout(figure, parent().editor.getLayoutType());
}
public void select() {
parent().editor.getGraphicalViewer().select(editPart);
}
public void reveal() {
parent().editor.getGraphicalViewer().reveal(editPart);
}
private ProcessFigure figure() {
return (ProcessFigure) figure;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ProcessNode))
return false;
ProcessNode other = (ProcessNode) obj;
return Objects.equal(process, other.process);
}
@Override
public int hashCode() {
return Objects.hashCode(process);
}
}