package org.mandarax.reference;

/*
 * 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
 */
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;
import org.mandarax.kernel.VariableTerm;
import org.mandarax.lib.Cut;

/**
 * Factory object for creating logical entities objects.
 * The classes with the postfix <it>Impl</it> should never be instanciated
 * directly. Instead use instances of this class. To use alternative
 * implementations, subclass this class. <br> To install an instance of this
 * class to be the default factory use the following code:
 * <code>(new DefaultLogicFactory()).install()</code>. If this is done, a
 * reference to the factory can be obtained using
 * <code>LogicFactory.getDefaultFactory()</code>.
 * <br>
 * As from 1.9, queries are supported.
 * @author <A HREF="mailto:mandarax@jbdietrich.com">Jens Dietrich</A>
 * @version 3.3.1 <9 August 2004>
 * @since 1.1
 */
public class DefaultLogicFactory extends LogicFactory {
	private Prerequisite cut = null;
	/**
	 * Constructor.
	 */
	public DefaultLogicFactory() {
		super ();
	}
	/**
	 * Create a new complex term.
	 * @return the created complex term
	 * @param anFunction a function
	 * @param terms an array of terms
	 */
	public ComplexTerm createComplexTerm(Function anFunction, Term[] terms) {
		return new ComplexTermImpl (anFunction, terms);
	}
	/**
	 * Create a new constant term.
	 * @return the created constant term
	 * @param obj the object that is to be wrapped by the constant term
	 */
	public ConstantTerm createConstantTerm(Object obj) {
		return new ConstantTermImpl (obj);
	}
	/**
	 * Create a new constant term.
	 * @return a new constant term
	 * @param obj the wrapped object
	 * @param type the type of the object
	 * @throws throws an IllegalArgumentException if object and type are inconsistent,
	 * i.e. if type object is not an instance of type
	 */
	public ConstantTerm createConstantTerm(Object obj, Class type) {
		return new ConstantTermImpl (obj, type);
	}
	/**
	 * Create a new fact.
	 * @return the created fact
	 * @param aPredicate the predicate
	 * @param terms the terms
	 */
	public Fact createFact(Predicate aPredicate, Term[] terms) {
		return new FactImpl (aPredicate, terms);
	}
    /**
     * Create a new prerequisite.
     * @return a new prerequisite
     * @param aPredicate a predicate
     * @param terms an array of terms
     * @param negatedAF whether the prerequisite is negated (as failure)
     */
    public Prerequisite createPrerequisite(Predicate aPredicate, Term[] terms, boolean negatedAF) {
    	return new PrerequisiteImpl(aPredicate,terms,negatedAF);
    }
    /**
     * Create a cut prerequisite.
     * @return a prerequisite
     */
    public Prerequisite createCut() {
		 // 2.2: Each cut has to be a unique instance
//    	if (cut==null) {
    		cut = new PrerequisiteImpl(new Cut(),new Term[]{},false) {
			    /**
				 * Indicates whether the prerequisite is negated (negation as failure)
				 * @return true if the prerequisite is negated, false otherwise
				 */
				public boolean isNegatedAF() {
					return false;
				}
				/**
				 * Set the negated (as failure) flag.
				 * @param value true or false
				 */
				public void setNegatedAF(boolean value) {
					// ignored
				}
    		};
//    	}
    	return cut;
    }
	/**
	 * Create a new rule.
	 * @return the created rule
	 * @param body a list of facts that will become the body of the rule
	 * @param head a fact that will become the head of the rule
	 */
	public Rule createRule(java.util.List body, Fact head) {
		return new RuleImpl (body, head);
	}
	/**
	 * Create a new rule.
	 * @return a new rule
	 * @param body a list facts becoming the body of the rules
	 * @param head the head of the rule
	 * @param or indicates whether the prerequisites are connected by OR
	 */
	public Rule createRule(java.util.List body, Fact head, boolean or) {
		return new RuleImpl (body, head, or);
	}
	/**
	 * Create a new rule with an empty body.
	 * @return the created rule
	 * @param head the fact that will become the head of the rule
	 */
	public Rule createRule(Fact head) {
		return createRule (new java.util.ArrayList(), head);
	}
	/**
	 * Create a new variable term.
	 * @return the created variable term
	 * @param aName the name of the variable
	 * @param aType the type of the variable
	 */
	public VariableTerm createVariableTerm(String aName, Class aType) {
		return new VariableTermImpl (aName, aType);
	}
	/**
     * Create a new query.
     * @return a new query
     * @param fact aFact
     * @param name the name of the query
     */
    public Query createQuery(Fact fact,String name) {
    	Fact[] facts = {fact};
    	return createQuery(facts,name);
    }
    /**
     * Create a new query.
     * @return a new query
     * @param facts an array of facts
     * @param name the name of the query
     */
    public Query createQuery(Fact[] facts,String name) {
    	return new QueryImpl(facts,name);
    }
	/**
	 * Return the implementation class for facts. 
	 * @return a class
	 */
	public Class getFactImplementationClass() {
		return FactImpl.class;
	}
	/**
	 * Return the implementation class for rules. 
	 * @return a class
	 */
	public Class getRuleImplementationClass() {
		return RuleImpl.class;
	}
	/**
	 * Return the implementation class for prerequisites. 
	 * @return a class
	 */
	public Class getPrerequisiteImplementationClass(){
		return PrerequisiteImpl.class;
	}
	/**
	 * Return the implementation class for queries. 
	 * @return a class
	 */
	public Class getQueryImplementationClass(){
		return QueryImpl.class;
	}
	/**
	 * Return the implementation class for constant terms. 
	 * @return a class
	 */
	public Class getConstantTermImplementationClass() {
		return ConstantTermImpl.class;
	}
	/**
	 * Return the implementation class for variable terms. 
	 * @return a class
	 */
	public Class getVariableTermImplementationClass() {
		return VariableTermImpl.class;
	}
	/**
	 * Return the implementation class for complex terms. 
	 * @return a class
	 */
	public Class getComplexTermImplementationClass() {
		return ComplexTermImpl.class;
	}
}
