@Override public Traversal.Admin<Object, Object> apply(final Traverser.Admin<Object> traverser) { // optimization to favor processing StarGraph local objects first to limit message passing (GraphComputer only) // TODO: generalize this for future MatchAlgorithms (given that 3.2.0 will focus on RealTimeStrategy, it will probably go there) if (this.onComputer) { final List<Set<String>> labels = traverser.path().labels(); final Set<String> lastLabels = labels.get(labels.size() - 1); Collections.sort(this.bundles, Comparator.<Bundle>comparingLong(b -> Helper.getStartLabels(b.traversal).stream().filter(startLabel -> !lastLabels.contains(startLabel)).count()). thenComparingInt(b -> b.traversalType.ordinal()). thenComparingDouble(b -> b.multiplicity)); } Bundle startLabelsBundle = null; for (final Bundle bundle : this.bundles) { if (!Helper.hasExecutedTraversal(traverser, bundle.traversal) && Helper.hasStartLabels(traverser, bundle.traversal)) { if (bundle.traversalType != TraversalType.MATCH_TRAVERSAL || Helper.hasEndLabel(traverser, bundle.traversal)) return bundle.traversal; else if (null == startLabelsBundle) startLabelsBundle = bundle; } } if (null != startLabelsBundle) return startLabelsBundle.traversal; throw UNMATCHABLE_PATTERN.apply(this.bundles.stream().map(record -> record.traversal).collect(Collectors.toList())); }
private boolean hasMatched(final ConnectiveStep.Connective connective, final Traverser.Admin<S> traverser) { int counter = 0; boolean matched = false; for (final Traversal.Admin<Object, Object> matchTraversal : this.matchTraversals) { if (traverser.getTags().contains(matchTraversal.getStartStep().getId())) { if (connective == ConnectiveStep.Connective.OR) { matched = true; break; } counter++; } } if (!matched) matched = this.matchTraversals.size() == counter; if (matched && this.dedupLabels != null) { final Path path = traverser.path(); final List<Object> objects = new ArrayList<>(this.dedupLabels.size()); for (final String label : this.dedupLabels) { objects.add(path.get(Pop.last, label)); } this.dedups.add(objects); } return matched; }
public static boolean hasEndLabel(final Traverser.Admin<Object> traverser, final Traversal.Admin<Object, Object> traversal) { final Optional<String> endLabel = Helper.getEndLabel(traversal); return endLabel.isPresent() && traverser.path().hasLabel(endLabel.get()); // TODO: !isPresent? }
@Override public Path path() { return this.baseTraverser.path(); }
public static boolean hasStartLabels(final Traverser.Admin<Object> traverser, final Traversal.Admin<Object, Object> traversal) { for (final String label : Helper.getStartLabels(traversal)) { if (!traverser.path().hasLabel(label)) return false; } return true; }
@Override protected Path map(final Traverser.Admin<S> traverser) { final Path path = traverser.path().subPath(this.fromLabel, this.toLabel); if (this.traversalRing.isEmpty()) return path; else { this.traversalRing.reset(); final Path byPath = MutablePath.make(); path.forEach((object, labels) -> byPath.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels)); return byPath; } }
if (!traverser.getTags().contains(this.getId())) { traverser.getTags().add(this.getId()); // so the traverser never returns to this branch ever again if (!this.hasPathLabel(traverser.path(), this.matchStartLabels)) traverser.addLabels(Collections.singleton(this.computedStartLabel)); // if the traverser doesn't have a legal start, then provide it the pre-computed one
if (!traverser.getTags().contains(this.getId())) { traverser.getTags().add(this.getId()); // so the traverser never returns to this branch ever again if (!this.hasPathLabel(traverser.path(), this.matchStartLabels)) traverser.addLabels(Collections.singleton(this.computedStartLabel)); // if the traverser doesn't have a legal start, then provide it the pre-computed one
@Override protected Traverser.Admin<Object> processNextStart() throws NoSuchElementException { if (null == this.parent) this.parent = ((MatchStep) this.getTraversal().getParent().asStep()); while (true) { final Traverser.Admin traverser = this.starts.next(); // no end label if (null == this.matchKey) { // if (this.traverserStepIdAndLabelsSetByChild) -- traverser equality is based on stepId, lets ensure they are all at the parent traverser.setStepId(this.parent.getId()); this.parent.getMatchAlgorithm().recordEnd(traverser, this.getTraversal()); return this.retractUnnecessaryLabels(traverser); } // TODO: sideEffect check? // path check final Path path = traverser.path(); if (!path.hasLabel(this.matchKey) || traverser.get().equals(path.get(Pop.last, this.matchKey))) { // if (this.traverserStepIdAndLabelsSetByChild) -- traverser equality is based on stepId and thus, lets ensure they are all at the parent traverser.setStepId(this.parent.getId()); traverser.addLabels(this.matchKeyCollection); this.parent.getMatchAlgorithm().recordEnd(traverser, this.getTraversal()); return this.retractUnnecessaryLabels(traverser); } } }
@Override protected E map(final Traverser.Admin<S> traverser) { E end = null; final Iterator<E> keyIterator = TraversalUtil.applyAll(traverser, this.keyTraversal); if (keyIterator.hasNext()) { final E key = keyIterator.next(); final Object object = traverser.get(); if (object instanceof Map && ((Map) object).containsKey(key)) end = (E) ((Map) object).get(key); else if (key instanceof String) { final String skey = (String) key; if (traverser.getSideEffects().exists(skey)) { end = traverser.getSideEffects().get((String) key); } else { final Path path = traverser.path(); if (path.hasLabel(skey)) end = null == pop ? path.get(skey) : path.get(pop, skey); } } } return null != end ? TraversalUtil.applyNullable(end, this.selectTraversal) : null; }
public default <S> S getNullableScopeValue(final Pop pop, final String key, final Traverser.Admin<?> traverser) { final Object object = traverser.get(); if (object instanceof Map && ((Map<String, S>) object).containsKey(key)) return ((Map<String, S>) object).get(key); /// if (traverser.getSideEffects().exists(key)) return traverser.getSideEffects().get(key); /// final Path path = traverser.path(); if (path.hasLabel(key)) return path.get(pop, key); /// return null; }
@Override public Tree projectTraverser(final Traverser.Admin<S> traverser) { final Tree topTree = new Tree(); Tree depth = topTree; final Path path = traverser.path(); for (int i = 0; i < path.size(); i++) { final Object object = TraversalUtil.applyNullable(path.<Object>get(i), this.traversalRing.next()); if (!depth.containsKey(object)) depth.put(object, new Tree<>()); depth = (Tree) depth.get(object); } this.traversalRing.reset(); return topTree; }
@Override protected void sideEffect(final Traverser.Admin<S> traverser) { final Tree root = new Tree(); Tree depth = root; final Path path = traverser.path(); for (int i = 0; i < path.size(); i++) { final Object object = TraversalUtil.applyNullable(path.<Object>get(i), this.traversalRing.next()); if (!depth.containsKey(object)) depth.put(object, new Tree<>()); depth = (Tree) depth.get(object); } this.traversalRing.reset(); this.getTraversal().getSideEffects().add(this.sideEffectKey, root); }
public default <S> S getScopeValue(final Pop pop, final String key, final Traverser.Admin<?> traverser) throws IllegalArgumentException { final Object object = traverser.get(); if (object instanceof Map && ((Map<String, S>) object).containsKey(key)) return ((Map<String, S>) object).get(key); /// if (traverser.getSideEffects().exists(key)) return traverser.getSideEffects().get(key); /// final Path path = traverser.path(); if (path.hasLabel(key)) return path.get(pop, key); /// throw new IllegalArgumentException("Neither the sideEffects, map, nor path has a " + key + "-key: " + this); }
@Override public Path path() { return this.baseTraverser.path(); }
@Override protected Vertex map(final Traverser.Admin<Edge> traverser) { final List<Object> objects = traverser.path().objects(); for (int i = objects.size() - 2; i >= 0; i--) { if (objects.get(i) instanceof Vertex) { return ElementHelper.areEqual((Vertex) objects.get(i), traverser.get().outVertex()) ? traverser.get().inVertex() : traverser.get().outVertex(); } } throw new IllegalStateException("The path history of the traverser does not contain a previous vertex: " + traverser.path()); }
@Override protected Traverser.Admin<Object> processNextStart() throws NoSuchElementException { if (null == this.parent) this.parent = (MatchStep<?, ?>) this.getTraversal().getParent(); final Traverser.Admin<Object> traverser = this.starts.next(); this.parent.getMatchAlgorithm().recordStart(traverser, this.getTraversal()); // TODO: sideEffect check? return null == this.selectKey ? traverser : traverser.split(traverser.path().get(Pop.last, this.selectKey), this); }
@Override protected Path map(final Traverser.Admin<S> traverser) { final Path path = traverser.path().subPath(this.fromLabel, this.toLabel); if (this.traversalRing.isEmpty()) return path; else { this.traversalRing.reset(); final Path byPath = MutablePath.make(); path.forEach((object, labels) -> byPath.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels)); return byPath; } }
@Override protected boolean filter(final Traverser.Admin<S> traverser) { final Path path = traverser.path().subPath(this.fromLabel, this.toLabel); if (this.traversalRing.isEmpty()) return path.isSimple() == this.isSimple; else { this.traversalRing.reset(); final Path byPath = MutablePath.make(); path.forEach((object, labels) -> byPath.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels)); return byPath.isSimple() == this.isSimple; } }
public static boolean hasStartLabels(final Traverser.Admin<Object> traverser, final Traversal.Admin<Object, Object> traversal) { for (final String label : Helper.getStartLabels(traversal)) { if (!traverser.path().hasLabel(label)) return false; } return true; }