/*
* Created on Feb 2, 2004 To change the template for this generated file go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
package org.jactr.core.production.condition;
import java.util.Collection;
import java.util.Collections;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.model.IModel;
import org.jactr.core.production.VariableBindings;
import org.jactr.core.production.bindings.VariableBindingsFactory;
import org.jactr.core.production.condition.match.ExceptionMatchFailure;
import org.jactr.core.production.condition.match.IMatchFailure;
import org.jactr.core.production.request.SlotBasedRequest;
import org.jactr.core.slot.ISlot;
import org.jactr.core.slot.ISlotContainer;
/**
* proxy condition that wraps a class that implements {@link ICondition}. This
* allows one to use arbitrary conditions in a model without futzing with the
* parsers. If the delegate {@link ICondition} is also an {@link ISlotContainer}
* , the slots added to this proxy will be added to the delegate instead and the
* delegate will be responsible for the variable resolution. If the delegate is
* not an {@link ISlotContainer}, it will have to query the variable bindings
* for the slot values.
*/
public class ProxyCondition extends AbstractSlotCondition
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(ProxyCondition.class);
String _className;
ICondition _delegateCondition;
public ProxyCondition(String className) throws ClassNotFoundException,
InstantiationException, IllegalAccessException
{
this(className, Collections.EMPTY_LIST);
}
public ProxyCondition(String className, Collection<? extends ISlot> slots)
throws ClassNotFoundException, InstantiationException,
IllegalAccessException
{
super();
setDelegateClassName(className);
setRequest(new SlotBasedRequest());
for (ISlot slot : slots)
addSlot(slot);
}
public ProxyCondition(Class<? extends ICondition> proxyClass,
Collection<? extends ISlot> slots) throws InstantiationException,
IllegalAccessException
{
super();
setDelegateClass(proxyClass);
setRequest(new SlotBasedRequest());
for (ISlot slot : slots)
addSlot(slot);
}
protected ProxyCondition(ICondition delegate,
Collection<? extends ISlot> slots)
{
super();
_delegateCondition = delegate;
_className = delegate.getClass().getName();
setRequest(new SlotBasedRequest());
for (ISlot slot : slots)
addSlot(slot);
}
public ICondition getDelegate()
{
return _delegateCondition;
}
public String getDelegateClassName()
{
return _className;
}
@SuppressWarnings("unchecked")
public void setDelegateClassName(String name) throws ClassNotFoundException,
InstantiationException, IllegalAccessException
{
Class<? extends ICondition> tmpClass = (Class<? extends ICondition>) getClass()
.getClassLoader().loadClass(name);
setDelegateClass(tmpClass);
}
public void setDelegateClass(Class<? extends ICondition> proxyClass)
throws InstantiationException, IllegalAccessException
{
_delegateCondition = proxyClass.newInstance();
_className = proxyClass.getName();
}
/**
* route to delegate if it implements {@link ISlotContainer}
*
* @param slot
* @see org.jactr.core.production.condition.AbstractSlotCondition#addSlot(org.jactr.core.slot.ISlot)
*/
@Override
public void addSlot(ISlot slot)
{
if (_delegateCondition instanceof ISlotContainer)
((ISlotContainer) _delegateCondition).addSlot(slot);
else
super.addSlot(slot);
}
@Override
public void removeSlot(ISlot slot)
{
if (_delegateCondition instanceof ISlotContainer)
((ISlotContainer) _delegateCondition).removeSlot(slot);
else
super.removeSlot(slot);
}
public ProxyCondition clone(IModel model, VariableBindings variableBindings)
throws CannotMatchException
{
try
{
return new ProxyCondition(_delegateCondition.clone(model,
variableBindings), getRequest().getSlots());
}
catch (CannotMatchException cme)
{
cme.getMismatch().setCondition(this);
throw cme;
}
catch (Exception e)
{
throw new CannotMatchException(new ExceptionMatchFailure(this,
_delegateCondition.getClass().getName(), e));
}
}
public int bind(IModel model, VariableBindings variableBindings,
boolean iterativeCall) throws CannotMatchException
{
int unresolved = 0;
try
{
unresolved = getRequest().bind(model, variableBindings, iterativeCall);
}
catch (CannotMatchException cme)
{
cme.getMismatch().setCondition(this);
throw cme;
}
VariableBindings expandedBindings = null;
boolean canRecycleBindings = false;
/*
* if the delegate doesn't have slots of its own, we provide them as
* expanded bindings, but this means it is a read only, no setting of
* variables..
*/
if (_delegateCondition instanceof ISlotContainer)
expandedBindings = variableBindings;
else
{
expandedBindings = VariableBindingsFactory.newInstance();
expandedBindings.copy(variableBindings);
canRecycleBindings = true;
for (ISlot slot : getSlots())
{
expandedBindings.bind(slot.getName(), slot.getValue());
expandedBindings.bind("=" + slot.getName(), slot.getValue());
}
}
try
{
unresolved = Math.max(unresolved,
_delegateCondition.bind(model, expandedBindings, iterativeCall));
return unresolved;
}
catch (CannotMatchException cme)
{
IMatchFailure mf = cme.getMismatch();
if (mf != null) mf.setCondition(this);
throw cme;
}
catch (Exception e)
{
throw new CannotMatchException(new ExceptionMatchFailure(this,
_delegateCondition.getClass().getName(), e));
}
finally
{
if (canRecycleBindings)
VariableBindingsFactory.recycle(expandedBindings);
}
}
}