📄 abstractclauseset.java
字号:
/*
* Copyright (C) 1999-2004 <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">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.kernel.meta;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import org.apache.commons.collections.iterators.SingletonIterator;
import org.mandarax.kernel.AbstractPropertiesSupport;
import org.mandarax.kernel.CachedClauseSet;
import org.mandarax.kernel.Clause;
import org.mandarax.kernel.ClauseSetChangeEvent;
import org.mandarax.kernel.ClauseSetChangeListener;
import org.mandarax.kernel.ConstantTerm;
import org.mandarax.kernel.Fact;
import org.mandarax.kernel.LogicFactory;
/**
* Abstract clause set based on the reflect mechanism. The idea is to consider java methods with a boolean
* return type as predicates and to analyse objects in order to build facts for tupels of objects
* where the invokation of the method with these obects as parameter yields true.
* Note that there is a boolean property to enable a cache mechanism. If the cache is switched off
* (the default), any call to <code>clauses()</code> builds a new clause iterator and therefore may
* perform a new fetch operation. Otherwise the result
* is stored and the clause set will not note further changes in the object model.
* There is also a flag to negate the clause set. If this flag is false (the default), a fact
* is built from the objects where invokation of the method (the JPredicate) returns <code>true</code>.
* If the set is negated, then a fact is built from objects where the invokation returns <code>false</code>;
* @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
* @version 3.4 <7 March 05>
* @since 1.0
* @todo replace clauses(Clauses,Object) ! parameters are only passed with the constructor in the subclass!!
* @version 3.4 <7 March 05>
*/
abstract class AbstractClauseSet extends AbstractPropertiesSupport implements CachedClauseSet {
protected boolean cacheEnabled = false;
protected Method method = null;
protected JPredicate predicate = null;
protected Collection cache = null;
protected boolean negated = false;
protected transient Vector clauseSetChangeListener = new Vector ();
/**
* Constructor.
*/
protected AbstractClauseSet() {
super ();
}
/**
* Constructor.
* @param isNegated true if the set should be negated, false otherwise
*/
protected AbstractClauseSet(boolean isNegated) {
this ();
negated = isNegated;
}
/**
* Add a clause set listener.
* @param l a listener
*/
public void addClauseSetChangeListener(ClauseSetChangeListener l) {
clauseSetChangeListener.add (l);
}
/**
* Build a fact.
* @return a fact
* @param target the object receiving the metod call
* @param parameters the parameters of the method call
*/
protected Clause buildFact(Object target, Object[] parameters) {
try {
LogicFactory logicFactory = LogicFactory.getDefaultFactory ();
Object result = method.invoke (target, parameters);
if(((Boolean) result).booleanValue () != negated) {
// build terms
ConstantTerm[] terms =
new ConstantTerm[parameters.length + 1];
terms[0] = logicFactory.createConstantTerm (target);
for(int i = 0; i < parameters.length; i++) {
terms[i + 1] =
logicFactory.createConstantTerm (parameters[i]);
}
// build and return the fact
Fact aFact = logicFactory.createFact (predicate, terms);
return aFact;
}
} catch(Throwable t) {
System.err.println ("Error building fact: " + t.getMessage ());
}
return null;
}
/**
* Build the collection of facts.
* @return a collection of facts
*/
protected abstract Collection buildFacts();
/**
* Check the method.
* @param aMethod a method
* @throws java.lang.IllegalAccessException Thrown if the return type of the method is not boolean or if the number of parameters does not equal 1.
* @throws java.lang.IllegalArgumentException Thrown if the method is not public.
*/
protected void checkMethod(Method aMethod)
throws NullPointerException, IllegalAccessException,
IllegalArgumentException {
if(aMethod.getParameterTypes ().length != 1) {
throw new IllegalArgumentException (
"The number of parameter sets does not fit");
}
if( !Modifier.isPublic (aMethod.getModifiers ())) {
throw new IllegalAccessException ("Public method expected");
}
if(aMethod.getReturnType () != Boolean.TYPE) {
throw new IllegalArgumentException (
"Method returning a boolean expected");
}
}
/**
* Get an iterator for clauses.
* @return a clause iterator
*/
public org.mandarax.util.ClauseIterator clauses() {
Collection coll = null;
if(isCacheEnabled ()) {
if(cache == null) {
cache = buildFacts ();
}
coll = cache;
} else {
coll = buildFacts ();
}
return new org.mandarax.util.SingleClauseSetIterator (coll);
}
/**
* Get an iterator for clauses. The parameters are ignored and <code>clauses()</code> is called!
* @return a clause iterator
* @param query the query clause
* @param additionalParameter an additional parameter
*/
public org.mandarax.util.ClauseIterator clauses(Clause query,
Object additionalParameter) {
return clauses ();
}
/**
* Fire a clause set change event
* @param e an event
*/
protected void fireClauseSetChangeEvent(ClauseSetChangeEvent e) {
ClauseSetChangeListener l;
for(Iterator it =
clauseSetChangeListener.iterator (); it.hasNext (); ) {
l = (ClauseSetChangeListener) it.next ();
l.clauseSetChanged (e);
}
}
/**
* Get a key for indexing. Here this is the predicate shared by all clauses in the set.
* @return the key object
*/
public Object getKey() {
return predicate;
}
/**
* Validate the parameters provided to set up the set.
* @param aMethod the method to be evaluated
* @throws java.lang.IllegalAccessException Thrown if the method is not public.
* @throws java.lang.IllegalArgumentException Thrown if the return type of the method is not boolean or if the number of argument sets does not match.
* @throws java.lang.NullPointerException Thrown if one of the arguments is null.
*/
protected void initialize(Method aMethod)
throws NullPointerException, IllegalAccessException,
IllegalArgumentException {
checkMethod (aMethod);
method = aMethod;
predicate = new JPredicate (aMethod, negated);
}
/**
* Validate the parameters provided to set up the set.
* @param aPredicate the JPredicate
* @throws java.lang.IllegalAccessException Thrown if the underlying method is not public.
* @throws java.lang.IllegalArgumentException Thrown if the return type of the underlying method is not boolean or if the number of argument sets does not match.
* @throws java.lang.NullPointerException Thrown if one of the arguments is null.
*/
protected void initialize(JPredicate aPredicate)
throws NullPointerException, IllegalAccessException,
IllegalArgumentException {
checkMethod (aPredicate.getMethod ());
method = aPredicate.getMethod ();
predicate = aPredicate;
}
/**
* Indicates whether the cache is enabled.
* @return true if the cache is enabled, false otherwise
*/
public boolean isCacheEnabled() {
return cacheEnabled;
}
/**
* Remove a clause set listener.
* @param l a listener
*/
public void removeClauseSetChangeListener(ClauseSetChangeListener l) {
clauseSetChangeListener.remove (l);
}
/**
* Reset the set. In particular, this includes cleaning the cache.
*/
public void reset() {
cache = null;
}
/**
* Enable / disable the cache property.
* @param flag true if the cache should be enabled and false if the cache should be disabled
*/
public void setCacheEnabled(boolean flag) {
cacheEnabled = flag;
}
/**
* Convert the object to a string.
* @return the string representation of this object
*/
public String toString() {
return predicate.toString () + " - facts";
}
/**
* Get an iterator iterating over the predicates contained in this clause set.
* @return an iterator
*/
public Iterator predicates() {
return new SingletonIterator(predicate);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -