package jadex.bdi.runtime.impl.flyweights; import jadex.bdi.model.IMElement; import jadex.bdi.model.OAVBDIMetaModel; import jadex.bdi.model.impl.flyweights.MEventbaseFlyweight; import jadex.bdi.runtime.IEventbase; import jadex.bdi.runtime.IInternalEvent; import jadex.bdi.runtime.IInternalEventListener; import jadex.bdi.runtime.IMessageEvent; import jadex.bdi.runtime.IMessageEventListener; import jadex.bdi.runtime.impl.SFlyweightFunctionality; import jadex.bdi.runtime.interpreter.AgentRules; import jadex.bdi.runtime.interpreter.BDIInterpreter; import jadex.bdi.runtime.interpreter.InternalEventRules; import jadex.bdi.runtime.interpreter.MessageEventRules; import jadex.bdi.runtime.interpreter.OAVBDIRuntimeModel; import jadex.bridge.IComponentIdentifier; import jadex.commons.IFuture; import jadex.commons.Tuple; import jadex.rules.state.IOAVState; /** * Flyweight for the eventbase. */ public class EventbaseFlyweight extends ElementFlyweight implements IEventbase { //-------- constructors -------- /** * Create a new goalbase flyweight. * @param state The state. * @param scope The scope handle. */ private EventbaseFlyweight(IOAVState state, Object scope) { super(state, scope, scope); } /** * Get or create a flyweight. * @return The flyweight. */ public static EventbaseFlyweight getEventbaseFlyweight(IOAVState state, Object scope) { BDIInterpreter ip = BDIInterpreter.getInterpreter(state); EventbaseFlyweight ret = (EventbaseFlyweight)ip.getFlyweightCache(IEventbase.class, new Tuple(IEventbase.class, scope)); if(ret==null) { ret = new EventbaseFlyweight(state, scope); ip.putFlyweightCache(IEventbase.class, new Tuple(IEventbase.class, scope), ret); } return ret; } //-------- methods -------- /** * Send a message after some delay. * @param me The message event. * @return The filter to wait for an answer. */ public IFuture sendMessage(IMessageEvent me) { IFuture ret; if(getInterpreter().isExternalThread()) { AgentInvocation invoc = new AgentInvocation(me) { public void run() { object = MessageEventRules.sendMessage(getState(), getScope(), ((ElementFlyweight)arg).getHandle()); } }; ret = (IFuture)invoc.object; } else { ret = MessageEventRules.sendMessage(getState(), getScope(), ((ElementFlyweight)me).getHandle()); } return ret; } /** * Dispatch an event. * @param event The event. */ // changed signature for javaflow, removed final public void dispatchInternalEvent(IInternalEvent event) { if(getInterpreter().isExternalThread()) { new AgentInvocation(event) { public void run() { InternalEventRules.adoptInternalEvent(getState(), getScope(), ((InternalEventFlyweight)arg).getHandle()); } }; } else { getInterpreter().startMonitorConsequences(); InternalEventRules.adoptInternalEvent(getState(), getScope(), ((InternalEventFlyweight)event).getHandle()); getInterpreter().endMonitorConsequences(); } } /** * Create a new message event. * @return The new message event. */ public IMessageEvent createMessageEvent(String type) { if(getInterpreter().isExternalThread()) { AgentInvocation invoc = new AgentInvocation(type) { public void run() { object = SFlyweightFunctionality.createMessageEvent(getState(), getScope(), (String)arg); } }; return (IMessageEvent)invoc.object; } else { return (IMessageEvent)SFlyweightFunctionality.createMessageEvent(getState(), getScope(), type); } } /** * Create a reply to a message event. * @param event The received message event. * @param msgeventtype The reply message event type. * @return The reply event. */ public IMessageEvent createReply(final IMessageEvent event, final String msgeventtype) { if(getInterpreter().isExternalThread()) { AgentInvocation invoc = new AgentInvocation(new Object[]{event, msgeventtype}) { public void run() { ElementFlyweight reply = (ElementFlyweight)SFlyweightFunctionality.createMessageEvent(getState(), getScope(), msgeventtype); object = MessageEventFlyweight.getMessageEventFlyweight(getState(), getScope(), MessageEventRules.initializeReply(getState(), getScope(), ((ElementFlyweight)event).getHandle(), ((ElementFlyweight)reply).getHandle())); } }; return (IMessageEvent)invoc.object; } else { ElementFlyweight reply = (ElementFlyweight)SFlyweightFunctionality.createMessageEvent(getState(), getScope(), msgeventtype); return MessageEventFlyweight.getMessageEventFlyweight(getState(), getScope(), MessageEventRules.initializeReply(getState(), getScope(), ((ElementFlyweight)event).getHandle(), ((ElementFlyweight)reply).getHandle())); } } /** * Create a new intenal event. * @return The new intenal event. */ public IInternalEvent createInternalEvent(final String ref) { if(getInterpreter().isExternalThread()) { AgentInvocation invoc = new AgentInvocation() { public void run() { Object[] scope = AgentRules.resolveCapability(ref, OAVBDIMetaModel.internalevent_type, getScope(), getState()); Object revent = InternalEventRules.createInternalEvent(getState(), scope[1], (String)scope[0]); object = InternalEventFlyweight.getInternalEventFlyweight(getState(), scope[1], revent); } }; return (IInternalEvent)invoc.object; } else { Object[] scope = AgentRules.resolveCapability(ref, OAVBDIMetaModel.internalevent_type, getScope(), getState()); Object revent = InternalEventRules.createInternalEvent(getState(), scope[1], (String)scope[0]); return InternalEventFlyweight.getInternalEventFlyweight(getState(), scope[1], revent); } } /** * Create a legacy internal event (not explicitly defined in ADF). * @return The new internal event. * @deprecated Convenience method for easy conversion to the new Jadex version. * Will be removed in later releases. * / public IInternalEvent createInternalEvent(String type, Object content);*/ /** * Register a new event model. * @param mevent The event model. * / public void registerEvent(IMEvent mevent) { throw new UnsupportedOperationException(); }*/ /** * Register a new event reference model. * @param meventref The event reference model. * / public void registerEventReference(IMEventReference meventref) { throw new UnsupportedOperationException(); }*/ /** * Deregister an event model. * @param mevent The event model. * / public void deregisterEvent(IMEvent mevent) { throw new UnsupportedOperationException(); }*/ /** * Deregister an event reference model. * @param meventref The event reference model. * / public void deregisterEventReference(IMEventReference meventref) { throw new UnsupportedOperationException(); }*/ //-------- listeners -------- /** * Add a internal event listener. * @param type The internal event type. * @param listener The internal event listener. */ public void addInternalEventListener(final String type, final IInternalEventListener listener) { if(getInterpreter().isExternalThread()) { new AgentInvocation(new Object[]{type, listener}) { public void run() { Object mevent = SFlyweightFunctionality.checkElementType(getState(), getScope(), type, OAVBDIMetaModel.capability_has_internalevents); addEventListener(listener, mevent); } }; } else { Object mevent = SFlyweightFunctionality.checkElementType(getState(), getScope(), type, OAVBDIMetaModel.capability_has_internalevents); addEventListener(listener, mevent); } } /** * Remove a internal event listener. * @param type The internal event type. * @param listener The internal event listener. */ public void removeInternalEventListener(final String type, final IInternalEventListener listener) { if(getInterpreter().isExternalThread()) { new AgentInvocation(new Object[]{type, listener}) { public void run() { Object mevent = SFlyweightFunctionality.checkElementType(getState(), getScope(), type, OAVBDIMetaModel.capability_has_internalevents); removeEventListener(args[1], mevent, false); } }; } else { Object mevent = SFlyweightFunctionality.checkElementType(getState(), getScope(), type, OAVBDIMetaModel.capability_has_internalevents); removeEventListener(listener, mevent, false); } } /** * Add a message event listener. * @param type The message event type. * @param listener The message event listener. */ public void addMessageEventListener(final String type, final IMessageEventListener listener) { if(getInterpreter().isExternalThread()) { new AgentInvocation(new Object[]{type, listener}) { public void run() { Object mevent = SFlyweightFunctionality.checkElementType(getState(), getScope(), type, OAVBDIMetaModel.capability_has_messageevents); addEventListener(args[1], mevent); } }; } else { Object mevent = SFlyweightFunctionality.checkElementType(getState(), getScope(), type, OAVBDIMetaModel.capability_has_messageevents); addEventListener(listener, mevent); } } /** * Remove a message event listener. * @param type The message event type. * @param listener The message event listener. */ public void removeMessageEventListener(final String type, final IMessageEventListener listener) { if(getInterpreter().isExternalThread()) { new AgentInvocation(new Object[]{type, listener}) { public void run() { Object mevent = SFlyweightFunctionality.checkElementType(getState(), getScope(), type, OAVBDIMetaModel.capability_has_messageevents); removeEventListener(listener, mevent, false); } }; } else { Object mevent = SFlyweightFunctionality.checkElementType(getState(), getScope(), type, OAVBDIMetaModel.capability_has_messageevents); removeEventListener(listener, mevent, false); } } /** * Register a conversation or reply_with to be able * to send back answers to the source capability. * @param msgevent The message event. * todo: indexing for msgevents for speed. */ public void registerMessageEvent(final IMessageEvent mevent) { if(getInterpreter().isExternalThread()) { new AgentInvocation() { public void run() { MessageEventFlyweight mef = (MessageEventFlyweight)mevent; MessageEventRules.registerMessageEvent(getState(), mef.getHandle(), mef.getScope()); } }; } else { MessageEventFlyweight mef = (MessageEventFlyweight)mevent; MessageEventRules.registerMessageEvent(getState(), mef.getHandle(), mef.getScope()); } } /** * Remove a registered message event. * @param msgevent The message event. */ public void deregisterMessageEvent(final IMessageEvent mevent) { if(getInterpreter().isExternalThread()) { new AgentInvocation() { public void run() { MessageEventFlyweight mef = (MessageEventFlyweight)mevent; MessageEventRules.deregisterMessageEvent(getState(), mef.getHandle(), mef.getScope()); } }; } else { MessageEventFlyweight mef = (MessageEventFlyweight)mevent; MessageEventRules.deregisterMessageEvent(getState(), mef.getHandle(), mef.getScope()); } } /** * Create component identifier. * @param name The name. * @param local True for local name. * @param addresses The addresses. * @return The new component identifier. */ public IComponentIdentifier createComponentIdentifier(String name) { return createComponentIdentifier(name, true, null); } /** * Create component identifier. * @param name The name. * @param local True for local name. * @param addresses The addresses. * @return The new component identifier. */ public IComponentIdentifier createComponentIdentifier(String name, boolean local) { return createComponentIdentifier(name, local, null); } /** * Create component identifier. * @param name The name. * @param local True for local name. * @param addresses The addresses. * @return The new component identifier. */ public IComponentIdentifier createComponentIdentifier(final String name, final boolean local, final String[] addresses) { if(getInterpreter().isExternalThread()) { AgentInvocation ai = new AgentInvocation() { public void run() { object = getInterpreter().getCMS().createComponentIdentifier(name, local, addresses); } }; return (IComponentIdentifier)ai.object; } else { return getInterpreter().getCMS().createComponentIdentifier(name, local, addresses); } } //-------- element interface -------- /** * Get the model element. * @return The model element. */ public IMElement getModelElement() { if(getInterpreter().isExternalThread()) { AgentInvocation invoc = new AgentInvocation() { public void run() { Object mscope = getState().getAttributeValue(getScope(), OAVBDIRuntimeModel.element_has_model); object = new MEventbaseFlyweight(getState(), mscope); } }; return (IMElement)invoc.object; } else { Object mscope = getState().getAttributeValue(getScope(), OAVBDIRuntimeModel.element_has_model); return new MEventbaseFlyweight(getState(), mscope); } } }