use of org.umlg.sqlg.structure.SqlgTraverser in project sqlg by pietermartin.
the class SqlgWhereTraversalStepBarrier method processNextStart.
@Override
protected Traverser.Admin<S> processNextStart() throws NoSuchElementException {
if (this.first) {
this.first = false;
while (this.starts.hasNext()) {
Traverser.Admin start = this.starts.next();
// However the traverser might have been created from a step and strategy that does not care for TraverserRequirement.ONE_BULK so we force it here.
if (start instanceof SqlgTraverser) {
((SqlgTraverser) start).setRequiresOneBulk(true);
}
List<Object> startObjects = start.path().objects();
StringBuilder recordIdConcatenated = new StringBuilder();
for (Object startObject : startObjects) {
if (startObject instanceof Element) {
Element e = (Element) startObject;
recordIdConcatenated.append(e.id().toString());
} else {
recordIdConcatenated.append(startObject.toString());
}
}
this.startRecordIds.put(recordIdConcatenated.toString(), start);
this.whereTraversal.addStart(start);
}
while (this.whereTraversal.hasNext()) {
Traverser.Admin<?> filterTraverser = this.whereTraversal.nextTraverser();
List<Object> filterTraverserObjects = filterTraverser.path().objects();
String startId = "";
for (Object filteredTraverserObject : filterTraverserObjects) {
if (filteredTraverserObject instanceof Element) {
Element e = (Element) filteredTraverserObject;
startId += e.id().toString();
} else {
startId += filteredTraverserObject.toString();
}
if (startRecordIds.containsKey(startId)) {
this.results.addAll(startRecordIds.get(startId));
startRecordIds.removeAll(startId);
}
if (startRecordIds.isEmpty()) {
break;
}
}
}
this.results.sort((o1, o2) -> {
SqlgTraverser x = (SqlgTraverser) o1;
SqlgTraverser y = (SqlgTraverser) o2;
return Long.compare(x.getStartElementIndex(), y.getStartElementIndex());
});
this.resultIterator = this.results.iterator();
}
if (this.resultIterator.hasNext()) {
Traverser.Admin<S> traverser = this.resultIterator.next();
return PathProcessor.processTraverserPathLabels(traverser, this.keepLabels);
} else {
// The standard TraversalFilterStep.filter calls TraversalUtil.test which normally resets the traversal for every incoming start.
reset();
throw FastNoSuchElementException.instance();
}
}
use of org.umlg.sqlg.structure.SqlgTraverser in project sqlg by pietermartin.
the class SqlgBranchStepBarrier method processNextStart.
@Override
protected Traverser.Admin<E> processNextStart() throws NoSuchElementException {
if (this.first) {
List<Traverser.Admin<S>> successfulStarts = new ArrayList<>();
Map<Long, Traverser.Admin<S>> cachedStarts = new HashMap<>();
Map<Traverser.Admin<S>, Object> startBranchTraversalResults = new HashMap<>();
this.first = false;
long startCount = 1;
while (this.starts.hasNext()) {
Traverser.Admin<S> start = this.starts.next();
this.branchTraversal.addStart(start);
((SqlgElement) start.get()).setInternalStartTraverserIndex(startCount);
cachedStarts.put(startCount++, start);
}
Set<Long> toRemove = new HashSet<>();
while (true) {
if (this.branchTraversal.hasNext()) {
Traverser.Admin<M> branchTraverser = this.branchTraversal.nextTraverser();
long startElementIndex = ((SqlgTraverser<M>) branchTraverser).getStartElementIndex();
M m = branchTraverser.get();
// i.e. traversals that do not go to the db.
if (startElementIndex == 0 && m instanceof SqlgElement) {
SqlgElement sqlgElement = (SqlgElement) m;
startElementIndex = sqlgElement.getInternalStartTraverserIndex();
}
if (!(m instanceof SqlgElement)) {
// This assumes that branchTraversals that do not go to the db only return one value per start.
List<Object> branchTraverserPathObjects = branchTraverser.path().objects();
long count = 0;
for (Traverser.Admin<S> cachedStart : cachedStarts.values()) {
count++;
List<Object> cachedStartPathObjects = cachedStart.path().objects();
boolean startsWith = false;
// for CountGlobalStep the path is lost but all elements return something so the branch to take is always the 'true' branch.
if (!(branchTraverserPathObjects.get(0) instanceof SqlgElement)) {
startsWith = true;
}
if (!startsWith) {
int countX = 0;
for (Object startObject : cachedStartPathObjects) {
startsWith = branchTraverserPathObjects.get(countX++).equals(startObject);
if (!startsWith) {
break;
}
}
}
if (startsWith) {
successfulStarts.add(cachedStart);
toRemove.add(count);
startBranchTraversalResults.put(cachedStart, branchTraverserPathObjects.get(branchTraverserPathObjects.size() - 1));
}
}
} else {
Traverser.Admin<S> start = cachedStarts.remove(startElementIndex);
if (start != null) {
successfulStarts.add(start);
}
}
} else {
break;
}
}
// i.e. only failed starts remain in the list.
for (Long remove : toRemove) {
cachedStarts.remove(remove);
}
// true false choose step does not have a HasNextStep. Its been removed to keep the path.
if (this.traversalOptions.containsKey(Boolean.TRUE) && this.traversalOptions.containsKey(Boolean.FALSE)) {
for (Traverser.Admin<S> successfulStart : successfulStarts) {
for (Traversal.Admin<S, E> optionTraversal : this.traversalOptions.get(Boolean.TRUE)) {
optionTraversal.addStart(successfulStart);
}
}
for (Traversal.Admin<S, E> optionTraversal : this.traversalOptions.get(Boolean.FALSE)) {
for (Traverser.Admin<S> start : cachedStarts.values()) {
optionTraversal.addStart(start);
}
}
} else {
for (Map.Entry<Traverser.Admin<S>, Object> entry : startBranchTraversalResults.entrySet()) {
Traverser.Admin<S> start = entry.getKey();
Object branchEndObject = entry.getValue();
if (this.traversalOptions.containsKey(branchEndObject)) {
for (Traversal.Admin<S, E> optionTraversal : this.traversalOptions.get(branchEndObject)) {
optionTraversal.addStart(start);
}
} else {
if (this.traversalOptions.containsKey(Pick.none)) {
for (Traversal.Admin<S, E> optionTraversal : this.traversalOptions.get(Pick.none)) {
optionTraversal.addStart(start);
}
}
}
}
// List<Traversal.Admin<S, E>> optionTraversals = this.traversalOptions.get(Pick.none);
// for (Traversal.Admin<S, E> optionTraversal : optionTraversals) {
// for (Traverser.Admin<S> start : cachedStarts.values()) {
// optionTraversal.addStart(start);
// }
// }
}
// Now travers the options. The starts have been set.
for (M choice : this.traversalOptions.keySet()) {
for (Traversal.Admin<S, E> option : this.traversalOptions.get(choice)) {
while (true) {
if (option.hasNext()) {
this.results.add(option.nextTraverser());
} else {
break;
}
}
}
}
// Sort the results, this is to ensure the the incoming start order is not lost.
this.results.sort((o1, o2) -> {
SqlgTraverser x = (SqlgTraverser) o1;
SqlgTraverser y = (SqlgTraverser) o2;
return Long.compare(x.getStartElementIndex(), y.getStartElementIndex());
});
this.resultIterator = this.results.iterator();
}
while (this.resultIterator.hasNext()) {
return this.resultIterator.next();
}
throw FastNoSuchElementException.instance();
}
use of org.umlg.sqlg.structure.SqlgTraverser in project sqlg by pietermartin.
the class SqlgOptionalStepBarrier method processNextStart.
@Override
protected Traverser.Admin<S> processNextStart() throws NoSuchElementException {
if (this.first) {
Multimap<String, Traverser.Admin<S>> startRecordIds = LinkedListMultimap.create();
this.first = false;
long startCount = 1;
while (this.starts.hasNext()) {
Traverser.Admin<S> start = this.starts.next();
this.optionalTraversal.addStart(start);
((SqlgElement) start.get()).setInternalStartTraverserIndex(startCount++);
List<Object> startObjects = start.path().objects();
StringBuilder recordIdConcatenated = new StringBuilder();
for (Object startObject : startObjects) {
Element e = (Element) startObject;
recordIdConcatenated.append(e.id().toString());
}
startRecordIds.put(recordIdConcatenated.toString(), start);
}
while (true) {
if (this.optionalTraversal.hasNext()) {
Traverser.Admin<S> optionalTraverser = this.optionalTraversal.nextTraverser();
this.results.add(optionalTraverser);
List<Object> optionObjects = optionalTraverser.path().objects();
String startId = "";
for (Object optionObject : optionObjects) {
Element e = (Element) optionObject;
startId += e.id().toString();
if (startRecordIds.removeAll(startId).isEmpty()) {
break;
}
}
} else {
break;
}
}
for (Traverser.Admin<S> start : startRecordIds.values()) {
this.results.add(start);
// Bulking logic interferes here, addStart calls DefaultTraversal.merge which has bulking logic
start.setBulk(1L);
}
// Now travers the options. The starts have been set.
while (true) {
if (this.optionalTraversal.hasNext()) {
this.results.add(optionalTraversal.nextTraverser());
} else {
break;
}
}
// Sort the results, this is to ensure the the incoming start order is not lost.
this.results.sort((o1, o2) -> {
SqlgTraverser x = (SqlgTraverser) o1;
SqlgTraverser y = (SqlgTraverser) o2;
return Long.compare(x.getStartElementIndex(), y.getStartElementIndex());
});
this.resultIterator = this.results.iterator();
}
while (this.resultIterator.hasNext()) {
return this.resultIterator.next();
}
throw FastNoSuchElementException.instance();
}
Aggregations