/*********************************************************************/ /* */ /* AgentService Framework */ /* www.agentservice.it */ /* */ /* Copyright (C) 2007 l.i.d.o. - DIST, University of Genoa, Italy */ /* GNU Lesser General Public License */ /* */ /* 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, */ /* version 2.1 of the License. */ /* */ /* 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. */ /* */ /*********************************************************************/ using System; using System.Collections.Generic; using System.Reflection; using AgentService.Agent; using AgentService.Agent.Behaviour; using AgentService.Agent.Knowledge; using AgentService.Agent.Runtime; using AgentService.Platform; using AgentService.Platform.DF; using AgentService.Platform.AMS; using AgentService.Platform.MTS; using AgentService.Platform.Modules; namespace AgentService.Agent { /// /// The delegate that manages the OnPersistAgent event. /// public delegate void PersistAgentDelegate(object sender, PersistenceEventArgs args); /// /// Delegate BehaviourDelegate. Delegate that manages every event related to the behaviour. /// public delegate void BehaviourDelegate(object sender, BehaviourArgs args); /// /// The delegate that manages the most of the Agent events: /// activation, stopping, termination... /// public delegate void AgentDelegate(AID sender); /// /// Class BehaviourArgs. Collects information about the event related /// to the behaviour. It mantains a reference to the behaviour type, /// name and state. /// public class BehaviourArgs { /// /// Type of the behaviour. /// private System.Type type; /// /// Gets the type of the behaviour, if the /// type is equal to Agent.Behaviour.Behaviour /// the event is not tied to a specific Behaviour /// class or instance but to all the Behaviour instances /// of the agent. /// public System.Type Type { get { return this.type; } } /// /// Name of the behaviour, if the name is null /// the event is related to the all the Behaviour /// instances of the agent. /// private string name; /// /// Gets the name of the behaviour, if the name is null /// the event is related to the all the Behaviour /// instances of the agent. /// public string Name { get { return this.name; } } /// /// State of the behaviour. /// private BehaviourState state; /// /// Gets the state of the behaviour. /// private BehaviourState State { get { return this.state; } } /// /// if true, the behaviour that terminated /// was the last behaviour scheduled by the /// agent. /// private bool bLast; /// /// Gets the Last flag, if true the behaviour /// that originated the event was the last /// behaviour scheduled by the agent /// public bool IsLast { get { return this.bLast; } } /// /// Construct a BehaviourArgs object. /// /// type of the behaviour /// name of the behaviour /// state of the behaviour /// if true this is the behaviour instance /// associated to the event was the last remined in the scheduler public BehaviourArgs(System.Type type, string name, BehaviourState state, bool bLast) { this.type = type; this.name = name; this.state = state; this.bLast = bLast; } /// /// Construct a BehaviourArgs object. /// /// type of the behaviour /// name of the behaviour /// state of the behaviour public BehaviourArgs(System.Type type, string name, BehaviourState state) { this.type = type; this.name = name; this.state = state; this.bLast = false; } } /// /// Class PeristenceEventArgs. Wraps the agent persistent object. /// public class PersistenceEventArgs { /// /// Persistent version of the agent. /// private AgentPersistent persistent; /// /// Gets the persistent version of the agent. /// public AgentPersistent Persistent { get { return this.persistent; } } /// /// Constructs a PersistenceEventArgs object for the given /// AgentPersistent object. /// /// persistent version of the agent public PersistenceEventArgs(AgentPersistent ap) { this.persistent = ap; } } /// /// Class Agent. Defines a running instance of an agent. /// public class Agent: IAgent { # region Members #region Agent Events /// /// Conversation handler delegate. /// private ConversationDelegate convHandler; /// /// Class DefaultAgentProxy. Agent proxy instance /// it is used to forward event handler addition /// and removal to the agent instance. /// private class DefaultAgentEventProxy : IAgentEventProxy { /// /// agent instance. /// private IAgent agent; /// /// flags that controls event forwardin, if /// true the events are forwarded, if false not. /// internal bool bForwardEvents; /// /// Fires when the agent is activated. /// public event AgentDelegate OnActivateAgent { add { if (this.bForwardEvents == true) { this.agent.OnActivateAgent += value; } } remove { if (this.bForwardEvents == true) { this.agent.OnActivateAgent -= value; } } } /// /// Fires when the agent is stopped. /// public event AgentDelegate OnStopAgent { add { if (this.bForwardEvents == true) { this.agent.OnStopAgent += value; } } remove { if (this.bForwardEvents == true) { this.agent.OnStopAgent -= value; } } } /// /// Fires when the system reosurces of the agent /// need to be released. /// public event AgentDelegate OnReleaseAgent { add { if (this.bForwardEvents == true) { this.agent.OnReleaseAgent += value; } } remove { if (this.bForwardEvents == true) { this.agent.OnReleaseAgent -= value; } } } /// /// Fires when the agent is terminated. /// public event AgentDelegate OnTerminateAgent { add { if (this.bForwardEvents == true) { this.agent.OnTerminateAgent += value; } } remove { if (this.bForwardEvents == true) { this.agent.OnTerminateAgent -= value; } } } /// /// Fires when a new behaviour in the agent is /// created. /// public event BehaviourDelegate OnNewBehaviour { add { if (this.bForwardEvents == true) { this.agent.OnNewBehaviour += value; } } remove { if (this.bForwardEvents == true) { this.agent.OnNewBehaviour -= value; } } } /// /// Fires when an agent's behaviour is started. /// public event BehaviourDelegate OnStartBehaviour { add { if (this.bForwardEvents == true) { this.agent.OnStartBehaviour += value; } } remove { if (this.bForwardEvents == true) { this.agent.OnStartBehaviour -= value; } } } /// /// Fires when an agent's behaviour is suspended. /// public event BehaviourDelegate OnSuspendBehaviour { add { if (this.bForwardEvents == true) { this.agent.OnSuspendBehaviour += value; } } remove { if (this.bForwardEvents == true) { this.agent.OnSuspendBehaviour -= value; } } } /// /// Fires when an agent's behaviour is terminated. /// public event BehaviourDelegate OnTerminateBehaviour { add { if (this.bForwardEvents == true) { this.agent.OnTerminateBehaviour += value; } } remove { if (this.bForwardEvents == true) { this.agent.OnTerminateBehaviour -= value; } } } /// /// Creates a proxy for the given agent instance. /// /// agent instance. internal DefaultAgentEventProxy(IAgent agent) { this.agent = agent; this.bForwardEvents = false; } } /// /// proxy to the agent events. /// private DefaultAgentEventProxy eventProxy; /// /// Thrown when the agent is activated. /// public event AgentDelegate OnActivateAgent; /// /// Fires every time an agent has terminated /// its activity either because it has been /// stopped by the platform or because it has /// terminated. /// public event AgentDelegate OnReleaseAgent; /// /// thrown when the agent is stopped /// public event AgentDelegate OnStopAgent; /// /// thrown when the agent temrminates its execution /// public event AgentDelegate OnTerminateAgent; /// /// thrown by a persistent agent, when its internal data /// change /// /*internal*/ public event PersistAgentDelegate OnPersistAgent; #endregion #region Behaviour related events /// /// Fires every time a new behaviour is created. /// public event BehaviourDelegate OnNewBehaviour; /// /// Fires every time a behaviour is started. /// public event BehaviourDelegate OnStartBehaviour; /// /// Fires every time a behaviour is terminated. /// public event BehaviourDelegate OnTerminateBehaviour; /// /// Fires every time a behaviour is suspended. /// public event BehaviourDelegate OnSuspendBehaviour; /// /// Fires every time a behaviour is woken up. /// public event BehaviourDelegate OnWakeUpBehaviour; #endregion /// /// Unique Agent-IDentifier. /// protected AID aid; /// /// Gets the Agent's AID. /// public AID AID { get { return this.aid; } set { this.aid = value; this.persistent.SetAID(value); } } /// /// Life cycle state of the Agent. /// private AgentState state = AgentState.Unknown; /// /// Gets the Agent's state. /// public AgentState State { get { return this.state; } set { this.state = value; this.persistent.SetState(value); } } /// /// Persistence flag. /// private bool bPersist; /// /// Gets the persistence flag. /// public bool IsPersistent { get { return this.bPersist; } } /// /// Behaviour scheduler. /// private AgentService.Agent.Behaviour.IBehaviourScheduler scheduler; /// /// Runtime environment for the agent. /// private AgentService.Agent.Runtime.IRuntimeEx runtime; /// /// Collection of KnowledgeManager objects. /// private AgentService.Agent.Knowledge.KnowledgeCollection knowledges; /// /// Gets the collection of KnowledgeManager objects. /// public AgentService.Agent.Knowledge.KnowledgeCollection Knowledges { get { return this.knowledges; } } /// /// Collection of Behaviour objects belonging to the Agent. /// private AgentService.Agent.Behaviour.BehaviourCollection behaviours; /// /// Gets the collection of Behaviour objects. /// public AgentService.Agent.Behaviour.BehaviourCollection Behaviours { get { return this.behaviours; } } /// /// Collection of Knowledge type objects handled by the agent. /// private TypeDescriptorCollection knowledgeTypes; /// /// Returns the collection of the Knowledge type objects that /// the agent handles. /// public TypeDescriptorCollection KnowledgeTypes { get { return this.knowledgeTypes; } } /// /// Collection of Behaviour type objects handled by the agent. /// private TypeDescriptorCollection behaviourTypes; /// /// Returns the collection of the Behaviour type objects that /// the agent handles. /// public TypeDescriptorCollection BehaviourTypes { get { return this.behaviourTypes; } } /// /// Reference to the AgentTemplate managed by the Agent. /// internal protected AgentTemplate template; /// /// The type context that loads into the agent the knowledge's and behaviour's type added by the template. /// private DefaultTypeContext typeContext; /// /// The factory context that istantiates and loads into the agent knowledge's and behaviour's object added by the template. /// private DefaultFactoryContext factoryContext; /// /// Persistent version of the agent. /// internal AgentPersistent persistent; public AgentPersistent Persistent { get { return this.persistent; } set { this.persistent = value; } } /// /// Profile of the agent /// private AgentProfile profile; /// /// Get the profile of the agent /// public AgentProfile Profile { get { if (this.profile == null) { TypeDescriptor[] bhDescriptors = new TypeDescriptor[this.behaviourTypes.Count]; TypeDescriptor[] knDescriptors = new TypeDescriptor[this.knowledgeTypes.Count]; lock(this.behaviourTypes) { this.behaviourTypes.CopyTo(bhDescriptors, 0); } lock(this.knowledgeTypes) { this.knowledgeTypes.CopyTo(knDescriptors, 0); } TypeDescriptor agentTemplateDescriptor = new TypeDescriptor(this.template.GetType()); this.profile = new AgentProfile(bhDescriptors,knDescriptors,agentTemplateDescriptor,this.aid.GlobalName,this.aid.HapName); } return this.profile; } } /// /// Name of agent's config file /// private string configFileName; /// /// Get the config file name of the agent /// public string ConfigFileName { get { return this.configFileName; } } #endregion # region Constructor /// /// Constructs an empty Agent. /// public Agent() { this.knowledges = new AgentService.Agent.Knowledge.KnowledgeCollection(); this.behaviours = new AgentService.Agent.Behaviour.BehaviourCollection(); this.knowledgeTypes = new TypeDescriptorCollection(); this.behaviourTypes = new TypeDescriptorCollection(); this.factoryContext = new DefaultFactoryContext(this); this.typeContext = new DefaultTypeContext(this); this.scheduler = new Behaviour.BehaviourScheduler(); this.persistent = new AgentPersistent(); this.bPersist = true; this.convHandler = new ConversationDelegate(this.HandleConversation); } /// /// Constructs an agent by specifying the persistence flag. /// /// persistence flag public Agent(bool bPersist) { this.knowledges = new AgentService.Agent.Knowledge.KnowledgeCollection(); this.behaviours = new AgentService.Agent.Behaviour.BehaviourCollection(); this.knowledgeTypes = new TypeDescriptorCollection(); this.behaviourTypes = new TypeDescriptorCollection(); this.factoryContext = new DefaultFactoryContext(this); this.typeContext = new DefaultTypeContext(this); this.scheduler = new Behaviour.BehaviourScheduler(); // TODO: Code review: why always create agentpersistent? this.persistent = new AgentPersistent(); this.bPersist = bPersist; this.convHandler = new ConversationDelegate(this.HandleConversation); } #endregion # region Agent Activity /// /// Initialize the internal Agent's data structures. /// /// configuration file for agent initialization including the full path public void Initiate(string configFile) // public void Initialize(object configFile) { //MOD: 07/06/2006: Marco Garr: removed typeContext from AgentTemplate.Initialize // now types are registered automatically using AgentAttributes. AgentBehavioursAttribute behas = (AgentBehavioursAttribute)Attribute.GetCustomAttribute(this.template.GetType(), typeof(AgentBehavioursAttribute)); if (behas != null) { this.typeContext.RegisterBehaviourTypes(behas.Types); } AgentKnowledgesAttribute knows = (AgentKnowledgesAttribute)Attribute.GetCustomAttribute(this.template.GetType(), typeof(AgentKnowledgesAttribute)); if (knows != null) { this.typeContext.RegisterKnowledgeTypes(knows.Types); } if (configFile != null) { bool bOk = this.template.Configure(configFile); if (bOk == false) { throw new AgentService.Generic.AgentServiceException("Unexpected error reading: " + configFile); } } this.template.Initiate(this.factoryContext); this.configFileName = System.IO.Path.GetFileName(configFile); } /// /// Starts the agent activity. /// public void Activate() { if (this.OnActivateAgent!= null) { this.OnActivateAgent(this.AID); } lock(this.behaviours) { foreach(Behaviour.Behaviour behaviour in this.behaviours) { behaviour.Bind(this.runtime.Clone(behaviour)); } } this.scheduler.StartAll(); } /// /// Assigns an AgentTemplate to the Agent and gives him an AID. /// /// full template name of the corresponding AgentTemplate subtype /// name of the containing assembly of the AgentTemplate subtype public void SetTemplate(AgentTemplate template) { this.template = template; if (this.bPersist == true) { this.persistent.SetTemplateName(template.GetType().FullName); } } /// /// Commits the agent migration process /// /// flag used to distinguish the source /// and the target platform public void CommitMove (bool bIsSourceInstance) { if (bIsSourceInstance == true) { // call the template to finalize all the data belonging to // the template this.template.Terminate(); // no more behaviours in execution; the agent terminated its work this.state = AgentState.Unknown; if (this.OnTerminateAgent != null) { this.OnTerminateAgent(this.AID); } } else { // everything the agent needs to restart its activity in the // target platform } } # endregion # region Manage Platform Services /// /// Binds the agent to the runtime environemt of the platform. /// /// gives access to the runtime services of the platform public void Bind(AgentService.Agent.Runtime.IRuntimeEx runtime) { this.runtime = runtime; if (this.eventProxy == null) { this.eventProxy = new DefaultAgentEventProxy(this); } this.eventProxy.bForwardEvents = true; this.runtime.PersistenceSvc.BindEvents(this.eventProxy); this.runtime.MessageSvc.BindEvents(this.eventProxy); this.runtime.LogSvc.BindEvents(this.eventProxy); this.runtime.WPageSvc.BindEvents(this.eventProxy); this.runtime.YPageSvc.BindEvents(this.eventProxy); /* this.runtime.LogSvc.OpenSession(this.GetHashCode()); this.OnStopAgent += this.runtime.MessageSvc.GetStopAgentDelegate(); */ this.runtime.MessageSvc.OnIncomingConversation += this.convHandler; this.eventProxy.bForwardEvents = false; } /// /// Loads agent data from its persisted version. /// /// persisted version of the agent public virtual void ResumeFrom(AgentPersistent agentPersistent) { this.persistent = agentPersistent; // MOD: 19/07/2006 Simone Belotti: check if collections are empty. If not, erase all the elements if (this.knowledges.Count != 0) { this.knowledges = new KnowledgeCollection(); } // ENDMOD this.knowledgeTypes = agentPersistent.KnowledgeTypeNames; this.behaviourTypes = agentPersistent.BehaviourTypeNames; for(int ndx = 0; ndx i=0: wrong because it goes outside // boundary limits // int i = 0; for(int ndx=1; ndx /// Gets the type object related to the given type name. /// /// name of the type /// type object holding the information about the type private System.Type findTypeByName(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); Type type = null; foreach(Assembly assembly in assemblies) { type = assembly.GetType(typeName); if (type != null) break; } return type; } /// /// Creates the persistent version of the agent. /// /// persisted version of the agent public AgentPersistent GetPersistent() { if (this.bPersist) { // CHANGE: 23/01/2003 - Added the following statement to // Clear the persistedKnowledge data structure this.persistent.PersistedKnowledges.RemoveAll(); foreach(Knowledge.Knowledge knowledge in this.knowledges) { this.persistent.PersistedKnowledges.Add(knowledge.GetPersistent()); } lock(this.behaviours) { foreach(Behaviour.Behaviour behaviour in this.behaviours) { foreach(Behaviour.BehaviourPersistent bp in this.persistent.PersistedBehaviours) { if (behaviour.Name.CompareTo(bp.Name) == 0) { bp.State = behaviour.State; } } } } this.persistent.SetState(this.state); return this.persistent; } return null; } /// /// Handles the incoming conversation event. /// /// /// information about the incoming conversation private void HandleConversation(object sender, ConversationArgs args) { DefaultAgentContext context = new DefaultAgentContext(this); this.template.HandleConversation(context, args); } #endregion #region Manage Agent Behaviours /// /// Adds a new behaviour to the agent and starts it. /// /// The Behaviour to be added to the Agent /// if true starts the behaviour public void SubmitBehaviour(Behaviour.Behaviour behaviour, bool bStart) { lock(this.behaviours) { this.behaviours.Add(behaviour); } this.scheduler.Add(behaviour); // notifies all the runtime components // that a new beahviour has been created // in this way we can properly handle // the WaitForTermination statement if (this.OnNewBehaviour != null) { this.OnNewBehaviour(this, new BehaviourArgs(behaviour.GetType(), behaviour.Name, behaviour.State)); } if (bStart == true) { // we have to bind the behaviour to the runtime // because bStart == true and this means that // the behaviour has been created at runtime and // has not yet bound behaviour.Bind(this.runtime.Clone(behaviour)); this.scheduler.Start(behaviour); } } /// /// Suspends a behaviour instance. /// /// behaviour instances that will be suspended public void SuspendBehaviour(AgentService.Agent.Behaviour.Behaviour behaviour) { this.scheduler.Suspend(behaviour); // notifies all the runtime components // that a behaviour has been suspended if (this.OnSuspendBehaviour != null) { this.OnSuspendBehaviour(this, new BehaviourArgs(behaviour.GetType(), behaviour.Name, behaviour.State)); } } /// /// Suspends all the behaviour instances. /// public void SuspendAllBehaviours() { this.scheduler.SuspendAll(); // notifies all the runtime components // that a all the behaviours have been // suspended if (this.OnSuspendBehaviour != null) { this.OnSuspendBehaviour(this, new BehaviourArgs(typeof(Behaviour.Behaviour), null, BehaviourState.Suspended)); } } /// /// Resumes a suspended behaviour instance. /// /// suspended behaviour instance that will be resumed public void WakeUpBehaviour(AgentService.Agent.Behaviour.Behaviour behaviour) { this.scheduler.WakeUp(behaviour); // notifies all the runtime components // that a new behaviour has been created // woken up if (this.OnWakeUpBehaviour != null) this.OnWakeUpBehaviour(this, new BehaviourArgs(behaviour.GetType(), behaviour.Name, behaviour.State)); } /// /// Resumes all suspended behaviour instances. /// public void WakeUpAllBehaviours() { this.scheduler.WakeUpAll(); // notifies all the runtime components // that a new behaviour has been created // woken up if (this.OnWakeUpBehaviour != null) this.OnWakeUpBehaviour(this, new BehaviourArgs(typeof(Behaviour.Behaviour), null, BehaviourState.Running)); } /// /// Removes a behaviour instance. /// /// behaviour instance that will be removed public void RemoveBehaviour(AgentService.Agent.Behaviour.Behaviour behaviour) { bool bTerminate = false; // ok the code behaviour has finished // its activity so we notify all the // handlers about the event this.scheduler.Remove(behaviour); lock(this.behaviours) { this.behaviours.Remove(behaviour); //MOD: Christian Vecchiola - 02/12/2005 // Agent Termination if (this.behaviours.Count == 0) { bTerminate = true; } //END MOD } // notifies all the runtime components // that a new behaviour has been terminated if (this.OnTerminateBehaviour != null) { this.OnTerminateBehaviour(this, new BehaviourArgs(behaviour.GetType(), behaviour.Name, behaviour.State, bTerminate)); } // checks if there are no more behaviours running // if bTerminate is true, ok we're done if (bTerminate == true) { // finalizes the agent instance: // let all runtime components stop // their activity. if (this.OnReleaseAgent != null) { this.OnReleaseAgent(this.aid); } // call the template to finalize // all the data belonging to the // template this.template.Terminate(); // no more behaviours in execution // the agent has terminated its work this.state = AgentState.Terminated; if (this.OnTerminateAgent != null) { this.OnTerminateAgent(this.AID); } // disconnects the event handlers. this.Unbind(); } else { if (this.bPersist == true) { lock(this.persistent.PersistedBehaviours) { this.persistent.PersistedBehaviours.Remove(behaviour); } if (this.OnPersistAgent != null) { PersistenceEventArgs args = new PersistenceEventArgs(this.GetPersistent()); this.OnPersistAgent(this,args); } } } } /// /// Removes all behaviours instances. /// public void RemoveAllBehaviours() { this.Stop(); lock(this.behaviours) { this.behaviours.RemoveAll(); } // notifies all the runtime components // that a new behaviour has been terminated if (this.OnTerminateBehaviour != null) { this.OnTerminateBehaviour(this, new BehaviourArgs(typeof(Behaviour.Behaviour), null, BehaviourState.Unknown, true)); } // NOTE: Do not check if the agent is persistent since the // it is going to be destroyed. } /// /// Starts a collection of behaviours instances. /// /// list of behaviour instances names that will be started public void StartBehaviours(params string[] behaviourNames) { foreach(string name in behaviourNames) { lock(this.behaviours) { foreach(AgentService.Agent.Behaviour.Behaviour deployedBehaviour in this.behaviours) { if(deployedBehaviour.Name.Equals(name)) { this.scheduler.Start(deployedBehaviour); // REVIEW: design a new state for started? if (this.OnStartBehaviour != null) this.OnStartBehaviour(this, new BehaviourArgs(deployedBehaviour.GetType(), deployedBehaviour.Name, deployedBehaviour.State)); break; } } } } } /// /// Starts all the behaviour instances previously added. /// public void StartAllBehaviours() { this.scheduler.StartAll(); // REVIEW: design a new state for behaviour just started? if (this.OnStartBehaviour != null) { this.OnStartBehaviour(this, new BehaviourArgs(typeof(Behaviour.Behaviour), null, BehaviourState.Running)); } } /// /// Kills all the threads and stops the agent /// as a result of the normal activity of the /// platform. /// public void Stop() { this.Stop(false); } /// /// Kills all the threads belonging to the agent. /// /// stop reason, if true the agent terminated abnormally public void Stop(bool bAbort) { // in case of normal termination // we signal all the events as // normal if (bAbort == false) { // if the agent is persistent // the scheduler will not change // the state of behaviours this.scheduler.RemoveAll(this.bPersist == false); if (this.OnReleaseAgent != null) { this.OnReleaseAgent(this.aid); } // MOD: Christian need to call this before dying. this.template.Terminate(); // this.runtime.LogSvc.CloseSession(theis.GetHashCode()); if (this.OnStopAgent != null) { this.OnStopAgent(this.aid); } } this.Unbind(); this.runtime.LogSvc.CloseSession(this.GetHashCode()); } /// /// Releases all the resources /// private void Unbind() { this.eventProxy.bForwardEvents = true; this.runtime.YPageSvc.UnbindEvents(this.eventProxy); this.runtime.WPageSvc.UnbindEvents(this.eventProxy); this.runtime.LogSvc.UnbindEvents(this.eventProxy); this.runtime.MessageSvc.UnbindEvents(this.eventProxy); this.runtime.PersistenceSvc.UnbindEvents(this.eventProxy); this.runtime.MessageSvc.OnIncomingConversation -= this.convHandler; this.eventProxy.bForwardEvents = false; } # endregion # region Manage Agent Knowledges /// /// Locks a knowledge instance to be used by a behaviour instance. /// /// behaviour instance that wants to use the knowledge instances /// list of knowledge instancess to be locked public void LockKnowledge(AgentService.Agent.Behaviour.Behaviour lockingBehaviour,params Knowledge.Knowledge[] myKnowledgeList) { lock(this.knowledges) { // check if behavior has already locked some knowledge for deadlock avoidance foreach(Knowledge.Knowledge k in this.knowledges) { if(k.IsLockedBy(lockingBehaviour)) { throw new KnowledgeLockedException(k.Name); } } // search for the knowledge to be ordered and locked foreach(Knowledge.Knowledge kN in myKnowledgeList) { foreach(Knowledge.Knowledge know in this.knowledges) { if(know.Name.Equals(kN.Name)) { if(!know.IsLocked) { know.Lock(lockingBehaviour); break; } else { lockingBehaviour.ReleaseKnowledge(true); throw new KnowledgeLockedException(know.Name); } } } } } } /// /// Persists the changes for a given Knowledge's item. /// ///knowledge object which fired the update event public void PersistChanges(object sender) { Knowledge.Knowledge know = sender as Knowledge.Knowledge; if(know != null) { lock(this.knowledges) { if(this.knowledges.Contains(know)) { this.runtime.PersistenceSvc.PersistKnowledge(know); } } } else { //TODO: log sender is null or is not a knowlegde } } /// /// Releases the knowledge instances previously locked by a behaviour instance. /// /// behaviour instance that releases the Knowledge public void ReleaseKnowledge(AgentService.Agent.Behaviour.Behaviour releaseBehaviour) { lock(this) { bool lockFlag = true; foreach(Knowledge.Knowledge know in this.knowledges) { if(know.IsLockedBy(releaseBehaviour)) { know.UnLock(); lockFlag = false; // Mettici il log //Console.WriteLine(String.Format("{0} : Resource {1} released by {2}", this.aid.Name, k.know.GetName(), releaseBehaviour.GetName())); } } if(lockFlag) { throw new KnowledgeUnlockedException(releaseBehaviour.Name); } } } # endregion } }