package jadex.bdi.runtime.impl.flyweights;
import jadex.bdi.model.IMElement;
import jadex.bdi.model.OAVBDIMetaModel;
import jadex.bdi.model.impl.flyweights.MParameterSetFlyweight;
import jadex.bdi.runtime.IParameterSet;
import jadex.bdi.runtime.interpreter.BDIInterpreter;
import jadex.bdi.runtime.interpreter.BeliefRules;
import jadex.bdi.runtime.interpreter.MessageEventRules;
import jadex.bdi.runtime.interpreter.OAVBDIRuntimeModel;
import jadex.bridge.MessageType;
import jadex.bridge.MessageType.ParameterSpecification;
import jadex.commons.SReflect;
import jadex.commons.Tuple;
import jadex.rules.state.IOAVState;
import java.lang.reflect.Array;
import java.util.Collection;
/**
* Flyweight for a parameter set on instance level.
*/
public class ParameterSetFlyweight extends ElementFlyweight implements IParameterSet
{
//-------- attributes --------
/** Parameter name. */
// Used only when handle is null, because no parameter value stored in state, yet.
protected String name;
/** Parameter element handle. */
protected Object pe;
//-------- constructors --------
/**
* Create a new parameter flyweight.
* @param state The state.
* @param scope The scope handle.
* @param handle The parameter handle (or null if no value yet).
* @param name The parameter name (used, if no value yet).
* @param pe The handle for the parameter element to which this parameter belongs.
*/
private ParameterSetFlyweight(IOAVState state, Object scope, Object handle, String name, Object pe)
{
super(state, scope, handle);
this.name = name;
this.pe = pe;
}
/**
* Get or create a flyweight.
* @return The flyweight.
*/
public static ParameterSetFlyweight getParameterSetFlyweight(IOAVState state, Object scope, Object handle, String name, Object parameterelement)
{
BDIInterpreter ip = BDIInterpreter.getInterpreter(state);
ParameterSetFlyweight ret = (ParameterSetFlyweight)ip.getFlyweightCache(IParameterSet.class, new Tuple(IParameterSet.class, parameterelement, name));
if(ret==null)
{
ret = new ParameterSetFlyweight(state, scope, handle, name, parameterelement);
ip.putFlyweightCache(IParameterSet.class, new Tuple(IParameterSet.class, parameterelement, name), ret);
}
return ret;
}
//-------- IParameter interface --------
/**
* Add a value to a parameter set.
* @param value The new value.
*/
public void addValue(final Object value)
{
if(getInterpreter().isExternalThread())
{
new AgentInvocation()
{
public void run()
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
if(!hasHandle())
{
Object mparamelem = getState().getAttributeValue(pe, OAVBDIRuntimeModel.element_has_model);
Object mparamset = getState().getAttributeValue(mparamelem, OAVBDIMetaModel.parameterelement_has_parametersets, name);
setHandle(BeliefRules.createParameterSet(getState(), name, null, resolveClazz(), pe, mparamset, getScope()));
}
String direction = resolveDirection();
if(OAVBDIMetaModel.PARAMETER_DIRECTION_FIXED.equals(direction)
|| OAVBDIMetaModel.PARAMETER_DIRECTION_IN.equals(direction) && ParameterFlyweight.inprocess(getState(), pe, getScope())
|| OAVBDIMetaModel.PARAMETER_DIRECTION_OUT.equals(direction) && !ParameterFlyweight.inprocess(getState(), pe, getScope()))
throw new RuntimeException("Write access not allowed to parameter set: "
+direction+" "+getName());
BeliefRules.addParameterSetValue(getState(), getHandle(), value);
}
};
}
else
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
if(!hasHandle())
{
Object mparamelem = getState().getAttributeValue(pe, OAVBDIRuntimeModel.element_has_model);
Object mparamset = getState().getAttributeValue(mparamelem, OAVBDIMetaModel.parameterelement_has_parametersets, name);
setHandle(BeliefRules.createParameterSet(getState(), name, null, resolveClazz(), pe, mparamset, getScope()));
}
String direction = resolveDirection();
if(OAVBDIMetaModel.PARAMETER_DIRECTION_FIXED.equals(direction)
|| OAVBDIMetaModel.PARAMETER_DIRECTION_IN.equals(direction) && ParameterFlyweight.inprocess(getState(), pe, getScope())
|| OAVBDIMetaModel.PARAMETER_DIRECTION_OUT.equals(direction) && !ParameterFlyweight.inprocess(getState(), pe, getScope()))
throw new RuntimeException("Write access not allowed to parameter set: "
+direction+" "+getName());
getInterpreter().startMonitorConsequences();
BeliefRules.addParameterSetValue(getState(), getHandle(), value);
getInterpreter().endMonitorConsequences();
}
}
/**
* Remove a value to a parameter set.
* @param value The new value.
*/
public void removeValue(final Object value)
{
if(getInterpreter().isExternalThread())
{
new AgentInvocation()
{
public void run()
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
String direction = resolveDirection();
if(OAVBDIMetaModel.PARAMETER_DIRECTION_FIXED.equals(direction)
|| OAVBDIMetaModel.PARAMETER_DIRECTION_IN.equals(direction) && ParameterFlyweight.inprocess(getState(), pe, getScope())
|| OAVBDIMetaModel.PARAMETER_DIRECTION_OUT.equals(direction) && !ParameterFlyweight.inprocess(getState(), pe, getScope()))
throw new RuntimeException("Write access not allowed to parameter set: "
+direction+" "+getName());
if(!hasHandle())
throw new RuntimeException("Value not contained: "+value);
BeliefRules.removeParameterSetValue(getState(), getHandle(), value);
}
};
}
else
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
String direction = resolveDirection();
if(OAVBDIMetaModel.PARAMETER_DIRECTION_FIXED.equals(direction)
|| OAVBDIMetaModel.PARAMETER_DIRECTION_IN.equals(direction) && ParameterFlyweight.inprocess(getState(), pe, getScope())
|| OAVBDIMetaModel.PARAMETER_DIRECTION_OUT.equals(direction) && !ParameterFlyweight.inprocess(getState(), pe, getScope()))
throw new RuntimeException("Write access not allowed to parameter set: "
+direction+" "+getName());
if(!hasHandle())
throw new RuntimeException("Value not contained: "+value);
getInterpreter().startMonitorConsequences();
BeliefRules.removeParameterSetValue(getState(), getHandle(), value);
getInterpreter().endMonitorConsequences();
}
}
/**
* Add values to a parameter set.
*/
public void addValues(final Object[] values)
{
if(values==null)
return;
if(getInterpreter().isExternalThread())
{
new AgentInvocation()
{
public void run()
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
if(!hasHandle())
{
Object mparamelem = getState().getAttributeValue(pe, OAVBDIRuntimeModel.element_has_model);
Object mparamset = getState().getAttributeValue(mparamelem, OAVBDIMetaModel.parameterelement_has_parametersets, name);
setHandle(BeliefRules.createParameterSet(getState(), name, null, resolveClazz(), pe, mparamset, getScope()));
}
String direction = resolveDirection();
if(OAVBDIMetaModel.PARAMETER_DIRECTION_FIXED.equals(direction)
|| OAVBDIMetaModel.PARAMETER_DIRECTION_IN.equals(direction) && ParameterFlyweight.inprocess(getState(), pe, getScope())
|| OAVBDIMetaModel.PARAMETER_DIRECTION_OUT.equals(direction) && !ParameterFlyweight.inprocess(getState(), pe, getScope()))
throw new RuntimeException("Write access not allowed to parameter set: "
+direction+" "+getName());
for(int i=0; i<values.length; i++)
BeliefRules.addParameterSetValue(getState(), getHandle(), values[i]);
}
};
}
else
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
if(!hasHandle())
{
Object mparamelem = getState().getAttributeValue(pe, OAVBDIRuntimeModel.element_has_model);
Object mparamset = getState().getAttributeValue(mparamelem, OAVBDIMetaModel.parameterelement_has_parametersets, name);
setHandle(BeliefRules.createParameterSet(getState(), name, null, resolveClazz(), pe, mparamset, getScope()));
}
String direction = resolveDirection();
if(OAVBDIMetaModel.PARAMETER_DIRECTION_FIXED.equals(direction)
|| OAVBDIMetaModel.PARAMETER_DIRECTION_IN.equals(direction) && ParameterFlyweight.inprocess(getState(), pe, getScope())
|| OAVBDIMetaModel.PARAMETER_DIRECTION_OUT.equals(direction) && !ParameterFlyweight.inprocess(getState(), pe, getScope()))
throw new RuntimeException("Write access not allowed to parameter set: "
+direction+" "+getName());
getInterpreter().startMonitorConsequences();
for(int i=0; i<values.length; i++)
BeliefRules.addParameterSetValue(getState(), getHandle(), values[i]);
getInterpreter().endMonitorConsequences();
}
}
/**
* Remove all values from a parameter set.
*/
public void removeValues()
{
if(getInterpreter().isExternalThread())
{
new AgentInvocation()
{
public void run()
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
String direction = resolveDirection();
if(OAVBDIMetaModel.PARAMETER_DIRECTION_FIXED.equals(direction)
|| OAVBDIMetaModel.PARAMETER_DIRECTION_IN.equals(direction) && ParameterFlyweight.inprocess(getState(), pe, getScope())
|| OAVBDIMetaModel.PARAMETER_DIRECTION_OUT.equals(direction) && !ParameterFlyweight.inprocess(getState(), pe, getScope()))
throw new RuntimeException("Write access not allowed to parameter set: "
+direction+" "+getName());
if(hasHandle())
{
Collection vals = getState().getAttributeValues(getHandle(), OAVBDIRuntimeModel.parameterset_has_values);
if(vals!=null)
{
Object[] avals = vals.toArray();
for(int i=0; i<avals.length; i++)
BeliefRules.removeParameterSetValue(getState(), getHandle(), avals[i]);
}
}
}
};
}
else
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
String direction = resolveDirection();
if(OAVBDIMetaModel.PARAMETER_DIRECTION_FIXED.equals(direction)
|| OAVBDIMetaModel.PARAMETER_DIRECTION_IN.equals(direction) && ParameterFlyweight.inprocess(getState(), pe, getScope())
|| OAVBDIMetaModel.PARAMETER_DIRECTION_OUT.equals(direction) && !ParameterFlyweight.inprocess(getState(), pe, getScope()))
throw new RuntimeException("Write access not allowed to parameter set: "
+direction+" "+getName());
if(hasHandle())
{
Collection vals = getState().getAttributeValues(getHandle(), OAVBDIRuntimeModel.parameterset_has_values);
if(vals!=null)
{
Object[] avals = vals.toArray();
getInterpreter().startMonitorConsequences();
for(int i=0; i<avals.length; i++)
BeliefRules.removeParameterSetValue(getState(), getHandle(), avals[i]);
getInterpreter().endMonitorConsequences();
}
}
}
}
/**
* Get a value equal to the given object.
* @param oldval The old value.
* /
public Object getValue(final Object oldval)
{
if(getInterpreter().isExternalThread())
{
AgentInvocation invoc = new AgentInvocation()
{
public void run()
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
if(!hasHandle())
{
setHandle(getState().createObject(OAVBDIRuntimeModel.parameterset_type));
getState().setAttributeValue(getHandle(), OAVBDIRuntimeModel.parameterset_has_name, name);
getState().addAttributeValue(pe, OAVBDIRuntimeModel.parameterelement_has_parametersets, getHandle());
}
Collection vals = getState().getAttributeValues(getHandle(), OAVBDIRuntimeModel.parameterset_has_values);
int index = indexOf(oldval);
if(index != -1)
{
found = true;
newval = values.get(index);
}
}
};
return invoc.bool;
}
else
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
if(!hasHandle())
{
setHandle(getState().createObject(OAVBDIRuntimeModel.parameterset_type));
getState().setAttributeValue(getHandle(), OAVBDIRuntimeModel.parameterset_has_name, name);
getState().addAttributeValue(pe, OAVBDIRuntimeModel.parameterelement_has_parametersets, getHandle());
}
Collection vals = getState().getAttributeValues(getHandle(), OAVBDIRuntimeModel.parameterset_has_values);
return vals.contains(value);
}
}*/
/**
* Test if a value is contained in a parameter.
* @param value The value to test.
* @return True, if value is contained.
*/
public boolean containsValue(final Object value)
{
if(getInterpreter().isExternalThread())
{
AgentInvocation invoc = new AgentInvocation()
{
public void run()
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
Collection vals = null;
Object newval = value;
if(hasHandle())
{
// Class clazz = (Class)getState().getAttributeValue(getHandle(), OAVBDIMetaModel.typedelement_has_class);
newval = SReflect.convertWrappedValue(value, resolveClazz());
vals = getState().getAttributeValues(getHandle(), OAVBDIRuntimeModel.parameterset_has_values);
}
bool = vals!=null && vals.contains(newval);
}
};
return invoc.bool;
}
else
{
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
Collection vals = null;
Object newval = value;
if(hasHandle())
{
//Class clazz = (Class)getState().getAttributeValue(getHandle(), OAVBDIMetaModel.typedelement_has_class);
newval = SReflect.convertWrappedValue(value, resolveClazz());
vals = getState().getAttributeValues(getHandle(), OAVBDIRuntimeModel.parameterset_has_values);
}
return vals!=null && vals.contains(newval);
}
}
/**
* Get the values of a parameterset.
* @return The values.
*/
public Object[] getValues()
{
if(getInterpreter().isExternalThread())
{
AgentInvocation invoc = new AgentInvocation()
{
public void run()
{
Collection vals = null;
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
if(hasHandle())
{
vals = getState().getAttributeValues(getHandle(), OAVBDIRuntimeModel.parameterset_has_values);
}
Object[] ret = (Object[])Array.newInstance(resolveClazz(), vals!=null ? vals.size() : 0);
oarray = vals!=null ? vals.toArray(ret) : ret;
}
};
return invoc.oarray;
}
else
{
Collection vals = null;
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
if(hasHandle())
{
vals = getState().getAttributeValues(getHandle(), OAVBDIRuntimeModel.parameterset_has_values);
}
Object[] ret = (Object[])Array.newInstance(resolveClazz(), vals!=null ? vals.size() : 0);
return vals!=null ? vals.toArray(ret) : ret;
}
}
/**
* Get the number of values currently
* contained in this set.
* @return The values count.
*/
public int size()
{
if(getInterpreter().isExternalThread())
{
AgentInvocation invoc = new AgentInvocation()
{
public void run()
{
integer = 0;
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
if(hasHandle())
{
Collection coll = getState().getAttributeValues(getHandle(), OAVBDIRuntimeModel.parameterset_has_values);
if(coll!=null)
integer = coll.size();
}
}
};
return invoc.integer;
}
else
{
int ret = 0;
if(!hasHandle() && getState().containsKey(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name))
{
setHandle(getState().getAttributeValue(pe,
OAVBDIRuntimeModel.parameterelement_has_parametersets, name));
}
if(hasHandle())
{
Collection coll = getState().getAttributeValues(getHandle(), OAVBDIRuntimeModel.parameterset_has_values);
if(coll!=null)
ret = coll.size();
}
return ret;
}
}
/**
* Get the name.
* @return The name.
*/
public String getName()
{
if(getInterpreter().isExternalThread())
{
AgentInvocation invoc = new AgentInvocation()
{
public void run()
{
string = (String)getState().getAttributeValue(getHandle(), OAVBDIRuntimeModel.parameterset_has_name);
}
};
return invoc.string;
}
else
{
return (String)getState().getAttributeValue(getHandle(), OAVBDIRuntimeModel.parameterset_has_name);
}
}
//-------- IElement interface --------
/**
* Get the model element.
* @return The model element.
*/
public IMElement getModelElement()
{
if(getInterpreter().isExternalThread())
{
AgentInvocation invoc = new AgentInvocation()
{
public void run()
{
Object mpe = getState().getAttributeValue(pe, OAVBDIRuntimeModel.element_has_model);
Object mparameterset = getState().getAttributeValue(mpe, OAVBDIMetaModel.parameterelement_has_parametersets, name);
Object mscope = getState().getAttributeValue(getScope(), OAVBDIRuntimeModel.element_has_model);
object = new MParameterSetFlyweight(getState(), mscope, mparameterset);
}
};
return (IMElement)invoc.object;
}
else
{
IMElement ret = null;
Object mpe = getState().getAttributeValue(pe, OAVBDIRuntimeModel.element_has_model);
Object mparameterset = getState().getAttributeValue(mpe, OAVBDIMetaModel.parameterelement_has_parametersets, name);
Object mscope = getState().getAttributeValue(getScope(), OAVBDIRuntimeModel.element_has_model);
ret = new MParameterSetFlyweight(getState(), mscope, mparameterset);
return ret;
}
}
/**
* Resolve the parameterset class.
*/
protected Class resolveClazz()
{
Class clazz = null;
Object mparamelem = getState().getAttributeValue(pe, OAVBDIRuntimeModel.element_has_model);
Object mparamset = getState().getAttributeValue(mparamelem, OAVBDIMetaModel.parameterelement_has_parametersets, name);
if(mparamset!=null)
{
clazz = (Class)getState().getAttributeValue(mparamset, OAVBDIMetaModel.typedelement_has_class);
}
else if(getState().getType(mparamelem).isSubtype(OAVBDIMetaModel.messageevent_type))
{
MessageType mt = MessageEventRules.getMessageEventType(getState(), mparamelem);
ParameterSpecification ps = mt.getParameter(name);
clazz = ps.getClazz();
}
if(clazz==null)
clazz = Object.class;
return clazz;
}
/**
* Resolve the parameter direction.
*/
protected String resolveDirection()
{
String direction = null;
Object mparamelem = getState().getAttributeValue(pe, OAVBDIRuntimeModel.element_has_model);
Object mparamset = getState().getAttributeValue(mparamelem, OAVBDIMetaModel.parameterelement_has_parametersets, name);
if(mparamset!=null)
{
direction = (String)getState().getAttributeValue(mparamset, OAVBDIMetaModel.parameterset_has_direction);
}
if(direction==null)
direction = OAVBDIMetaModel.PARAMETER_DIRECTION_IN;
return direction;
}
}