/*********************************************************************/
/* */
/* 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
}
}