/*
 * Copyright (C) 1999-2004 <a href="mailto:mandarax@jbdietrich.com">Jens Dietrich</a>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package org.mandarax.util;


import java.util.List;
import java.util.Vector;

import org.mandarax.kernel.ComplexTerm;
import org.mandarax.kernel.ConstantTerm;
import org.mandarax.kernel.Fact;
import org.mandarax.kernel.Function;
import org.mandarax.kernel.LogicFactory;
import org.mandarax.kernel.Predicate;
import org.mandarax.kernel.Prerequisite;
import org.mandarax.kernel.Query;
import org.mandarax.kernel.Rule;
import org.mandarax.kernel.Term;

/**
 * Utility class to facilitate creating rules, facts and terms.
 * @author <A HREF="mailto:mandarax@jbdietrich.com">Jens Dietrich</A>
 * @version 3.3.1 <9 August 2004>
 * @since 1.2
 */
public class LogicFactorySupport {

    private LogicFactory lfactory = LogicFactory.getDefaultFactory ();

    /**
     * Constructor.
     */
    public LogicFactorySupport() {
        super ();
    }

    /**
     * Constructor.
     * @param aFactory the logic factory to be used
     */
    public LogicFactorySupport(LogicFactory aFactory) {
        super ();
    }

    /**
     * Create a constant term.
     * @return the constant term created
     * @param obj the object
     * @param type the type
     */
    public ConstantTerm cons(Object obj, Class type) {
        return lfactory.createConstantTerm (obj, type);
    }

