blob: 853c02882454278572a384ba71cb5604e98eda0d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Aston University.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License, v. 2.0 are satisfied: GNU General Public License, version 3.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-3.0
*
* Contributors:
* Antonio Garcia-Dominguez - initial API and implementation
******************************************************************************/
package org.eclipse.hawk.greycat;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import org.eclipse.hawk.core.graph.IGraphEdge;
import org.eclipse.hawk.greycat.GreycatNode.NodeReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import greycat.Node;
import greycat.Type;
/**
* "Heavy" edge that can have its own properties. Emulated in Greycat
* through documents, like in Orient.
*/
public class GreycatHeavyEdge implements IGraphEdge {
public static GreycatHeavyEdge create(String type, GreycatNode from, GreycatNode to, Map<String, Object> props) {
try (NodeReader rStart = from.getNodeReader(); NodeReader rEnd = to.getNodeReader()) {
final GreycatNode gHeavyEdgeNode = from.getGraph().createNode(props, NODETYPE);
try (GreycatNode.NodeReader rEdge = gHeavyEdgeNode.getNodeReader()) {
final Node heavyEdgeNode = rEdge.get();
heavyEdgeNode.set(GreycatHeavyEdge.TYPE_PROP, Type.STRING, type);
heavyEdgeNode.addToRelation(GreycatHeavyEdge.START_REL, rStart.get());
heavyEdgeNode.addToRelation(GreycatHeavyEdge.END_REL, rEnd.get());
GreycatNode.addOutgoing(type, rStart, rEdge);
GreycatNode.addIncoming(type, rEnd, rEdge);
rEdge.markDirty();
}
return new GreycatHeavyEdge(gHeavyEdgeNode, type);
}
}
private static final Logger LOGGER = LoggerFactory.getLogger(GreycatHeavyEdge.class);
protected static final String NODETYPE = "h_heavyEdge";
protected static final String END_REL = "h_end";
protected static final String START_REL = "h_start";
protected static final String TYPE_PROP = "h_type";
private final GreycatNode node;
/**
* The type is already known from the in/out edge of the target/source node, but
* we keep it in the intermediate node as well in case the user takes advantage
* of a node visualizer.
*/
private final String type;
public GreycatHeavyEdge(GreycatNode node, String type) {
this.node = node;
this.type = type;
}
@Override
public Object getId() {
return node.getId();
}
@Override
public String getType() {
return type;
}
@Override
public Set<String> getPropertyKeys() {
return node.getPropertyKeys();
}
@Override
public Object getProperty(String name) {
return node.getProperty(name);
}
@Override
public void setProperty(String name, Object value) {
node.setProperty(name, value);
}
@Override
public GreycatNode getStartNode() {
return getRawTarget(START_REL);
}
@Override
public GreycatNode getEndNode() {
return getRawTarget(END_REL);
}
public GreycatNode getBackingNode() {
return node;
}
@Override
public void delete() {
final GreycatNode startNode = getStartNode();
final GreycatNode endNode = getEndNode();
try (
NodeReader rEdge = node.getNodeReader();
NodeReader rStart = startNode.getNodeReader();
NodeReader rEnd = endNode.getNodeReader()
) {
final String type = getType();
GreycatNode.removeOutgoing(type, rStart, rEdge);
GreycatNode.removeIncoming(type, rEnd, rEdge);
final Node edgeNode = rEdge.get();
if (edgeNode.timeDephasing() > 0 || node.getAllVersions().size() > 1) {
/* There is more than one instant for this edge: end it in the previous timepoint. */
node.travelInTime(node.getTime() - 1).end();
} else {
/* There is exactly one version and we are right in its timepoint - just delete the backing node altogether. */
node.delete();
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
@Override
public void removeProperty(String name) {
node.removeProperty(name);
}
protected GreycatNode getRawTarget(final String relationName) {
try (NodeReader reader = node.getNodeReader()) {
CompletableFuture<GreycatNode> result = new CompletableFuture<>();
reader.get().traverse(relationName, (Node[] targets) -> {
final Node target = targets[0];
final GreycatNode newNode = node.getGraph().lookup(
target.world(), target.time(), target.id());
for (Node t : targets) {
t.free();
}
result.complete(newNode);
});
return result.get();
} catch (InterruptedException | ExecutionException e) {
LOGGER.error(e.getMessage(), e);
return null;
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((node == null) ? 0 : node.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
GreycatHeavyEdge other = (GreycatHeavyEdge) obj;
if (node == null) {
if (other.node != null)
return false;
} else if (!node.equals(other.node))
return false;
return true;
}
@Override
public String toString() {
return "GreycatHeavyEdge [node=" + node + ", getStartNode()=" + getStartNode() + ", getEndNode()="
+ getEndNode() + "]";
}
}