/* * 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 java.util.HashMap; import java.util.List; import java.util.Map; import com.hp.hpl.jena.graph.Node; import com.hp.hpl.jena.reasoner.TriplePattern; import com.hp.hpl.jena.reasoner.rulesys.BindingEnvironment; import com.hp.hpl.jena.reasoner.rulesys.ClauseEntry; import com.hp.hpl.jena.reasoner.rulesys.Functor; import com.hp.hpl.jena.reasoner.rulesys.Node_RuleVariable; import com.hp.hpl.jena.reasoner.rulesys.Rule; import com.hp.hpl.jena.reasoner.rulesys.impl.BindingVector; /** * A Rule whose clauses may include other rules. */ public class CompoundRule extends Rule { private CompoundRule alternative; public CompoundRule(String name, List head, List body, int numVars) { super(name, head, body); this.numVars = numVars; } public CompoundRule(String name, ClauseEntry[] head, ClauseEntry[] body, int numVars) { super(name, head, body); this.numVars = numVars; } public CompoundRule(CompoundRule main, CompoundRule alternative) { super(main.name, main.head, main.body); this.numVars = main.numVars; this.name = main.name; this.isBackward = main.isBackward; this.alternative = alternative; } public boolean isFunction() { if( body.length == 0 || ! (body[0] instanceof Functor)) return false; Node[] formals = ((Functor)body[0]).getArgs(); for(int ix = 0; ix < formals.length; ix++) if(! formals[ix].isVariable()) return false; return true; } @Override public int getNumVars() { assert numVars > -1; return numVars; } public CompoundRule getAlternative() { return alternative; } /** * Instantiate a rule given a variable binding environment. * This will clone any non-bound variables though that is only needed * for trail implementations. */ @Override public Rule instantiate(BindingEnvironment env) { env = new PartialBinding(((BindingVector)env).getEnvironment()); HashMap vmap = new HashMap(); return instantiate(vmap, env); } /** * Clone a rule, cloning any embedded variables. */ @Override public Rule cloneRule() { if (getNumVars() > 0) { HashMap vmap = new HashMap(); return new CompoundRule(name, cloneClauseArray(head, vmap, null), cloneClauseArray(body, vmap, null), numVars); } else { return this; } } private CompoundRule instantiate(HashMap vmap, BindingEnvironment env) { return new CompoundRule(name, cloneClauseArray(head, vmap, env), cloneClauseArray(body, vmap, env), numVars); } /** * Clone a clause array. */ private ClauseEntry[] cloneClauseArray(ClauseEntry[] clauses, Map vmap, BindingEnvironment env) { ClauseEntry[] cClauses = new ClauseEntry[clauses.length]; for (int i = 0; i < clauses.length; i++ ) { cClauses[i] = cloneClause(clauses[i], vmap, env); } return cClauses; } /** * Clone a clause, cloning any embedded variables. */ private ClauseEntry cloneClause(ClauseEntry clause, Map vmap, BindingEnvironment env) { if (clause instanceof TriplePattern) { return cloneTriplePattern((TriplePattern)clause, vmap, env); } else if(clause instanceof Functor ){ return cloneFunctor((Functor)clause, vmap, env); } else if(clause instanceof CompoundRule) return ((CompoundRule)clause).instantiate(new HashMap(vmap), env); else if(clause instanceof QuoteClause) return cloneQuoteClause((QuoteClause)clause, vmap, env); else return null; } private ClauseEntry cloneQuoteClause(QuoteClause clause, Map vmap, BindingEnvironment env) { return new QuoteClause(cloneNode(clause.getQuote(), vmap, env), cloneClause(clause.getClause(), vmap, env)); } private TriplePattern cloneTriplePattern(TriplePattern tp, Map vmap, BindingEnvironment env) { return new TriplePattern ( cloneNode(tp.getSubject(), vmap, env), cloneNode(tp.getPredicate(), vmap, env), cloneNode(tp.getObject(), vmap, env) ); } /** * Clone a functor, cloning any embedded variables. */ private Functor cloneFunctor(Functor f, Map vmap, BindingEnvironment env) { Node[] args = f.getArgs(); Node[] cargs = new Node[args.length]; for (int i = 0; i < args.length; i++) { cargs[i] = cloneNode(args[i], vmap, env); } Functor fn = new Functor(f.getName(), cargs); fn.setImplementor(f.getImplementor()); return fn; } /** * Clone a single node. */ private Node cloneNode(Node nIn, Map vmap, BindingEnvironment env) { Node n = (env == null) ? nIn : env.getGroundVersion(nIn); if (n instanceof Node_RuleVariable) { Node_RuleVariable nv = (Node_RuleVariable)n; Node c = (Node)vmap.get(nv); if (c == null) { c = nv.cloneNode(); vmap.put(nv, c); } return c; } else if (Functor.isFunctor(n)) { Functor f = (Functor)n.getLiteralValue(); return Functor.makeFunctorNode(cloneFunctor(f, vmap, env)); } else { return n; } } @Override public String toString() { if( alternative == null ) return super.toString(); else return super.toString() + "||" + alternative.toString(); } }