    /**
     * Create a complex term.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the complex term created
     * @param function the function
     * @param objs objects (will be interpreted as terms)
     */
    public ComplexTerm cplx(Function function, Object[] objs) {
        Class[] structure = function.getStructure ();

        if(structure.length != objs.length) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this function, the number is "
                + objs.length + ", but must be " + structure.length);
        }

        Term[] terms = new Term[structure.length];

        for(int i = 0; i < structure.length; i++) {
            terms[i] = toTerm (objs[i], structure[i]);
        }

        return lfactory.createComplexTerm (function, terms);
    }

    /**
     * Create a complex term with one (sub)term.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the complex term created
     * @param function the function
     * @param obj an object
     */
    public ComplexTerm cplx(Function function, Object obj1) {
        Class[] structure = function.getStructure ();

        if(structure.length != 1) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this function, the number is 1, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj1, structure[0]) };

        return lfactory.createComplexTerm (function, terms);
    }

    /**
     * Create a complex term with two (sub)terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the complex term created
     * @param function the function
     * @param obj1 an object
     * @param obj2 an object
     */
    public ComplexTerm cplx(Function function, Object obj1, Object obj2) {
        Class[] structure = function.getStructure ();

        if(structure.length != 2) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this function, the number is 2, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj1, structure[0]),
                         toTerm (obj2, structure[1]) };

        return lfactory.createComplexTerm (function, terms);
    }

    /**
     * Create a complex term with three (sub)terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the complex term created
     * @param function the function
     * @param obj1 an object
     * @param obj2 an object
     * @param obj3 an object
     */
    public ComplexTerm cplx(Function function, Object obj1, Object obj2,
                            Object obj3) {
        Class[] structure = function.getStructure ();

        if(structure.length != 3) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this function, the number is 3, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj1, structure[0]),
                         toTerm (obj2, structure[1]),
                         toTerm (obj3, structure[2]) };

        return lfactory.createComplexTerm (function, terms);
    }

    /**
     * Create a complex term with four (sub)terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the complex term created
     * @param function the function
     * @param obj1 an object
     * @param obj2 an object
     * @param obj3 an object
     * @param obj4 an object
     */
    public ComplexTerm cplx(Function function, Object obj1, Object obj2,
                            Object obj3, Object obj4) {
        Class[] structure = function.getStructure ();

        if(structure.length != 4) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this function, the number is 4, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj1, structure[0]),
                         toTerm (obj2, structure[1]),
                         toTerm (obj3, structure[2]),
                         toTerm (obj4, structure[3]) };

        return lfactory.createComplexTerm (function, terms);
    }

    /**
     * Create a fact.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the fact created
     * @param predicate the predicate
     * @param objs objects (will be interpreted as terms)
     */
    public Fact fact(Predicate predicate, Object[] objs) {
        Class[] structure = predicate.getStructure ();

        if(structure.length != objs.length) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this predicate, the number is "
                + objs.length + ", but must be " + structure.length);
        }

        Term[] terms = new Term[structure.length];

        for(int i = 0; i < structure.length; i++) {
            terms[i] = toTerm (objs[i], structure[i]);
        }

        return lfactory.createFact (predicate, terms);
    }

    /**
     * Create a fact with one term.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the fact created
     * @param predicate the predicate
     * @param obj an object
     */
    public Fact fact(Predicate predicate, Object obj) {
        Class[] structure = predicate.getStructure ();

        if(structure.length != 1) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this predicate, the number is 1, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj, structure[0]) };

        return lfactory.createFact (predicate, terms);
    }

    /**
     * Create a fact with two terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the fact created
     * @param predicate the predicate
     * @param obj1 an object
     * @param obj2 an object
     */
    public Fact fact(Predicate predicate, Object obj1, Object obj2) {
        Class[] structure = predicate.getStructure ();

        if(structure.length != 2) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this predicate, the number is 2, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj1, structure[0]),
                         toTerm (obj2, structure[1]) };

        return lfactory.createFact (predicate, terms);
    }

    /**
     * Create a fact with three terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the fact created
     * @param predicate the predicate
     * @param obj1 an object
     * @param obj2 an object
     * @param obj3 an object
     */
    public Fact fact(Predicate predicate, Object obj1, Object obj2, Object obj3) {
        Class[] structure = predicate.getStructure ();

        if(structure.length != 3) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this predicate, the number is 3, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj1, structure[0]),
                         toTerm (obj2, structure[1]),
                         toTerm (obj3, structure[2]) };

        return lfactory.createFact (predicate, terms);
    }

    /**
     * Create a fact with four terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the fact created
     * @param predicate the predicate
     * @param obj1 an object
     * @param obj2 an object
     * @param obj3 an object
     * @param obj4 an object
     */
    public Fact fact(Predicate predicate, Object obj1, Object obj2,Object obj3, Object obj4) {
        Class[] structure = predicate.getStructure ();

        if(structure.length != 4) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this predicate, the number is 4, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj1, structure[0]),
                         toTerm (obj2, structure[1]),
                         toTerm (obj3, structure[2]),
                         toTerm (obj4, structure[3]) };

        return lfactory.createFact (predicate, terms);
    }
    
    /**
     * Create a prerequisite.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the prerequisite created
     * @param predicate the predicate
     * @param objs objects (will be interpreted as terms)
     */
    public Prerequisite prereq(Predicate predicate, Object[] objs) {
    	
        return prereq(predicate,objs,false);
    }

    /**
     * Create a prerequisite with one term.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the prerequisite created
     * @param predicate the predicate
     * @param obj an object
     */
    public Prerequisite prereq(Predicate predicate, Object obj) {
        
		return prereq(predicate,obj,false);
    }

    /**
     * Create a prerequisite with two terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the prerequisite created
     * @param predicate the predicate
     * @param obj1 an object
     * @param obj2 an object
     */
    public Prerequisite prereq(Predicate predicate, Object obj1, Object obj2) {
    	
        return prereq(predicate,obj1,obj2,false);
    }

    /**
     * Create a prerequisite with three terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the prerequisite created
     * @param predicate the predicate
     * @param obj1 an object
     * @param obj2 an object
     * @param obj3 an object
     */
    public Prerequisite prereq(Predicate predicate, Object obj1, Object obj2, Object obj3) {
        
        return prereq(predicate,obj1,obj2,obj3,false);
    }

    /**
     * Create a prerequisite with four terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the prerequisite created
     * @param predicate the predicate
     * @param obj1 an object
     * @param obj2 an object
     * @param obj3 an object
     * @param obj4 an object
     */
    public Prerequisite prereq(Predicate predicate, Object obj1, Object obj2,Object obj3, Object obj4) {
        
        return prereq(predicate,obj1,obj2,obj3,obj4,false);
    }
    

