
com.telenav.mesakit.graph.query.GraphQuery Maven / Gradle / Ivy
package com.telenav.mesakit.graph.query;
import com.telenav.kivakit.core.progress.ProgressReporter;
import com.telenav.kivakit.core.value.count.Maximum;
import com.telenav.kivakit.interfaces.code.Callback;
import com.telenav.mesakit.graph.Route;
import com.telenav.mesakit.graph.collections.EdgeSequence;
import com.telenav.mesakit.graph.query.antlr.GraphQueryLexer;
import com.telenav.mesakit.graph.query.antlr.GraphQueryParser;
import com.telenav.mesakit.graph.query.compiler.GraphQueryCompiler;
import com.telenav.mesakit.graph.query.compiler.GraphQueryErrorListener;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import java.util.HashSet;
import java.util.Set;
import static com.telenav.kivakit.core.collections.set.ObjectSet.set;
/**
* Evaluates a sequence of candidate edges against a query, return up to the given maximum number of matches.
*
* @author jonathanl (shibo)
*/
public class GraphQuery
{
private volatile boolean stop;
/**
* Selects from a sequence of edges those that match the query.
*
* @param candidates The candidate edges to match against the query
* @param query The query string
* @param maximumMatches The maximum number of matching edges to return
* @param errorHandler Callback for receiving error messages
* @return The set of candidate edges matching the query
*/
public Set execute(ProgressReporter reporter,
EdgeSequence candidates,
String query,
Maximum maximumMatches,
Callback errorHandler)
{
// Start the progress reporter,
reporter.steps(candidates.count().asMaximum());
reporter.start();
// create a lexer for query,
var lexer = new GraphQueryLexer(CharStreams.fromString(query));
// parse the lexer token stream,
var parser = new GraphQueryParser(new CommonTokenStream(lexer));
var listener = new GraphQueryErrorListener(errorHandler);
parser.addErrorListener(listener);
var queryParseTree = parser.select();
// and if an error was reported
if (listener.error())
{
// return nothing
return set();
}
// or if the parser ran out of input
if (!parser.isMatchedEOF())
{
// report that
errorHandler.call("Parser did not match all input in query expression");
return set();
}
// or if there's a syntax error
if (parser.getNumberOfSyntaxErrors() > 0)
{
// return an empty set
errorHandler.call("Syntax error");
return set();
}
// otherwise, create a query compiler,
var compiler = new GraphQueryCompiler();
// build the query program to run,
var program = compiler.compile(queryParseTree, Maximum._8);
// then go through all the candidate edges
var matches = new HashSet();
for (var candidate : candidates)
{
if (stop)
{
break;
}
// and if running the program on the candidate results in a match
var match = program.run(candidate);
if (match != null)
{
// then add the route to the set of matches
matches.add(match);
// and if we have found enough matches already,
if (matches.size() == maximumMatches.asInt())
{
// then stop looking and return them
return matches;
}
}
reporter.next();
}
reporter.end();
return matches;
}
public void stop()
{
stop = true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy