/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.gui.communication.views;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import de.rcenvironment.core.communication.common.NetworkGraphNode;
import de.rcenvironment.core.communication.common.InstanceNodeSessionId;
import de.rcenvironment.core.gui.communication.views.internal.AnchorPoints;
import de.rcenvironment.core.gui.communication.views.model.NetworkGraphNodeWithContext;
import de.rcenvironment.core.gui.communication.views.model.NetworkGraphNodeWithContext.Context;
import de.rcenvironment.core.gui.communication.views.model.NetworkViewModel;
import de.rcenvironment.core.gui.communication.views.spi.ContributedNetworkViewNode;
import de.rcenvironment.core.gui.communication.views.spi.ContributedNetworkViewNodeWithParent;
import de.rcenvironment.core.gui.communication.views.spi.NetworkViewContributor;
import de.rcenvironment.core.gui.communication.views.spi.SelfRenderingNetworkViewNode;
import de.rcenvironment.core.monitoring.system.api.model.FullSystemAndProcessDataSnapshot;
/**
* The network view content provider.
*
* @author Robert Mischke
* @author David Scholz
*/
public class NetworkViewContentProvider implements IStructuredContentProvider, ITreeContentProvider {
/**
* The object representing the network root; added to avoid creating a class without an actual purpose.
*/
private static final String COLON = ": ";
private static final Object[] EMPTY_ARRAY = new Object[0];
private NetworkViewModel model;
private boolean optionRawPropertiesVisible = false;
private final List<NetworkViewContributor> rootContributors;
private final List<NetworkViewContributor> instanceDataContributors;
private final List<Object> firstLevelNodes = new ArrayList<>();
private Log log = LogFactory.getLog(getClass());
public NetworkViewContentProvider(List<NetworkViewContributor> rootContributors,
List<NetworkViewContributor> instanceDataContributors) {
this.rootContributors = rootContributors;
this.instanceDataContributors = instanceDataContributors;
}
@Override
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
if (newInput == null) {
// ignore empty input
return;
}
model = (NetworkViewModel) newInput;
}
@Override
public void dispose() {}
@Override
public Object[] getElements(Object parent) {
// keep top-level nodes in a set to recognize them in getParent()
firstLevelNodes.clear();
firstLevelNodes.add(AnchorPoints.MAIN_NETWORK_SECTION_PARENT_NODE);
firstLevelNodes.add(AnchorPoints.SSH_REMOTE_ACCESS_SECTION_PARENT_NODE);
return firstLevelNodes.toArray();
}
@Override
public Object[] getChildren(Object parentNode) {
if (parentNode == AnchorPoints.INSTANCES_PARENT_NODE) {
if (model.networkGraphWithProperties == null) {
return EMPTY_ARRAY;
}
Collection<? extends NetworkGraphNode> nodes = model.networkGraphWithProperties.getNodes();
int i = 0;
Object[] result = new Object[nodes.size()];
for (NetworkGraphNode node : nodes) {
NetworkGraphNodeWithContext nodeWithContext = new NetworkGraphNodeWithContext(node, Context.ROOT, null);
nodeWithContext.setAttachedNodeProperties(model.getNodeProperties().get(node.getNodeId()));
result[i++] = nodeWithContext;
}
Arrays.sort(result);
return result;
}
if (parentNode instanceof ContributedNetworkViewNode) {
if (parentNode instanceof SelfRenderingNetworkViewNode) {
SelfRenderingNetworkViewNode typedParentNode = (SelfRenderingNetworkViewNode) parentNode;
// TODO somewhat weird; rework? - misc_ro
if (!typedParentNode.getHasChildren()) {
return EMPTY_ARRAY;
} else {
return typedParentNode.getContributor().getChildren(typedParentNode);
}
} else {
ContributedNetworkViewNode typedParentNode = (ContributedNetworkViewNode) parentNode;
// if clause to separate old and new approach nodes; fall-through in "null" case for old approach
if (typedParentNode.getContributor() != null) {
return typedParentNode.getContributor().getChildren(typedParentNode);
}
}
}
if (parentNode == AnchorPoints.MAIN_NETWORK_SECTION_PARENT_NODE
|| parentNode == AnchorPoints.SSH_REMOTE_ACCESS_SECTION_PARENT_NODE) {
List<Object> result = new ArrayList<>();
if (parentNode == AnchorPoints.MAIN_NETWORK_SECTION_PARENT_NODE) {
// old code - hard-coded element
result.add(AnchorPoints.INSTANCES_PARENT_NODE);
}
// new code - contributors
for (NetworkViewContributor contributor : rootContributors) {
Object[] contributedNodes = contributor.getTopLevelElements(parentNode);
if (contributedNodes != null) {
for (Object element : contributedNodes) {
result.add(element);
}
}
}
return result.toArray();
}
NetworkGraphNodeWithContext typedParentNode = (NetworkGraphNodeWithContext) parentNode;
// switch by parent node context
Object[] result;
switch (typedParentNode.getContext()) {
case ROOT:
List<Object> contribList = new ArrayList<>();
// new approach
for (NetworkViewContributor contributor : instanceDataContributors) {
for (Object contrib : contributor.getChildrenForNetworkInstanceNode(typedParentNode)) {
contribList.add(contrib);
}
}
// old approach
if (optionRawPropertiesVisible) {
contribList.add(new NetworkGraphNodeWithContext(typedParentNode, Context.RAW_NODE_PROPERTIES_FOLDER, null));
}
// trim to actual length
result = contribList.toArray();
break;
case RESOURCE_MONITORING_FOLDER:
FullSystemAndProcessDataSnapshot monitoringDataModel =
model.getMonitoringDataModelMap().get(typedParentNode.getNode().getNodeId());
if (monitoringDataModel != null) {
result =
createNodeSystemResources(monitoringDataModel, typedParentNode
.getNode().getNodeId());
} else {
result = new Object[1];
result[0] = "Fetching monitoring data...";
}
break;
case RAW_NODE_PROPERTIES_FOLDER:
List<NetworkGraphNodeWithContext> children = new ArrayList<NetworkGraphNodeWithContext>();
Map<String, String> propertyValueMap = typedParentNode.getAttachedNodeProperties();
if (propertyValueMap != null) {
for (Entry<String, String> property : propertyValueMap.entrySet()) {
NetworkGraphNodeWithContext newChild =
new NetworkGraphNodeWithContext(typedParentNode, Context.RAW_NODE_PROPERTY, null);
newChild.setDisplayText(property.getKey() + COLON + property.getValue());
children.add(newChild);
}
} else {
// add placeholder
NetworkGraphNodeWithContext newChild = new NetworkGraphNodeWithContext(typedParentNode, Context.RAW_NODE_PROPERTY, null);
newChild.setDisplayText("<unknown>");
children.add(newChild);
}
result = children.toArray(EMPTY_ARRAY);
Arrays.sort(result);
break;
default:
result = EMPTY_ARRAY;
}
return result;
}
private Object[] createNodeSystemResources(FullSystemAndProcessDataSnapshot monitoringDataModel, InstanceNodeSessionId nodeId) {
return null;
}
@Override
public boolean hasChildren(Object parent) {
if (parent instanceof SelfRenderingNetworkViewNode) {
SelfRenderingNetworkViewNode typedParentNode = (SelfRenderingNetworkViewNode) parent;
return typedParentNode.getHasChildren();
} else if (parent instanceof ContributedNetworkViewNode && ((ContributedNetworkViewNode) parent).getContributor() != null) {
// TODO second "if" clause can be removed after full transition
return ((ContributedNetworkViewNode) parent).getContributor().hasChildren(parent);
} else if (parent instanceof NetworkGraphNodeWithContext) {
NetworkGraphNodeWithContext typedParentNode = (NetworkGraphNodeWithContext) parent;
if (typedParentNode.getContributor() != null) {
// new approach
return typedParentNode.getContributor().hasChildren(parent);
}
switch (typedParentNode.getContext()) {
case ROOT:
// always true now, as each instance's folder contains at least the monitoring data folder
return true;
case RAW_NODE_PROPERTIES_FOLDER:
case RESOURCE_MONITORING_FOLDER:
return true; // always has entries or a placeholder
case RAW_NODE_PROPERTY:
return false;
default:
return true;
}
} else if (firstLevelNodes.contains(parent) || parent == AnchorPoints.INSTANCES_PARENT_NODE) {
return true;
}
return false;
}
@Override
public Object getParent(Object node) {
if (node instanceof NetworkGraphNodeWithContext) {
final NetworkGraphNodeWithContext typedNode = (NetworkGraphNodeWithContext) node;
final NetworkGraphNodeWithContext parent = typedNode.getParent();
if (parent != null) {
return parent;
} else {
return AnchorPoints.INSTANCES_PARENT_NODE;
}
}
if (node instanceof ContributedNetworkViewNodeWithParent) {
return ((ContributedNetworkViewNodeWithParent) node).getParentNode();
}
if (node instanceof ContributedNetworkViewNode) {
final ContributedNetworkViewNode typedNode = (ContributedNetworkViewNode) node;
final NetworkViewContributor contributor = typedNode.getContributor();
if (contributor == null) {
log.warn("getParent() called on contributed node without a contributor: " + node.toString());
return null;
}
Object parent = contributor.getParent(typedNode);
if (parent == null) {
log.warn("Contributor returned a null parent for " + node.toString());
} else if (parent == AnchorPoints.SYMBOLIC_ROOT_NODE) {
return model; // the actual root node
} else {
return parent;
}
}
if (firstLevelNodes.contains(node)) {
return model;
}
log.warn("getParent() fall-through; returning null for node " + node.toString());
return null;
}
public void setRawPropertiesVisible(boolean value) {
this.optionRawPropertiesVisible = value;
}
}