Changeset View
Changeset View
Standalone View
Standalone View
java/src/main/java/org/softwareheritage/graph/rpc/Traversal.java
Show First 20 Lines • Show All 232 Lines • ▼ Show 20 Lines | public class Traversal { | ||||
* processing, notably related to graph properties and filters. | * processing, notably related to graph properties and filters. | ||||
*/ | */ | ||||
static class SimpleTraversal extends BFSVisitor { | static class SimpleTraversal extends BFSVisitor { | ||||
private final NodeFilterChecker nodeReturnChecker; | private final NodeFilterChecker nodeReturnChecker; | ||||
private final AllowedEdges allowedEdges; | private final AllowedEdges allowedEdges; | ||||
private final TraversalRequest request; | private final TraversalRequest request; | ||||
private final NodePropertyBuilder.NodeDataMask nodeDataMask; | private final NodePropertyBuilder.NodeDataMask nodeDataMask; | ||||
private final NodeObserver nodeObserver; | private final NodeObserver nodeObserver; | ||||
private long remainingMatches; | |||||
private Node.Builder nodeBuilder; | private Node.Builder nodeBuilder; | ||||
SimpleTraversal(SwhBidirectionalGraph bidirectionalGraph, TraversalRequest request, NodeObserver nodeObserver) { | SimpleTraversal(SwhBidirectionalGraph bidirectionalGraph, TraversalRequest request, NodeObserver nodeObserver) { | ||||
super(getDirectedGraph(bidirectionalGraph, request.getDirection())); | super(getDirectedGraph(bidirectionalGraph, request.getDirection())); | ||||
this.request = request; | this.request = request; | ||||
this.nodeObserver = nodeObserver; | this.nodeObserver = nodeObserver; | ||||
this.nodeReturnChecker = new NodeFilterChecker(g, request.getReturnNodes()); | this.nodeReturnChecker = new NodeFilterChecker(g, request.getReturnNodes()); | ||||
this.nodeDataMask = new NodePropertyBuilder.NodeDataMask(request.hasMask() ? request.getMask() : null); | this.nodeDataMask = new NodePropertyBuilder.NodeDataMask(request.hasMask() ? request.getMask() : null); | ||||
this.allowedEdges = new AllowedEdges(request.hasEdges() ? request.getEdges() : "*"); | this.allowedEdges = new AllowedEdges(request.hasEdges() ? request.getEdges() : "*"); | ||||
request.getSrcList().forEach(srcSwhid -> { | request.getSrcList().forEach(srcSwhid -> { | ||||
long srcNodeId = g.getNodeId(new SWHID(srcSwhid)); | long srcNodeId = g.getNodeId(new SWHID(srcSwhid)); | ||||
addSource(srcNodeId); | addSource(srcNodeId); | ||||
}); | }); | ||||
if (request.hasMaxDepth()) { | if (request.hasMaxDepth()) { | ||||
setMaxDepth(request.getMaxDepth()); | setMaxDepth(request.getMaxDepth()); | ||||
} | } | ||||
if (request.hasMaxEdges()) { | if (request.hasMaxEdges()) { | ||||
setMaxEdges(request.getMaxEdges()); | setMaxEdges(request.getMaxEdges()); | ||||
} | } | ||||
if (request.hasMaxMatchingNodes() && request.getMaxMatchingNodes() > 0) { | |||||
this.remainingMatches = request.getMaxMatchingNodes(); | |||||
} else { | |||||
this.remainingMatches = -1; | |||||
} | |||||
} | } | ||||
@Override | @Override | ||||
protected ArcLabelledNodeIterator.LabelledArcIterator getSuccessors(long nodeId) { | protected ArcLabelledNodeIterator.LabelledArcIterator getSuccessors(long nodeId) { | ||||
return filterLabelledSuccessors(g, nodeId, allowedEdges); | return filterLabelledSuccessors(g, nodeId, allowedEdges); | ||||
} | } | ||||
@Override | @Override | ||||
public void visitNode(long node) { | public void visitNode(long node) { | ||||
nodeBuilder = null; | nodeBuilder = null; | ||||
if (nodeReturnChecker.allowed(node) && (!request.hasMinDepth() || depth >= request.getMinDepth())) { | if (nodeReturnChecker.allowed(node) && (!request.hasMinDepth() || depth >= request.getMinDepth())) { | ||||
nodeBuilder = Node.newBuilder(); | nodeBuilder = Node.newBuilder(); | ||||
NodePropertyBuilder.buildNodeProperties(g, nodeDataMask, nodeBuilder, node); | NodePropertyBuilder.buildNodeProperties(g, nodeDataMask, nodeBuilder, node); | ||||
} | } | ||||
super.visitNode(node); | super.visitNode(node); | ||||
if (request.getReturnNodes().hasMinTraversalSuccessors() | |||||
&& traversalSuccessors < request.getReturnNodes().getMinTraversalSuccessors() | boolean nodeMatchesConstraints = true; | ||||
|| request.getReturnNodes().hasMaxTraversalSuccessors() | |||||
&& traversalSuccessors > request.getReturnNodes().getMaxTraversalSuccessors()) { | if (request.getReturnNodes().hasMinTraversalSuccessors()) { | ||||
nodeBuilder = null; | nodeMatchesConstraints &= traversalSuccessors >= request.getReturnNodes().getMinTraversalSuccessors(); | ||||
} | |||||
if (request.getReturnNodes().hasMaxTraversalSuccessors()) { | |||||
nodeMatchesConstraints &= traversalSuccessors <= request.getReturnNodes().getMaxTraversalSuccessors(); | |||||
} | } | ||||
if (nodeMatchesConstraints) { | |||||
if (nodeBuilder != null) { | if (nodeBuilder != null) { | ||||
nodeObserver.onNext(nodeBuilder.build()); | nodeObserver.onNext(nodeBuilder.build()); | ||||
} | } | ||||
if (remainingMatches >= 0) { | |||||
remainingMatches--; | |||||
if (remainingMatches == 0) { | |||||
// We matched as many nodes as allowed | |||||
throw new StopTraversalException(); | |||||
} | |||||
} | |||||
} | |||||
} | } | ||||
@Override | @Override | ||||
protected void visitEdge(long src, long dst, Label label) { | protected void visitEdge(long src, long dst, Label label) { | ||||
super.visitEdge(src, dst, label); | super.visitEdge(src, dst, label); | ||||
NodePropertyBuilder.buildSuccessorProperties(g, nodeDataMask, nodeBuilder, src, dst, label); | NodePropertyBuilder.buildSuccessorProperties(g, nodeDataMask, nodeBuilder, src, dst, label); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 241 Lines • Show Last 20 Lines |