package org.openlca.app.editors.systems;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormEditor;
import org.eclipse.ui.forms.editor.FormPage;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.openlca.app.M;
import org.openlca.app.db.Cache;
import org.openlca.app.rcp.html.HtmlView;
import org.openlca.app.rcp.html.WebPage;
import org.openlca.app.util.Labels;
import org.openlca.app.util.UI;
import org.openlca.core.database.EntityCache;
import org.openlca.core.matrix.LongIndex;
import org.openlca.core.matrix.ProcessLinkSearchMap;
import org.openlca.core.model.ProcessLink;
import org.openlca.core.model.ProductSystem;
import org.openlca.core.model.descriptors.ProcessDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import gnu.trove.list.linked.TLongLinkedList;
import gnu.trove.set.hash.TLongHashSet;
import javafx.scene.web.WebEngine;
class HtmlGraph extends FormPage implements WebPage {
private Logger log = LoggerFactory.getLogger(getClass());
private ProductSystem productSystem;
public HtmlGraph(FormEditor editor, ProductSystem productSystem) {
super(editor, "system.HtmlGraph", M.HTMLGraph);
this.productSystem = productSystem;
}
@Override
public String getUrl() {
return HtmlView.GRAPH_VIEW.getUrl();
}
@Override
public void onLoaded(WebEngine webkit) {
try {
String graph = buildGraph().toJson();
String command = "setData(" + graph + ")";
webkit.executeScript(command);
} catch (Exception e) {
log.error("failed to set graph data", e);
}
}
@Override
protected void createFormContent(IManagedForm managedForm) {
ScrolledForm form = UI.formHeader(managedForm, "HTML Graph");
FormToolkit toolkit = managedForm.getToolkit();
Composite body = UI.formBody(form, toolkit);
body.setLayout(new FillLayout());
UI.createWebView(body, this);
form.reflow(true);
}
private Graph buildGraph() {
Graph graph = new Graph();
LongIndex nodeIndex = createNodes(graph);
ProcessLinkSearchMap map = new ProcessLinkSearchMap(
productSystem.getProcessLinks());
long startId = productSystem.getReferenceProcess().getId();
TLongLinkedList queue = new TLongLinkedList();
queue.add(startId);
TLongHashSet handled = new TLongHashSet();
while (!queue.isEmpty()) {
long recipient = queue.removeAt(0);
handled.add(recipient);
int recipId = nodeIndex.getIndex(recipient);
for (ProcessLink link : map.getIncomingLinks(recipient)) {
long provider = link.providerId;
if (handled.contains(provider) || queue.contains(provider))
continue;
queue.add(provider);
int provId = nodeIndex.getIndex(provider);
Link lnk = new Link();
lnk.source = provId;
lnk.target = recipId;
graph.links.add(lnk);
}
}
return graph;
}
private LongIndex createNodes(Graph graph) {
LongIndex idx = new LongIndex();
EntityCache cache = Cache.getEntityCache();
Map<Long, ProcessDescriptor> descriptors = cache.getAll(
ProcessDescriptor.class, productSystem.getProcesses());
for (Long processId : productSystem.getProcesses()) {
Node node = createNode(processId, descriptors);
graph.nodes.add(node);
idx.put(processId);
}
return idx;
}
private Node createNode(Long processId,
Map<Long, ProcessDescriptor> descriptors) {
Node node = new Node();
ProcessDescriptor descriptor = descriptors.get(processId);
if (descriptor != null) {
node.name = Labels.getDisplayName(descriptor);
Long group = descriptor.getCategory();
node.group = group == null ? 0 : group.intValue();
} else {
node.name = "unknown";
node.group = 0;
}
return node;
}
@SuppressWarnings("unused")
private class Node {
String name;
int group;
}
private class Link {
// fields are used in html/js
@SuppressWarnings("unused")
int source;
@SuppressWarnings("unused")
int target;
}
private class Graph {
List<Node> nodes = new ArrayList<>();
List<Link> links = new ArrayList<>();
String toJson() {
Gson gson = new Gson();
return gson.toJson(this);
}
}
}