package io.sigpipe.sing.query;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import io.sigpipe.sing.dataset.feature.FeatureType;
import io.sigpipe.sing.graph.Vertex;
import io.sigpipe.sing.serialization.SerializationInputStream;
import io.sigpipe.sing.serialization.SerializationOutputStream;

public class RelationalQuery extends Query {

    private Set<Vertex> pruned;

    public RelationalQuery() {

    }

    @Override
    public void execute(Vertex root)
    throws IOException, QueryException {
        this.pruned = new HashSet<Vertex>();
        System.out.println("expressions: " + expressions.size());
        prune(root, 0);
        System.out.println("Pruned " + pruned.size() + " vertices");
    }

    private void prune(Vertex vertex, int expressionsEvaluated)
    throws QueryException {
        if (expressionsEvaluated == this.expressions.size()) {
            return;
        }

        String childFeature = vertex.getFirstNeighbor().getLabel().getName();
        List<Expression> expList = this.expressions.get(childFeature);
        if (expList != null) {
            Set<Vertex> allNeighbors = new HashSet<>(vertex.getAllNeighbors());
            Set<Vertex> matches = evaluate(vertex, expList);
            for (Vertex match : matches) {
                if (match == null) {
                    continue;
                }

                if (match.getLabel().getType() == FeatureType.NULL) {
                    continue;
                }

                prune(match, expressionsEvaluated + 1);
            }

            allNeighbors.removeAll(matches);
            for (Vertex nonMatch : allNeighbors) {
                pruned.add(nonMatch);
            }
        } else {
            /* No expression operates on this vertex. Consider all children. */
            for (Vertex neighbor : vertex.getAllNeighbors()) {
                prune(neighbor, expressionsEvaluated);
            }
        }

        if (foundSubMatch == false) {

    }
}

@@ -775,20 +775,23 @@
 private 
-void
+boolean
  prune(V
@@ -937,26 +937,231 @@
     
-return;%0A        %7D%0A
+/* There are no further expressions to evaluate. Therefore, we must%0A             * assume all children from this point are relevant to the query. */%0A            return true;%0A        %7D%0A%0A        boolean foundSubMatch = false;
 %0A   
@@ -1365,124 +1365,164 @@
 ex%3E 
-allNeighbors = new HashSet%3C%3E(vertex.getAllNeighbors());%0A            Set%3CVertex%3E matches = evaluate(vertex, expList);
+matches = evaluate(vertex, expList);%0A            if (matches.size() == 0) %7B%0A                pruned.add(vertex);%0A                return false;%0A            %7D%0A
 %0A   
@@ -1778,24 +1778,28 @@
             
+if (
 prune(match,
@@ -1828,48 +1828,194 @@
 + 1)
-;%0A            %7D%0A%0A            allNeighbor
+ == true) %7B%0A                    foundSubMatch = true;%0A                %7D%0A            %7D%0A%0A            Set%3CVertex%3E nonMatches = new HashSet%3C%3E(vertex.getAllNeighbors());%0A            nonMatche
 s.re
@@ -2071,19 +2071,17 @@
 h : 
-allNeighbor
+nonMatche
 s) %7B
@@ -2305,24 +2305,28 @@
             
+if (
 prune(neighb
@@ -2354,73 +2354,215 @@
 ted)
-;%0A            %7D%0A        %7D%0A%0A        if (foundSubMatch == false) %7B%0A
+ == true) %7B%0A                    foundSubMatch = true;%0A                %7D%0A            %7D%0A        %7D%0A%0A        if (foundSubMatch == false) %7B%0A            pruned.add(vertex);%0A        %7D%0A%0A        return foundSubMatch;
 %0A   

Add a boolean return value to prune()