/*
* This software is Copyright 2005,2006,2007,2008 Langdale Consultants.
* Langdale Consultants can be contacted at: http://www.langdale.com.au
*/
package au.com.langdale.inference;
import com.hp.hpl.jena.graph.Graph;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.reasoner.rulesys.BuiltinException;
import com.hp.hpl.jena.reasoner.rulesys.BuiltinRegistry;
import com.hp.hpl.jena.reasoner.rulesys.RuleContext;
import com.hp.hpl.jena.reasoner.rulesys.builtins.BaseBuiltin;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;
/**
* Custom builtins for the Jena rule based inference engine.
*/
public class ValidationBuiltins extends Reporting {
public static abstract class VarArgsBuiltin extends BaseBuiltin {
protected abstract int getMinArgs();
@Override
public void checkArgs(int length, RuleContext context) {
if (length < getMinArgs()) {
throw new BuiltinException(this, context, "requires at least " + getMinArgs() + " arguments but has " + length);
}
}
}
public static abstract class ValidationBuiltin extends VarArgsBuiltin {
@Override
public void headAction(Node[] args, int length, RuleContext context) {
if( bodyCall(args, length, context))
return;
int offset1 = getMinArgs();
Node subject = getReportSubject(args, offset1, length);
Node phrase = getReportPhrase(getName(), args, offset1, length);
Graph graph = context.getGraph().getDeductionsGraph();
createReport(graph, subject, phrase, args, offset1, length);
}
}
public static class Problem extends ValidationBuiltin {
@Override
protected int getMinArgs() {
return 0;
}
public String getName() {
return "problem";
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
return false;
}
}
public static class DatatypeTest extends ValidationBuiltin {
public String getName() {
return "datatype";
}
@Override
protected int getMinArgs() {
return 2;
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
return isLexicalForm(args[0], args[1]);
}
}
public static class NotDatatypeTest extends ValidationBuiltin {
public String getName() {
return "notDatatype";
}
@Override
protected int getMinArgs() {
return 2;
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
return ! isLexicalForm(args[0], args[1]);
}
}
public static class FactTest extends ValidationBuiltin {
public String getName() {
return "axiom";
}
@Override
protected int getMinArgs() {
return 3;
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
return context.contains(args[0], args[1], args[2]);
}
}
public static class NotFactTest extends ValidationBuiltin {
public String getName() {
return "notAxiom";
}
@Override
protected int getMinArgs() {
return 3;
}
@Override
public boolean isMonotonic() {
return false;
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
return ! context.contains(args[0], args[1], args[2]);
}
}
public static class SameTest extends ValidationBuiltin {
public String getName() {
return "same";
}
@Override
protected int getMinArgs() {
return 2;
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
return args[0].sameValueAs(args[1]);
}
}
public static class NotSameTest extends ValidationBuiltin {
public String getName() {
return "notSame";
}
@Override
protected int getMinArgs() {
return 2;
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
return ! args[0].sameValueAs(args[1]);
}
}
public static abstract class PathTest extends VarArgsBuiltin {
static boolean any(Node start, Node[] path, int at, int length, Graph graph) {
if( at == length - 2)
return graph.contains(start, path[at], path[at+1]);
ExtendedIterator it = graph.find(start, path[at], Node.ANY);
while(it.hasNext()) {
Triple t = (Triple) it.next();
if( any(t.getObject(), path, at + 1, length, graph) )
return true;
}
return false;
}
static boolean all(Node start, Node[] path, int at, int length, Graph graph) {
if( at == length - 1)
return start.sameValueAs(path[at]);
ExtendedIterator it = graph.find(start, path[at], Node.ANY);
while(it.hasNext()) {
Triple t = (Triple) it.next();
if(! all(t.getObject(), path, at + 1, length, graph))
return false;
}
return true;
}
@Override
protected int getMinArgs() {
return 3;
}
}
public static class AnyTest extends PathTest {
public String getName() {
return "any";
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
return any(args[0], args, 1, length, context.getGraph());
}
}
public static class AllTest extends PathTest {
public String getName() {
return "all";
}
@Override
public boolean isMonotonic() {
return false;
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
return all(args[0], args, 1, length, context.getGraph());
}
}
public static class NotAnyTest extends PathTest {
public String getName() {
return "notAny";
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
return ! any(args[0], args, 1, length, context.getGraph());
}
@Override
public boolean isMonotonic() {
return false;
}
}
public static class NotAllTest extends PathTest {
public String getName() {
return "notAll";
}
@Override
public boolean bodyCall(Node[] args, int length, RuleContext context) {
checkArgs(length, context);
return ! all(args[0], args, 1, length, context.getGraph());
}
}
public static void registerAll() {
registerAll(BuiltinRegistry.theRegistry);
}
public static void registerAll(BuiltinRegistry r) {
r.register(new Problem());
r.register(new DatatypeTest());
r.register(new DatatypeTest());
r.register(new NotDatatypeTest());
r.register(new SameTest());
r.register(new NotSameTest());
r.register(new FactTest());
r.register(new NotFactTest());
r.register(new AnyTest());
r.register(new NotAnyTest());
r.register(new AllTest());
}
}