///

    /**
     * Create a prerequisite.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the prerequisite created
     * @param predicate the predicate
     * @param objs objects (will be interpreted as terms)
     * @param negatedAF whether the prerequisite is negated (using negation as failure)
     */
    public Prerequisite prereq(Predicate predicate, Object[] objs,boolean negatedAF) {
        Class[] structure = predicate.getStructure ();

        if(structure.length != objs.length) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this predicate, the number is "
                + objs.length + ", but must be " + structure.length);
        }

        Term[] terms = new Term[structure.length];

        for(int i = 0; i < structure.length; i++) {
            terms[i] = toTerm (objs[i], structure[i]);
        }

        return lfactory.createPrerequisite (predicate, terms,negatedAF);
    }

    /**
     * Create a prerequisite with one term.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the prerequisite created
     * @param predicate the predicate
     * @param obj an object
     * @param negatedAF whether the prerequisite is negated (using negation as failure)
     */
    public Prerequisite prereq(Predicate predicate, Object obj,boolean negatedAF) {
        Class[] structure = predicate.getStructure ();

        if(structure.length != 1) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this predicate, the number is 1, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj, structure[0]) };

        return lfactory.createPrerequisite (predicate, terms,negatedAF);
    }

    /**
     * Create a prerequisite with two terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the prerequisite created
     * @param predicate the predicate
     * @param obj1 an object
     * @param obj2 an object
     * @param negatedAF whether the prerequisite is negated (using negation as failure)
     */
    public Prerequisite prereq(Predicate predicate, Object obj1, Object obj2,boolean negatedAF) {
        Class[] structure = predicate.getStructure ();

        if(structure.length != 2) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this predicate, the number is 2, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj1, structure[0]),
                         toTerm (obj2, structure[1]) };

        return lfactory.createPrerequisite (predicate, terms,negatedAF);
    }

    /**
     * Create a prerequisite with three terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the prerequisite created
     * @param predicate the predicate
     * @param obj1 an object
     * @param obj2 an object
     * @param obj3 an object
     * @param negatedAF whether the prerequisite is negated (using negation as failure)
     */
    public Prerequisite prereq(Predicate predicate, Object obj1, Object obj2, Object obj3,boolean negatedAF) {
        Class[] structure = predicate.getStructure ();

        if(structure.length != 3) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this predicate, the number is 3, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj1, structure[0]),
                         toTerm (obj2, structure[1]),
                         toTerm (obj3, structure[2]) };

        return lfactory.createPrerequisite (predicate, terms,negatedAF);
    }

    /**
     * Create a prerequisite with four terms.
     * See <code>toTerm</code> how the object is converted to a term.
     * @return the prerequisite created
     * @param predicate the predicate
     * @param obj1 an object
     * @param obj2 an object
     * @param obj3 an object
     * @param obj4 an object
     * @param negatedAF whether the prerequisite is negated (using negation as failure)
     */
    public Prerequisite prereq(Predicate predicate, Object obj1, Object obj2,Object obj3, Object obj4,boolean negatedAF) {
        Class[] structure = predicate.getStructure ();

        if(structure.length != 4) {
            throw new IllegalArgumentException (
                "Not the right number of terms for this predicate, the number is 4, but must be "
                + structure.length);
        }

        Term[] terms = { toTerm (obj1, structure[0]),
                         toTerm (obj2, structure[1]),
                         toTerm (obj3, structure[2]),
                         toTerm (obj4, structure[3]) };

        return lfactory.createPrerequisite (predicate, terms,negatedAF);
    } 

    /**
     * Create a rule with two prerequisites.
     * The prerequisites are connected by OR.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param conclusion the concusion of the rule
     * @deprecated use Prerequisite instead of Fact to build rules
     */
    public Rule orRule(Fact prerequisite1, Fact prerequisite2,Fact conclusion) {
        Vector body = new Vector ();
        body.add (fact2prereq(prerequisite1));
        body.add (fact2prereq(prerequisite2));
        return lfactory.createRule (body, conclusion, true);
    }

    /**
     * Create a rule with three prerequisites.
     * The prerequisites are connected by OR.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param prerequisite3 a prerequisite
     * @param conclusion the concusion of the rule
     * @deprecated use Prerequisite instead of Fact to build rules
     */
    public Rule orRule(Fact prerequisite1, Fact prerequisite2,Fact prerequisite3, Fact conclusion) {
        Vector body = new Vector ();
        body.add (fact2prereq(prerequisite1));
        body.add (fact2prereq(prerequisite2));
        body.add (fact2prereq(prerequisite3));
        return lfactory.createRule (body, conclusion, true);
    }

    /**
     * Create a rule with four prerequisites.
     * The prerequisites are connected by OR.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param prerequisite3 a prerequisite
     * @param prerequisite4 a prerequisite
     * @param conclusion the concusion of the rule
     * @deprecated use Prerequisite instead of Fact to build rules
     */
    public Rule orRule(Fact prerequisite1, Fact prerequisite2,Fact prerequisite3, Fact prerequisite4,Fact conclusion) {
        Vector body = new Vector ();
        body.add (fact2prereq(prerequisite1));
        body.add (fact2prereq(prerequisite2));
        body.add (fact2prereq(prerequisite3));
        body.add (fact2prereq(prerequisite4));
        return lfactory.createRule (body, conclusion, true);
    }

    /**
     * Create a rule.
     * @return the rule created
     * @param body the prerequisites of the rule
     * @param conclusion the concusion of the rule
     */
    public Rule rule(List body, Fact conclusion) {
        return lfactory.createRule (body, conclusion);
    }

    /**
     * Create a rule with no prerequisites.
     * @return the rule created
     * @param conclusion the concusion of the rule
     */
    public Rule rule(Fact conclusion) {
        Vector body = new Vector ();
        return lfactory.createRule (body, conclusion);
    }

    /**
     * Create a rule with one prerequisite.
     * @return the rule created
     * @param prerequisite a prerequisite
     * @param conclusion the concusion of the rule
     * @deprecated use Prerequisite instead of Fact to build rules
     */
    public Rule rule(Fact prerequisite, Fact conclusion) {
        Vector body = new Vector ();
        body.add (fact2prereq(prerequisite));
        return lfactory.createRule (body, conclusion);
    }

    /**
     * Create a rule with two prerequisites.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param conclusion the concusion of the rule
     * @deprecated use Prerequisite instead of Fact to build rules
     */
    public Rule rule(Fact prerequisite1, Fact prerequisite2,Fact conclusion) {
        Vector body = new Vector ();
        body.add (fact2prereq(prerequisite1));
        body.add (fact2prereq(prerequisite2));
        return lfactory.createRule (body, conclusion);
    }

    /**
     * Create a rule with three prerequisites.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param prerequisite3 a prerequisite
     * @param conclusion the concusion of the rule
     * @deprecated use Prerequisite instead of Fact to build rules
     */
    public Rule rule(Fact prerequisite1, Fact prerequisite2,Fact prerequisite3, Fact conclusion) {
        Vector body = new Vector ();
        body.add (fact2prereq(prerequisite1));
        body.add (fact2prereq(prerequisite2));
        body.add (fact2prereq(prerequisite3));
        return lfactory.createRule (body, conclusion);
    }

    /**
     * Create a rule with four prerequisites.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param prerequisite3 a prerequisite
     * @param prerequisite4 a prerequisite
     * @param conclusion the concusion of the rule
     * @deprecated use Prerequisite instead of Fact to build rules
     */
    public Rule rule(Fact prerequisite1, Fact prerequisite2,Fact prerequisite3, Fact prerequisite4,Fact conclusion) {
        Vector body = new Vector ();
        body.add (fact2prereq(prerequisite1));
        body.add (fact2prereq(prerequisite2));
        body.add (fact2prereq(prerequisite3));
        body.add (fact2prereq(prerequisite4));
        return lfactory.createRule (body, conclusion);
    }


    /**
     * Create a rule with two prerequisites.
     * The prerequisites are connected by OR.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param conclusion the concusion of the rule
     */
    public Rule orRule(Prerequisite prerequisite1, Prerequisite prerequisite2,Fact conclusion) {
        Vector body = new Vector ();
        body.add (prerequisite1);
        body.add (prerequisite2);
        return lfactory.createRule (body, conclusion, true);
    }

    /**
     * Create a rule with three prerequisites.
     * The prerequisites are connected by OR.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param prerequisite3 a prerequisite
     * @param conclusion the concusion of the rule
     */
    public Rule orRule(Prerequisite prerequisite1, Prerequisite prerequisite2,Prerequisite prerequisite3, Fact conclusion) {
        Vector body = new Vector ();
        body.add (prerequisite1);
        body.add (prerequisite2);
        body.add (prerequisite3);
        return lfactory.createRule (body, conclusion, true);
    }

    /**
     * Create a rule with four prerequisites.
     * The prerequisites are connected by OR.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param prerequisite3 a prerequisite
     * @param prerequisite4 a prerequisite
     * @param conclusion the concusion of the rule
     */
    public Rule orRule(Prerequisite prerequisite1, Prerequisite prerequisite2,Prerequisite prerequisite3, Prerequisite prerequisite4,Fact conclusion) {
        Vector body = new Vector ();
        body.add (prerequisite1);
        body.add (prerequisite2);
        body.add (prerequisite3);
        body.add (prerequisite4);
        return lfactory.createRule (body, conclusion, true);
    }

    /**
     * Create a rule with one prerequisite.
     * @return the rule created
     * @param prerequisite a prerequisite
     * @param conclusion the concusion of the rule
     */
    public Rule rule(Prerequisite prerequisite, Fact conclusion) {
        Vector body = new Vector ();
        body.add (prerequisite);
        return lfactory.createRule (body, conclusion);
    }

    /**
     * Create a rule with two prerequisites.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param conclusion the concusion of the rule
     */
    public Rule rule(Prerequisite prerequisite1, Prerequisite prerequisite2,Fact conclusion) {
        Vector body = new Vector ();
        body.add (prerequisite1);
        body.add (prerequisite2);
        return lfactory.createRule (body, conclusion);
    }

    /**
     * Create a rule with three prerequisites.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param prerequisite3 a prerequisite
     * @param conclusion the concusion of the rule
     */
    public Rule rule(Prerequisite prerequisite1, Prerequisite prerequisite2,Prerequisite prerequisite3, Fact conclusion) {
        Vector body = new Vector ();
        body.add (prerequisite1);
        body.add (prerequisite2);
        body.add (prerequisite3);
        return lfactory.createRule (body, conclusion);
    }

    /**
     * Create a rule with four prerequisites.
     * @return the rule created
     * @param prerequisite1 a prerequisite
     * @param prerequisite2 a prerequisite
     * @param prerequisite3 a prerequisite
     * @param prerequisite4 a prerequisite
     * @param conclusion the concusion of the rule
     */
    public Rule rule(Prerequisite prerequisite1, Prerequisite prerequisite2,Prerequisite prerequisite3, Prerequisite prerequisite4,Fact conclusion) {
        Vector body = new Vector ();
        body.add (prerequisite1);
        body.add (prerequisite2);
        body.add (prerequisite3);
        body.add (prerequisite4);
        return lfactory.createRule (body, conclusion);
    }
    
    
    /**
     * Convenient method to interprete objects as terms.
     * The following rules apply:
     * <ol>
     * <li> if the object is a term, keep it as it is
     * <li> if the object is an instance of clazz, create a constant term wrapping the object
     * <li> if the object is a string (an the previous does not apply), create a variable using the object as a name
     * <li> otherwise throw an illegal argument exception;
     * </ol>
     * @return a term
     * @param obj the object to be interpreted as a term
     * @param clazz the type of the term
     */
    private Term toTerm(Object obj, Class clazz) {
        if(obj == null) {
            throw new IllegalArgumentException (
                "Cannot build term from null");
        }

        if(obj instanceof Term) {
            return(Term) obj;
        }
		// remark: this was a bug in 1.6 : if (clazz==obj.getClass())
        if(clazz.isAssignableFrom(obj.getClass())) {
            return lfactory.createConstantTerm (obj);
        }

        if(obj instanceof String) {
            return lfactory.createVariableTerm ((String) obj, clazz);
        }

        throw new IllegalArgumentException ("Cannot build term from " + obj);
    }

    /**
     * Convenient method to create a variable.
     * @return a term
     * @param name a var name
     * @param clazz a type
     */
    public Term variable(String name, Class clazz) {
        return lfactory.createVariableTerm (name, clazz);
    }

    /**
     * Convenient method to create a string type variable.
     * @return a term
     * @param name a var name
     */
    public Term variable(String name) {
        return variable (name, String.class);
    }
    
    /**
     * Create a query with one fact.
     * @return the query created
     * @param fact a fact
     * @param name the name of the query
     */
    public Query query(Fact fact,String name) {
    	Fact[] facts = {fact};
    	return query(facts,name);
    }
    
    /**
     * Create a query with two facts.
     * @return the query created
     * @param fact1 a fact
     * @param fact2 a fact
     * @param name the name of the query
     */
    public Query query(Fact fact1,Fact fact2,String name) {
    	Fact[] facts = {fact1,fact2};
    	return query(facts,name);
    }
    
    /**
     * Create a query with three facts.
     * @return the query created
     * @param fact1 a fact
     * @param fact2 a fact
     * @param fact3 a fact
     * @param name the name of the query
     */
    public Query query(Fact fact1,Fact fact2,Fact fact3,String name) {
    	Fact[] facts = {fact1,fact2,fact3};
    	return query(facts,name);
    }
    
    /**
     * Create a query with N facts.
     * @return the query created
     * @param fact1 a fact
     * @param fact2 a fact
     * @param name the name of the query
     */
    public Query query(Fact[] facts,String name) {
    	return lfactory.createQuery(facts,name);
    }            
    
    /** 
     * Convert a fact to a prerequisite.
     * @param fact a fact
     * @return a prerequisite
     */ 
    public Prerequisite fact2prereq(Fact fact) {
    	Predicate p = fact.getPredicate();
    	Term[] terms = fact.getTerms();
    	return this.prereq(p,terms);
    }
    /**
     * Create a prerequiste using the cut predicate.
     * @return a prerequisite
     */
    public Prerequisite cut() {
    	return lfactory.createCut();
    }
    
}
