overflowdb.Edge Maven / Gradle / Ivy
package overflowdb;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import overflowdb.util.IteratorUtils;
public abstract class Edge extends Element {
private final Graph graph;
private final String label;
private final NodeRef outNode;
private final NodeRef inNode;
/* When storing the inVertex in the outVertex' adjacent node array, there may be multiple edges
* with the same (direction, label), i.e. they are stored in the same block. To be able to
* identify this edge, we store it's offset into that block */
private int outBlockOffset = UNINITIALIZED_BLOCK_OFFSET;
/**
* When storing the outVertex in the inVertex' adjacent node array, there may be multiple edges
* with the same (direction, label), i.e. they are stored in the same block. To be able to
* identify this edge, we store it's offset into that block
*/
private int inBlockOffset = UNINITIALIZED_BLOCK_OFFSET;
private final Set specificKeys;
private boolean removed = false;
private static final int UNINITIALIZED_BLOCK_OFFSET = -1;
public Edge(Graph graph,
String label,
NodeRef outNode,
NodeRef inVertex,
Set specificKeys) {
this.graph = graph;
this.label = label;
this.outNode = outNode;
this.inNode = inVertex;
this.specificKeys = specificKeys;
graph.applyBackpressureMaybe();
}
public NodeRef outNode() {
return outNode;
}
public NodeRef inNode() {
return inNode;
}
public Iterator bothNodes() {
return IteratorUtils.from(outNode, inNode);
}
public int getOutBlockOffset() {
return outBlockOffset;
}
public void setOutBlockOffset(int offset) {
outBlockOffset = offset;
}
public int getInBlockOffset() {
return inBlockOffset;
}
public void setInBlockOffset(int offset) {
inBlockOffset = offset;
}
@Override
public String label() {
return label;
}
@Override
public Graph graph() {
return graph;
}
@Override
protected void setPropertyImpl(String key, Object value) {
// TODO check if it's an allowed property key
if (inBlockOffset != UNINITIALIZED_BLOCK_OFFSET) {
if (outBlockOffset == UNINITIALIZED_BLOCK_OFFSET) {
initializeOutFromInOffset();
}
} else if (outBlockOffset != UNINITIALIZED_BLOCK_OFFSET) {
if (inBlockOffset == UNINITIALIZED_BLOCK_OFFSET) {
initializeInFromOutOffset();
}
} else {
throw new RuntimeException("Cannot set property. In and out block offset uninitialized.");
}
inNode.get().setEdgeProperty(Direction.IN, label, key, value, inBlockOffset);
outNode.get().setEdgeProperty(Direction.OUT, label, key, value, outBlockOffset);
}
@Override
public Set propertyKeys() {
return specificKeys;
}
@Override
protected void removePropertyImpl(String key) {
inNode.get().removeEdgeProperty(Direction.IN, label, key, inBlockOffset);
outNode.get().removeEdgeProperty(Direction.OUT, label, key, outBlockOffset);
}
@Override
protected void removeImpl() {
fixupBlockOffsets();
outNode.get().removeEdge(Direction.OUT, label(), outBlockOffset);
inNode.get().removeEdge(Direction.IN, label(), inBlockOffset);
}
@Override
public Map propertiesMap() {
final Map properties;
if (inBlockOffset != -1) {
properties = inNode.get().edgePropertyMap(Direction.IN, this, getInBlockOffset());
} else if (outBlockOffset != -1) {
properties = outNode.get().edgePropertyMap(Direction.OUT, this, getOutBlockOffset());
} else {
throw new RuntimeException("Cannot get properties. In and out block offset uninitialized.");
}
for (String key : propertyKeys()) {
if (!properties.containsKey(key)) {
final Object defaultValue = propertyDefaultValue(key);
if (defaultValue != null) {
properties.put(key, propertyDefaultValue(key));
}
}
}
return properties;
}
public Object property(String propertyKey) {
final Object value;
if (inBlockOffset != -1) {
value = inNode.get().edgeProperty(Direction.IN, this, inBlockOffset, propertyKey);
} else if (outBlockOffset != -1) {
value = outNode.get().edgeProperty(Direction.OUT, this, outBlockOffset, propertyKey);
} else {
throw new RuntimeException("Cannot get property. In and out block offset unitialized.");
}
return value != null ? value : propertyDefaultValue(propertyKey);
}
@Override
public A property(PropertyKey key) {
return (A) property(key.name);
}
@Override
public Optional propertyOption(PropertyKey key) {
return Optional.ofNullable(property(key));
}
@Override
public Optional