package dz.esi.edma.noyau;
import java.awt.Color;
import java.awt.Image;
import java.awt.Toolkit;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
import javax.swing.ImageIcon;
import javax.swing.border.MatteBorder;
import dz.esi.edma.interfacegraphique.Interface;
import dz.esi.edma.interfacegraphique.JInternalFrameAgent;
import dz.esi.edma.interfacegraphique.JPanelAgent;
import dz.esi.edma.noyau.message.IMCompetence;
import dz.esi.edma.noyau.message.IMessage;
import dz.esi.edma.noyau.message.MCCompetence;
import dz.esi.edma.noyau.message.MMCompetence;
import dz.esi.edma.noyau.message.MMObjet;
import dz.esi.edma.noyau.message.MMString;
import dz.esi.edma.noyau.message.MMessage;
import dz.esi.edma.noyau.message.Message;
/**
* La classe de base de tous les agents. Elle crée un agent Atomique comportant
* toutes les informations nécessaires pour son bon fonctionnement:
*
Un identificateur unique.
* Un thread de contrôle.
* Un cycle de vie qui définit son état.
* Une boîte aux lettres (BAL) qui contient des messages.
* Une table d’agents (TA).
* Une table de compétences réactives.
* Une table de compétences proactives.
* Une file des tâches.
* Deux compétences initiales : une pour communiquer avec ses semblables et
* une autre pour apprendre de nouvelles compétences.
*
* @author Aroussi Sanaa
* @author Guessoum Lamia
* @version 1.0 2009
*/
public class AgentAtomique implements Runnable, Acquisition, Communication,
Graphique {
/*
* LES CLASSES INTERNES
*/
/* Définir le cycle de vie actif */
private class CycleDeVieActif extends CycleDeVie {
/* Spécifier la cause d'attente */
private int causeAttente = 0;
private CycleDeVieActif() {
super(Initial);
}
/*
* Changer l'état initial à actif, l'état actif à attente ou l'état
* attente à actif
*/
protected void setEtat(int etat, int cause) {
this.etat = etat;
if (etat == Attente)
causeAttente = cause;
else
causeAttente = 0;
setEtatEntree();
}
/* Exécuter une tâche */
protected void execute() {
ObjetCompétence O = null;
if (filedestaches.isEmpty())
cycleDeVieCourant.setEtat(Attente, TacheAExecuter);
try {
O = filedestaches.take();
} catch (InterruptedException e1) {
/*
* Le thread du contrôle sera interrompu en appelant la méthode
* suspendre ou supprimer
*/
return;/* Sortir de la méthode */
}
if (O != null) {
try {
URL chemins[] = { new URL(O.getchemin()) };
URLClassLoader loader = new URLClassLoader(chemins);
Class cl = loader.loadClass(O.getnom());
Constructor[] ct = cl.getConstructors();
Constructor cons = null;
for (int i = 0; i < ct.length; i++) {
//System.out.println(ct[i].toString());
if ((ct[i].getParameterTypes().length == 1)
&& (ct[i].getParameterTypes()[0]
.equals(String.class))) {
cons = ct[i];
// System.out.println("ok");
break;
}
}
Object o = null;
if (cons != null) {
//System.out.println("Avec paramètre");
Object[] arg = new String[] { AgentAtomique.this
.getNom() };
o = cons.newInstance(arg);
} else {
o = cl.newInstance();
}
Class[] arg = null;
Object[] arg1 = null;
if (O.getParametre() != null) {
Object type[] = O.getParametre();
arg = new Class[type.length];
for (int i = 0; i < type.length; i++) {
arg[i] = type[i].getClass();
}
arg1 = type;
}
Method m = o.getClass().getMethod(O.getMethode(), arg);
if (m != null)
m.invoke(o, arg1);
} catch (SecurityException e) {
afficherErreur(e);
} catch (IllegalArgumentException e) {
afficherErreur(e);
} catch (NoSuchMethodException e) {
afficherErreur(e);
} catch (ClassNotFoundException e) {
afficherErreur(e);
} catch (InstantiationException e) {
afficherErreur(e);
} catch (IllegalAccessException e) {
afficherErreur(e);
} catch (MalformedURLException e) {
afficherErreur(e);
} catch (InvocationTargetException e) {
afficherErreur(e);
}
}
/* Le point interruptible de l'agent */
synchronized (mutex) {
if (cycleDeVieProchain != null) {
cycleDeVieCourant = cycleDeVieProchain;
cycleDeVieProchain = null;
setEtatEntree();
}
}
}
protected void activer() {
/* Réveiller le thread du contrôle */
synchronized (block) {
block.notifyAll();
}
}
}
/* Définir le cycle de vie suspendu */
private class CycleDeVieSuspendu extends CycleDeVie {
private CycleDeVieSuspendu() {
super(Suspendu);
}
/* Suspendre l'agent */
protected void execute() {
/* Bloquer le thread du contrôle */
synchronized (block) {
try {
block.wait();
} catch (InterruptedException e) {
afficherErreur(e);
}
}
}
}
/* Définir le cycle de vie supprimé */
private class CycleDeVieSupprime extends CycleDeVie {
private CycleDeVieSupprime() {
super(Supprime);
}
/*
* Annuler l'inscription auprés AMS, supprimer les compétences auprés DF
* et libérer les ressources
*/
protected void fin() {
/* desinscription auprés AMS */
RequeteAMS msg = new RequeteAMS(RequeteAMS.ANNULER_INSCRIPTION,
AgentAtomique.this, null);
try {
if ((Boolean) AMS.getDescription().Executer(msg).get())
setEtatEntree();
} catch (InterruptedException e) {
afficherErreur(e);
} catch (ExecutionException e) {
afficherErreur(e);
}
/*supprimer les compétences*/
Iterator iter = new ArrayList(nomCompetences).iterator();
while (iter.hasNext())
{
supprimerCompetence(iter.next());
}
/* Nettoyer les structures de données */
TA=null;
BAL=null;
filedestaches=null;
cycleDeVieProchain=null;
cycleDeVieSupprime=null;
cycleDeVieSuspendu=null;
cycleDeVieActif=null;
competencesReactives=null;
competencesProactives=null;
}
protected boolean EstEnVie() {
return false;
}
protected void activer() {
/* Réveiller le thread du contrôle */
synchronized (block) {
block.notifyAll();
}
}
}
/*
* LES CONSTANTES
*/
/**
* Définit la priorité minimale qu’un agent peut avoir. La valeur de la
* priorité minimale est 1.
*/
public final static int MIN_PRIORITE = Thread.MIN_PRIORITY;
/**
* Définit la priorité par défaut d’un agent. La valeur de la priorité par
* défaut est 5.
*/
public final static int NORM_PRIORITE = Thread.NORM_PRIORITY;
/**
* Définit la priorité maximale qu’un agent peut avoir. La valeur de la
* priorité maximale est 10.
*/
public final static int MAX_PRIORITE = Thread.MAX_PRIORITY;
/**
* Constante pour définir l'état de l'agent.
*/
public static final int Initial = 1;
/**
* Constante pour définir l'état de l'agent.
*/
public static final int Actif = 2;
/**
* Constante pour définir l'état de l'agent.
*/
public static final int Attente = 3;
/* Les trois causes d'attente */
private static final int EnvoiMessage = 1;
private static final int ReceptionMessage = 2;
private static final int TacheAExecuter = 3;
/**
* Constante pour définir l'état de l'agent.
*/
public static final int Suspendu = 4;
/**
* Constante pour définir l'état de l'agent.
*/
public static final int Supprime = 5;
/** Le composant graphique où les agents seront inserés */
private static Object environnementGraphique = null;
/*
* LES VARIABLES
*/
/* La date de création de l'agent */
private Date dateDeCreation = null;
/* L'identificateur de l'agent */
AID aid = null;
/* Le thread de contrôle de l'agent */
Thread thread = null;
/* La priorité de l'agent */
private int priorite = -1;
/* L'ordre d'arrivé des compétences à exécuter */
private static int ordreArrivé = 1;
/* La boite aux lettres de l'agent */
private LinkedBlockingQueue BAL = null;
/* La capacité de la boite aux lettres de l'agent */
private int capacite = 0;
/*
* La base de données de l'agent. Elle contient les descripteurs des agents
* qu'il a déjà communiqué avec eux.
*/
private ArrayList TA = null;
/* La file des tâches de l'agent */
PriorityBlockingQueue filedestaches = null;
/* Les compétences réactives de l'agent */
private HashMap competencesReactives = null;
/* Les compétences proactives de l'agent */
private HashMap competencesProactives = null;
/* Les nom des compétence de l'agent */
private ArrayList nomCompetences = null;
/* Le cycle de vie courant */
CycleDeVie cycleDeVieCourant = null;
/*
* Le prochain cycle de vie qui est nécessaire dans le cas où l'agent
* exécute une tâche et nous voulons changer son état
*/
private CycleDeVie cycleDeVieProchain = null;
/* Le cycle de vie actif */
private CycleDeVie cycleDeVieActif = null;
/* Le cycle de vie supprimé */
private CycleDeVie cycleDeVieSupprime = null;
/* Le cycle de vie suspendu */
private CycleDeVie cycleDeVieSuspendu = null;
/* Un objet qui sert à suspendre le thread et le réveiller */
private Object block = null;
/*
* Un objet qui sert à protéger le cycle de vie courant et le prochain cycle
* de vie
*/
private Object mutex = null;
/* Le composant graphique qui représente l'agent : L'entrée à l'agent */
private Object entree = null;
/*
* Le composant graphique où l'agent affiche ses résultats : La sortie de
* l'agent
*/
private Object sortie = null;
/*
* CONSTRUCTEURS
*/
AgentAtomique(boolean inscrire, AID nouvAID, int nouvCapacite,
int nouvPriorite) throws Exception {
if (! inscrire) {
try {
cycleDeVieCourant = cycleDeVieActif = new CycleDeVieActif();
dateDeCreation = new Date();
aid = nouvAID;
thread = new Thread(this);
block = new Object();
mutex = new Object();
thread.setPriority(nouvPriorite);
priorite = nouvPriorite;
capacite = nouvCapacite;
BAL = new LinkedBlockingQueue(nouvCapacite);
TA = new ArrayList();
competencesProactives = new HashMap();
competencesReactives = new HashMap();
nomCompetences = new ArrayList();
filedestaches = new PriorityBlockingQueue();
} catch (Exception e) {
throw new Exception();
}
}
}
/**
*Créer un agent atomique en spécifiant son nom, la capacité de sa boite
* aux lettre, et sa priorité.
*
* @param nouvNom
* le nom de l'agent
* @param nouvCapacite
* la capacité de la boite aux lettres de l'agent.
* @param nouvPriorite
* la priorité de l'agent.
* @throws Exception
* lorsque la création de l'agent échoue
*/
public AgentAtomique(AID nouvAID, int nouvCapacite, int nouvPriorite)
throws Exception {
try {
cycleDeVieCourant = cycleDeVieActif = new CycleDeVieActif();
dateDeCreation = new Date();
aid = nouvAID;
thread = new Thread(this);
block = new Object();
mutex = new Object();
thread.setPriority(nouvPriorite);
priorite = nouvPriorite;
capacite = nouvCapacite;
BAL = new LinkedBlockingQueue(nouvCapacite);
TA = new ArrayList();
competencesProactives = new HashMap();
competencesReactives = new HashMap();
nomCompetences = new ArrayList();
filedestaches = new PriorityBlockingQueue();
getEntree(); /* appelle automatiquement getSortie */
RequeteAMS msg = new RequeteAMS(RequeteAMS.INSCRIRE, this, null);
if (!(Boolean) AMS.getDescription().Executer(msg).get())
throw new Exception();
} catch (Exception e) {
throw e;
}
ajouterEntree();
ajouterSortie();
}
/**
* Créer un agent atomique avec ses propriétés par défaut.
*
* @throws Exception
* lorsque la création de l'agent échoue
*/
public AgentAtomique() throws Exception {
this(new AID("Agent" + AMS.getNbrAgentsCrees()), Integer.MAX_VALUE,
NORM_PRIORITE);
}
/**
* Créer un agent atomique en spécifiant son nom.
*
* @param nouvNom
* le nom de l'agent
* @throws Exception
* lorsque la création de l'agent échoue
*/
public AgentAtomique(String nouvNom) throws Exception {
this(new AID(nouvNom), Integer.MAX_VALUE, NORM_PRIORITE);
}
/**
* Créer un agent atomique en spécifiant la capacité de sa BAL.
*
* @param nouvCapacite
* la capacité de la boite aux Lettres de l'agent
* @throws Exception
* lorsque la création de l'agent échoue
*/
public AgentAtomique(int nouvCapacite) throws Exception {
this(new AID("Agent" + AMS.getNbrAgentsCrees()), nouvCapacite,
NORM_PRIORITE);
}
/**
* Créer un agent atomique en spécifiant son nom et la capacité de sa BAL.
*
* @param nouvNom
* le nom de l'agent
* @param nouvCapacite
* la capacité de la boite aux Lettres de l'agent
* @throws Exception
* lorsque la création de l'agent échoue
*/
public AgentAtomique(String nouvNom, int nouvCapacite) throws Exception {
this(new AID(nouvNom), nouvCapacite, NORM_PRIORITE);
}
/*
* CYCLE DE VIE
*/
/** Suspendre l'exécution de l'agent. */
public final void suspendre() {
synchronized (mutex) {
if (cycleDeVieCourant.equals(cycleDeVieActif)) {
if (cycleDeVieSuspendu == null)
cycleDeVieSuspendu = new CycleDeVieSuspendu();
if (((CycleDeVieActif) cycleDeVieCourant).causeAttente == TacheAExecuter) {
cycleDeVieCourant = cycleDeVieSuspendu;
thread.interrupt();
setEtatEntree();
} else
cycleDeVieProchain = cycleDeVieSuspendu;
}
}
}
/** Reprendre l'éxecution de l'agent. */
public final void reprendre() {
synchronized (mutex) {
if (cycleDeVieCourant.equals(cycleDeVieSuspendu)) {
/* positionner le cycle de vie(execute) */
cycleDeVieCourant = cycleDeVieActif;
/* réveiller le thread du contrôle */
cycleDeVieCourant.activer();
setEtatEntree();
}
}
}
/**
* Supprimer l'agent.
*/
public final void supprimer() {
if (cycleDeVieSupprime == null)
cycleDeVieSupprime = new CycleDeVieSupprime();
synchronized (mutex) {
if (cycleDeVieCourant.equals(cycleDeVieSuspendu)) {
/* Positionner le cycle de vie (estEnVie) */
cycleDeVieCourant = cycleDeVieSupprime;
/* réveiller le thread du contrôle s'il est bloqué */
cycleDeVieCourant.activer();
}
if (cycleDeVieCourant.equals(cycleDeVieActif)) {
/* S'il est en attente d'une tâche à réaliser */
if (((CycleDeVieActif) cycleDeVieCourant).causeAttente == TacheAExecuter) {
cycleDeVieCourant = cycleDeVieSupprime;
thread.interrupt();
} else
cycleDeVieProchain = cycleDeVieSupprime;
}
}
}
public final void run() {
while (cycleDeVieCourant.EstEnVie()) {
cycleDeVieCourant.execute();
}
cycleDeVieCourant.fin();
}
/*
* LES METHODES CONCERNANT L'INTERFACE ACQUISITION
*/
public final boolean ajouterCompetence(String nom,String chemin,boolean execute)
{
if((getEtat()!=Supprime) &&(!nomCompetences.contains(nom)))
{
try{
URL chemins[] = { new URL(chemin) };
URLClassLoader loader = new URLClassLoader(chemins);
Class cl=loader.loadClass(nom);
Class c = cl.getSuperclass();
if ((c.getName()).equals("dz.esi.edma.noyau.competences.Compétence"))
{
if (!competencesReactives.containsKey(nom)) {
if(enregistrerCompetence(nom, chemin))
{
competencesReactives.put(nom, chemin);
nomCompetences.add(nom);
MAJlistCompetence(true, nom);
return true;
}
}
else
{return false;}
}
else
if((c.getName()).equals("dz.esi.edma.noyau.competences.CompétenceAction"))
{
if (!competencesProactives.containsKey(nom))
{
competencesProactives.put(nom, chemin);
nomCompetences.add(nom);
MAJlistCompetence(true, nom);
if(execute)
{
ObjetCompétence O = new ObjetCompétence(nom, chemin, "Action",
null, 0, ordreArrivé);
filedestaches.put(O);
ordreArrivé++;
}
}
else
return false;
}
else
return false;
}
catch (SecurityException e) {
return false;
} catch (IllegalArgumentException e) {
return false;
} catch (ClassNotFoundException e) {
return false;
} catch (MalformedURLException e) {
return false;
}
}
return false;
}
public final boolean enseignerCompetence(String competence,
AgentAtomique recepteur) {
if ((competencesReactives.containsKey(competence))
&& (recepteur != null)) {
MCCompetence contenu = new MCCompetence(competence,
competencesReactives.get(competence), null, null);
MMCompetence msg = new MMCompetence(contenu, MMCompetence.ENSEIGNER);
msg.addRecepteurs(recepteur);
msg.setEmetteur(this);
return envoyerEnUrgence(msg);
} else
return false;
}
public final boolean enseignerCompetence(String competence, AID recepteur) {
if ((competencesReactives.containsKey(competence))
&& (recepteur != null)) {
MCCompetence contenu = new MCCompetence(competence,
competencesReactives.get(competence), null, null);
MMCompetence msg = new MMCompetence(contenu, MMCompetence.ENSEIGNER);
msg.addRecepteurs(recepteur);
msg.setEmetteur(this);
return envoyerEnUrgence(msg);
} else
return false;
}
public final boolean executerCompetence(String competence, String methode,
Object[] args) {
if(getEtat()!=Supprime)
if (competencesProactives.containsKey(competence)) {
String chemin = competencesProactives.get(competence);
ObjetCompétence O = new ObjetCompétence(competence, chemin,
"Action", null, 0, ordreArrivé);
filedestaches.put(O);
ordreArrivé++;
return true;
}
else
if (competencesReactives.containsKey(competence)) {
try {
URL chemins[] = { new URL(competencesReactives.get(competence)) };
URLClassLoader loader = new URLClassLoader(chemins);
Class cl = loader.loadClass(competence);
Method[] M = cl.getDeclaredMethods();
//System.out.println("le nombre des méthodes "+M.length);
for (int i = 0; i < M.length; i++) {
boolean trouve = true;
if (M[i].getName().equals(methode)) {
Class[] paramTypes = null;
Class[] argument = new Class[M[i].getParameterTypes().length];
if (args != null) {
paramTypes = new Class[args.length];
for (int j = 0; j < args.length; j++) {
paramTypes[j] = args[j].getClass();
}
}
for (int j = 0; j < M[i].getParameterTypes().length; j++) {
argument[j] = M[i].getParameterTypes()[j];
}
for (int l = 0; l < argument.length; l++) {
if (!(argument[l].toString()).equals(paramTypes[l].toString()))
{
trouve = false;
}
if (trouve) {
ObjetCompétence O = new ObjetCompétence(competence,
competencesReactives.get(competence), methode,
args, 1, ordreArrivé);
filedestaches.put(O);
ordreArrivé++;
return true;
}
}
}
}
} catch (SecurityException E) {
return false;
} catch (IllegalArgumentException E) {
return false;
} catch (ClassNotFoundException E) {
return false;
} catch (MalformedURLException E) {
return false;
}
}
return false;
}
public final boolean traiterMessageCompetence(IMCompetence msg) {
String competence = msg.getContenu().getNomCompetence();
String chemin = msg.getContenu().getChemin();
String methode = msg.getContenu().getNomMethode();
Object[] arg = msg.getContenu().getArgumentsMethode();
Object emetteur = msg.getEmetteur();
switch (msg.getPerformative()) {
case IMCompetence.EXECUTER: /* Exécuter une compétence */
return executerCompetence(competence, methode, arg);
case IMCompetence.DEMANDE_ENSEIGNER:
/*Demande d'enseigner une compétence */
if (emetteur instanceof AID)
return enseignerCompetence(competence, (AID) emetteur);
else
if(emetteur instanceof AgentAtomique)
return enseignerCompetence(competence,(AgentAtomique) emetteur);
case IMCompetence.ENSEIGNER: /* Enseigner une compétence */
{
return ajouterCompetence(competence, chemin,false);
}
case IMCompetence.NECOMPRENDPAS:{}
default:{
if(emetteur != null)
{
MMCompetence msg1=new MMCompetence(msg.getContenu(),MMCompetence.NECOMPRENDPAS);
msg1.setEmetteur(this);
if (emetteur instanceof AID)
msg1.addRecepteurs((AID) emetteur);
else
msg1.addRecepteurs((AgentAtomique) emetteur);
return envoyerEnUrgence(msg1);
}
}
}
return false;
}
@SuppressWarnings("static-access")
public final boolean supprimerCompetence(String nom) {
if (competencesReactives.containsKey(nom)) {
String chemin = competencesReactives.get(nom);
competencesReactives.remove(nom);
supprimerCompetenceduDF(nom, chemin);
nomCompetences.remove(nom);
MAJlistCompetence(false, nom);
return true;
}
else
{
if(competencesProactives.containsKey(nom))
{
competencesProactives.remove(nom);
nomCompetences.remove(nom);
MAJlistCompetence(false, nom);
return true;
}
else {
ecrireConsole("La Compétence " + nom + " n'existe pas\r\n");
return false;
}
}
}
/*
* LES METHODES DE L'INTERFACE COMMUNICATION
*/
public final boolean envoyer(Message msg) {
return envoyer(msg, 0, TimeUnit.NANOSECONDS);
}
public final boolean envoyerEnUrgence(Message msg) {
return envoyer(msg, -1, TimeUnit.NANOSECONDS);
}
public final boolean envoyer(Message msg, long timeOut, TimeUnit unite) {
/*
* 0- Vérifier que timeOut >0 ou == 0(mode d'envoi immédiat) ou ==
* -1(mode d'envoi attente jusqu'à non pleine)
*/
if ((timeOut < 0) && (timeOut != -1))
return false;
/* 1- Vérifier qu'il existe au moins un récepteur pour le message */
if (msg.getRecepteurs().size() == 0)
return false;
/*
* 2- Vérifier que le contenu du message MMString, MMObjet et
* MMCompétence sont non null. Pour le contenu du IMString, IMObjet et
* IMCompétence sont tjrs non nulls. Cette vérification est faite dans
* leurs constructeurs. La plupart des messages ACL exigent le parametre
* content. Certains types de message (selon la performative), ont
* implicitement le contenu.
*/
if ((msg instanceof MMString)
&& (((MMString) msg).getContenu() == null))
return false;
if ((msg instanceof MMObjet) && (((MMObjet) msg).getContenu() == null))
return false;
if ((msg instanceof MMCompetence)
&& (((MMCompetence) msg).getContenu() == null))
return false;
/*
* 3- Transformer le message mutable en message immuable (s'il n'est
* pas)
*/
Message msg1 = msg;
if (msg instanceof MMessage)
msg1 = ((MMessage) msg).toImmuable();
/* Le processus d'envoi */
for (int i = 0; i < msg1.getNbrRecepteurs(); i++) {
Object recepteur = msg1.getRecepteurs().get(i);
/* 4 - Vérifier que l'émetteur n'envoi pas le message à lui même */
if (recepteur.equals(this)) {
/*
* 10- Mettre à jour l'accusé de réception : Echec d'envoi
*/
msg.getAccuseReception().set(i, false);
continue;
}
AgentAtomique agentRecepteur = null;
if (recepteur instanceof AID) {
/*
* 5- Recherche locale
*/
int j = TA.indexOf(recepteur);
if (j != -1) {
agentRecepteur = TA.get(j);
if (agentRecepteur.getEtat() == Supprime) {
/* l'agent est supprimé */
/* MAJ TA */
TA.remove(i);
/* Echec d'envoi */
msg.getAccuseReception().set(i, false);
continue;
}
} else {
/*
* 6- recherche globale
*/
agentRecepteur = (AgentAtomique) rechercher((AID) recepteur);
if (agentRecepteur == null) {
/* l'agent est supprimé */
/* Echec d'envoi */
msg.getAccuseReception().set(i, false);
continue;
} else {
/* MAJ TA */
TA.add(agentRecepteur);
}
}
} else {
agentRecepteur = (AgentAtomique) recepteur;
if (!TA.contains(agentRecepteur))
/* MAJ TA */
TA.add(agentRecepteur);
}
/* mode d'envoi immédiat */
if (timeOut == 0) {
/* Déposer le message et MAJ accusé de réception */
msg.getAccuseReception().set(i, agentRecepteur.BAL.offer(msg1));
continue;
}
/* mode d'envoi attente jusqu'à non plein */
if (timeOut == -1) {
cycleDeVieCourant.setEtat(Attente, EnvoiMessage);
try {
/* Déposer le message */
agentRecepteur.BAL.put(msg1);
/* Accusé de Réception positif */
msg.getAccuseReception().set(i, true);
} catch (InterruptedException e) {
/* cas impossible */
msg.getAccuseReception().set(i, false);
}
cycleDeVieCourant.setEtat(Actif, 0);
continue;
}
/* mode d'envoi attente jusqu'à timeOut */
cycleDeVieCourant.setEtat(Attente, EnvoiMessage);
try {
/* Déposer le message et MAJ accusé de réception */
msg.getAccuseReception().set(i,
agentRecepteur.BAL.offer(msg1, timeOut, unite));
} catch (InterruptedException e) {
/* cas impossible */
msg.getAccuseReception().set(i, false);
}
cycleDeVieCourant.setEtat(Actif, 0);
}
return true;
}
public final boolean diffuser(Message msg) {
return diffuser(msg, 0, TimeUnit.NANOSECONDS);
}
public final boolean diffuserEnUrgence(Message msg) {
return diffuser(msg, -1, TimeUnit.NANOSECONDS);
}
/*
* L'émetteur demande une copie de répertoire de AMS, puis il envoi le msg à
* chaque agent, en utilisant la méthode Envoyer(Message, long, Timeunit);
*/
public final boolean diffuser(Message msg, long timeMoyenne, TimeUnit unite) {
if (msg instanceof IMessage)
msg = ((IMessage) msg).toMutable();
((MMessage) msg).clearRecepteurs();
Iterator iter = AMS.getAgents().iterator();
((MMessage) msg).addRecepteurs(iter);
return envoyer(msg, timeMoyenne, unite);
}
public final Message recevoir() {
return BAL.poll();
}
public final Message recevoir(long timeOut, TimeUnit unite)
throws InterruptedException {
if (timeOut < 0)
return null;
Message msg = null;
cycleDeVieCourant.setEtat(Attente, ReceptionMessage);
try {
msg = BAL.poll(timeOut, unite);
} catch (InterruptedException e) {
afficherErreur(e);
}
cycleDeVieCourant.setEtat(Actif, 0);
return msg;
}
public final Message recevoirEnUrgence() {
Message msg = null;
cycleDeVieCourant.setEtat(Attente, ReceptionMessage);
try {
msg = BAL.take();
return msg;
} catch (InterruptedException e) {
afficherErreur(e);
}
cycleDeVieCourant.setEtat(Actif, 0);
return msg;
}
/*
* LES METHODES CONCERNANT LA BOITE AUX LETTRES
*/
/**
* @return le nombre des messages dans la boite aux lettre de l'agent
* @see #getCapacite()
* @see #getCapaciteRestantBAL()
*/
public final int getNbrEltBAL() {
return BAL.size();
}
/**
* @return true si la boite aux lettres de l'agent est vide
*
* sinon false
*
* @see #BALPleine()
*/
public final boolean BALVide() {
return BAL.isEmpty();
}
/**
* @return true si la boite aux lettres de l'agent est pleine
*
* sinon false
*
* @see #BALVide()
*/
public final boolean BALPleine() {
return (BAL.size() == capacite);
}
/**
* @return le nombre des messages restants à ajouter dans la boite aux
* lettres de l'agent.
* @see #getCapacite()
* @see #getNbrEltBAL()
*/
public final int getCapaciteRestantBAL() {
return BAL.remainingCapacity();
}
/**
* Vider la boite aux lettres de l'agent.
*/
public final void viderBAL() {
BAL.clear();
}
/*
* LES METHODES CONCERNANT AID
*/
/**
* @return le nom local de l'agent.
*/
public final String getNom() {
return aid.nom;
}
/**
* @return le nom global de l'agent.
*/
public final String getGUID() {
return aid.getGUID();
}
/*
* LES METHODES NECESSITANT AMS
*/
/**
* Modifier le nom local de l'agent.
*
* @param nouvNom
* le nouveau nom local de l'agent
* @return true si le nouvNom
n'existe pas pour un autre
* agent.
*
* false sinon.
*
*/
public final boolean setNom(String nouvNom) {
if (nouvNom == null) return false;
RequeteAMS msg = new RequeteAMS(RequeteAMS.MODIFIER, this, new AID(
nouvNom));
try {
return ((Boolean) AMS.getDescription().Executer(msg).get());
} catch (InterruptedException e) {
return false;
} catch (ExecutionException e) {
return false;
}
}
/**
* Rechercher le descripteur d'un autre agent.
*
* @param aid
* l'identificateur de l'agent à rechercher
* @return le descripteur de l'agent qui correspond à aid
* sinon null.
*/
public static final AgentAtomique rechercher(AID aid) {
if (aid == null)
return null;
RequeteAMS msg = new RequeteAMS(RequeteAMS.RECHERCHER, null, aid);
try {
return (AgentAtomique) AMS.getDescription().Executer(msg).get();
} catch (InterruptedException e) {
return null;
} catch (ExecutionException e) {
return null;
}
}
/**
* Créer un fils.
* Si l'identificateur AID
est null alors le fils
* possédera un identificateur par défaut.
*
* @param fils
* l'identificateur correspondant au fils.
* @return le descripteur de fils s'il est bien crée.
*
* null sinon
*
*/
public final AgentAtomique creerFils(AID fils) {
RequeteAMS msg = new RequeteAMS(RequeteAMS.CREER, this, fils);
try {
AgentAtomique a = ((AgentAtomique) AMS.getDescription().Executer(
msg).get());
if (a != null) {
a.getEntree();
a.ajouterEntree();
a.ajouterSortie();
}
return a;
} catch (InterruptedException e) {
return null;
} catch (ExecutionException e) {
return null;
}
}
public final AgentAtomique creerFils(AID fils, int capacite, int priorite) {
RequeteAMS msg = new RequeteAMS(RequeteAMS.CREER, this, fils);
if (capacite < 0)
return null;
if ((priorite > MAX_PRIORITE) || (priorite < MIN_PRIORITE))
return null;
msg.capacite = capacite;
msg.priorite = priorite;
try {
AgentAtomique a = ((AgentAtomique) AMS.getDescription().Executer(
msg).get());
if (a != null) {
a.getEntree();
a.ajouterEntree();
a.ajouterSortie();
}
return a;
} catch (InterruptedException e) {
return null;
} catch (ExecutionException e) {
return null;
}
}
/**
* Suspendre le fils qui correspond à l'identificateur fils
*
* @param fils
* l'identificateur du fils
* @return true si l'agent fils
est suspendu
*
* false sinon.
*
*/
public final boolean suspendreFils(AID fils) {
if (fils == null)
return false;
RequeteAMS msg = new RequeteAMS(RequeteAMS.SUSPENDRE, this, fils);
try {
return ((Boolean) AMS.getDescription().Executer(msg).get());
} catch (InterruptedException e) {
return false;
} catch (ExecutionException e) {
return false;
}
}
/**
* Réveiller le fils qui correspond à l'identificateur fils
*
* @param fils
* l'identificateur du fils
* @return true si l'agent fils
est réveillé
*
* false sinon.
*
*/
public final boolean reprendreFils(AID fils) {
if (fils == null)
return false;
RequeteAMS msg = new RequeteAMS(RequeteAMS.REPRENDRE, this, fils);
try {
return ((Boolean) AMS.getDescription().Executer(msg).get());
} catch (InterruptedException e) {
return false;
} catch (ExecutionException e) {
return false;
}
}
/**
* Supprimer le fils qui correspond à l'identificateur fils
*
* @param fils
* l'identificateur du fils
* @return true si l'agent fils
est tué
*
* false sinon.
*
*/
public final boolean supprimerFils(AID fils) {
if (fils == null)
return false;
RequeteAMS msg = new RequeteAMS(RequeteAMS.SUPPRIMER, this, fils);
try {
return ((Boolean) AMS.getDescription().Executer(msg).get());
} catch (InterruptedException e) {
return false;
} catch (ExecutionException e) {
return false;
}
}
/*
* LES METHODES CONCERNANT DF
*/
private boolean enregistrerCompetence(String nom, String chemin)
throws IllegalArgumentException {
try {
URL chemins[] = { new URL(chemin) };
URLClassLoader loader = new URLClassLoader(chemins);
Class cl = loader.loadClass(nom);
Method[] M = cl.getDeclaredMethods();
for (int i = 0; i < M.length; i++) {
Object[] arg = null;
if (M[i].getParameterTypes() != null) {
arg = new Object[M[i].getParameterTypes().length];
for (int j = 0; j < M[i].getParameterTypes().length; j++)
arg[j] = M[i].getParameterTypes()[j];
}
RequeteDF requete = new RequeteDF(RequeteDF.ENREGISTRER, nom,
M[i].getName(), arg, aid);
try {
if (!(Boolean) (DF.getDescription().Executer(requete).get()))
throw new IllegalArgumentException();
} catch (InterruptedException e) {
return false;
} catch (ExecutionException e) {
return false;
}
}
return true;
} catch (SecurityException e) {
ecrireConsole(e.getMessage()+" "+e.getCause());
return false;
} catch (IllegalArgumentException e) {
ecrireConsole(e.getMessage()+" "+e.getCause());
return false;
} catch (ClassNotFoundException e) {
ecrireConsole("La classe"+e.getMessage()+ "n'existe pas");
return false;
} catch (MalformedURLException e) {
ecrireConsole(e.getMessage()+" "+e.getCause());
return false;
}
}
public static ArrayList rechercherMethode(String nomCompetence,
String nomMethode) {
if ((nomMethode == null) || (nomCompetence == null))
return null;
else {
RequeteDF requete = new RequeteDF(RequeteDF.CHERCHERSANSPARAMETRES,
nomCompetence, nomMethode, null, null);
try {
return (ArrayList) DF.getDescription().Executer(requete).get();
} catch (InterruptedException e) {
return null;
} catch (ExecutionException e) {
return null;
}
}
}
public static AID[] rechercherMethode(String nomCompetence,
String nomMethode, Object[] args) {
if ((nomMethode == null) || (nomCompetence == null))
return null;
else {
RequeteDF requete = new RequeteDF(RequeteDF.CHERCHERAVECPARAMETRES,
nomCompetence, nomMethode, args, null);
try {
return (AID[]) DF.getDescription().Executer(requete).get();
} catch (InterruptedException e) {
return null;
} catch (ExecutionException e) {
return null;
}
}
}
private void supprimerCompetenceduDF(String nom, String chemin) throws IllegalArgumentException{
try {
URL chemins[] = { new URL(chemin) };
URLClassLoader loader = new URLClassLoader(chemins);
Class cl = loader.loadClass(nom);
Method[] M = cl.getDeclaredMethods();
for (int i = 0; i < M.length; i++) {
Object[] arg = null;
if (M[i].getParameterTypes() != null) {
arg = new Object[M[i].getParameterTypes().length];
for (int j = 0; j < M[i].getParameterTypes().length; j++)
arg[j] = M[i].getParameterTypes()[j];
}
RequeteDF requete = new RequeteDF(RequeteDF.SUPPRIMER, nom,
M[i].getName(), arg, aid);
try {
if (!(Boolean) (DF.getDescription().Executer(requete).get()))
throw new IllegalArgumentException();
//System.out.println("Retourner faux");
} catch (InterruptedException e) {
afficherErreur(e);
} catch (ExecutionException e) {
afficherErreur(e);
}
}
} catch (SecurityException e) {
afficherErreur(e);
} catch (IllegalArgumentException e) {
afficherErreur(e);
} catch (ClassNotFoundException e) {
afficherErreur(e);
} catch (MalformedURLException e) {
afficherErreur(e);
}
}
/*
* LES GETTERS DES VARAIBLES
*/
/**
* @return la capacité de la boite aux lettres de l'agent
* @see #getNbrEltBAL()
* @see #getCapaciteRestantBAL()
*/
public final int getCapacite() {
return capacite;
}
/**
* @return la priorité de l'agent.
*/
public final int getPriorite() {
return (priorite);
}
/**
* @return une copie de la table des agents.
*/
@SuppressWarnings("unchecked")
public final ArrayList getTA() {
return (ArrayList) TA.clone();
}
/**
* @return true si l'agent a communiqué avec le DF sinon false.
*/
public final boolean isCommuniquerDF() {
return aid.communiquerDF;
}
/**
* @return la date de création de l'agent.
*/
public final Date getDateDeCreation() {
return dateDeCreation;
}
/**
* @param priorite
* la priorité de l'agent.
* @return la priorité de l'agent sous forme d'une chaîne de caractère.
*/
public static final String prioriteToString(int priorite) {
switch (priorite) {
case MIN_PRIORITE:
return "minimale";
case NORM_PRIORITE:
return "normale";
case MAX_PRIORITE:
return "maximale";
}
return null;
}
/**
* @return les compétences réactives de l'agent.
*/
public final Set> getCompetencesReactives()
{
return competencesReactives.entrySet();
}
public final Set> getCompetencesProactives()
{
return competencesProactives.entrySet();
}
/**
* @return l'état de l'agent.
*/
public final int getEtat() {
return cycleDeVieCourant.getEtat();
}
/**
* @param etat
* l'état de l'agent.
* @return l'état de l'agent sous forme d'une chaîne de caractères.
*/
public final String etatToString(int etat) {
switch (etat) {
case Initial:
return "initial";
case Actif:
return "actif";
case Attente:
String str = "attente";
switch (((CycleDeVieActif)cycleDeVieCourant).causeAttente)
{
case EnvoiMessage : str = str + " l'envoi d'un message";
break;
case ReceptionMessage : str = str + " la réception d'un message";
break;
case TacheAExecuter : str = str+ " d'une tâche à exécuter";
}
return str;
case Suspendu:
return "suspendu";
case Supprime:
return "supprime";
}
return null;
}
/**
* @return une copie de compétence de l'agent.
*/
@SuppressWarnings("unchecked")
public final ArrayList getNomCompetences() {
return (ArrayList) nomCompetences.clone();
}
/*
* LES SETTERS DES VARIABLES
*/
/**
* Définir la priorité de l'agent. Cette priorité doit être comprise entre
* MIN_ PRIORITE
et MAX_ PRIORITE
. Utilisez
* NORM_ PRIORITE
pour une priorité normale.
*
* @param nouvPriorite
* la nouvelle priorité de l'agent
* @return true si MIN_PRIORITE<= nouvPriorite <= MAX_PRIORITE
*
* sinon false.
*
* @see #MAX_PRIORITE
* @see #MIN_PRIORITE
* @see #NORM_PRIORITE
*/
public final boolean setPriorite(int nouvPriorite) {
if ((nouvPriorite >= MIN_PRIORITE) && (nouvPriorite <= MAX_PRIORITE)) {
thread.setPriority(nouvPriorite);
priorite = nouvPriorite;
return true;
}
return false;
}
public static void setEnvironnementGraphique(Object environnementGraphique) {
AgentAtomique.environnementGraphique = environnementGraphique;
}
/*
* LES METHODES DE L'OBECT
*/
/**
* @param agent
* l'agent
* @return true si l'agent en cours correspond à agent
*/
public final boolean equals(AgentAtomique agent) {
if (agent instanceof AgentAtomique)
return aid.equals(((AgentAtomique) agent).aid);
return false;
}
/*
* retourne true si les deux agents sont identitiques (même AID) ET aussi si
* on compare l'agent avec son identificateur. En effet:Les récepteurs du
* message est de type Arraylist où T peut être AID ou AgentAtomique.
* Pour ne pas insérer des doublons, la méthode equals doit nous retourne
* true si on compare l'agent avec son identificateur pour que la méthode
* contains return true;
*/
public final boolean equals(Object o) {
if (o instanceof AgentAtomique)
return aid.equals(((AgentAtomique) o).aid);
if (o instanceof AID)
return aid.equals((AID) o);
return false;
}
/**
* @return une représentation de l'agent sous forme (Identité, Nom,
* Priorité, Etat, Date de création).
*/
public String toString() {
String str = "GUID = " + aid.getGUID() + " ; " + "ETAT = "
+ etatToString(getEtat()) + " ; " + "PRIORITE = "
+ prioriteToString(priorite) + " ; " + "DATE DE CREATION = "
+ dateDeCreation + " .";
return str;
}
/*
* LES METHODES CONCERNANT L'INTERFACE GRAPHIQUE
*/
/*
* public Object getEntree() { return null; }
*/
public Object getEntree() {
if ((entree == null) && (environnementGraphique != null)) {
entree = new JPanelAgent(this, (JInternalFrameAgent) getSortie());
if (Interface.jPanelAgentSelectionne != null) {
Interface.jPanelAgentSelectionne.setBorder(new MatteBorder(0,
0, 0, 0, Color.WHITE));
Interface.jPanelAgentSelectionne.getPopupMenu().setVisible(
false);
}
Interface.jPanelAgentSelectionne = (JPanelAgent) entree;
((JPanelAgent) entree).setBorder(new MatteBorder(5, 5, 5, 5,
JPanelAgent.getColor(getEtat())));
}
return entree;
}
/*
* public void ajouterEntree() {}
*/
public void ajouterEntree() {
if (entree != null) {
((Interface) environnementGraphique).getJPanelAgents().add(
(JPanelAgent) entree, null);
/* Redessiner Fenetres d'agents */
((Interface) environnementGraphique).getJPanelAgents().validate();
((Interface) environnementGraphique).getJPanelAgents().repaint();
((Interface) environnementGraphique).getJScrollPane().validate();
}
}
/*
* public void setEtarEntree() {}
*/
public void setEtatEntree() {
if (entree != null) {
((JPanelAgent) getEntree())
.setFond(new ImageIcon((((Image) Toolkit.getDefaultToolkit().getImage(
getClass().getResource(JPanelAgent.getImageFond(getEtat()))))).
getScaledInstance(125, 70,Image.SCALE_DEFAULT)).getImage());
if (entree == Interface.jPanelAgentSelectionne) {
Interface.jPanelAgentSelectionne.setBorder(new MatteBorder(5,
5, 5, 5, JPanelAgent.getColor(getEtat())));
switch (getEtat()) {
case AgentAtomique.Actif:
((Interface) environnementGraphique).getSuspendreAgent()
.setEnabled(true);
((Interface) environnementGraphique).getReprendreAgent()
.setEnabled(true);
((Interface) environnementGraphique).getSupprimerAgent()
.setEnabled(true);
((Interface) environnementGraphique).getNom().setEnabled(
true);
((Interface) environnementGraphique).getPriorite()
.setEnabled(true);
((Interface) environnementGraphique).getAjouterCompetence()
.setEnabled(true);
((Interface) environnementGraphique)
.getSupprimerCompetence().setEnabled(true);
((Interface) environnementGraphique)
.getExecuterCompetence().setEnabled(true);
break;
case AgentAtomique.Attente:
((Interface) environnementGraphique).getSuspendreAgent()
.setEnabled(true);
((Interface) environnementGraphique).getReprendreAgent()
.setEnabled(true);
((Interface) environnementGraphique).getSupprimerAgent()
.setEnabled(true);
((Interface) environnementGraphique).getNom().setEnabled(
true);
((Interface) environnementGraphique).getPriorite()
.setEnabled(true);
((Interface) environnementGraphique).getAjouterCompetence()
.setEnabled(true);
((Interface) environnementGraphique)
.getSupprimerCompetence().setEnabled(true);
((Interface) environnementGraphique)
.getExecuterCompetence().setEnabled(true);
break;
case AgentAtomique.Suspendu:
((Interface) environnementGraphique).getSuspendreAgent()
.setEnabled(false);
((Interface) environnementGraphique).getReprendreAgent()
.setEnabled(true);
((Interface) environnementGraphique).getSupprimerAgent()
.setEnabled(true);
((Interface) environnementGraphique).getNom().setEnabled(
true);
((Interface) environnementGraphique).getPriorite()
.setEnabled(true);
((Interface) environnementGraphique).getAjouterCompetence()
.setEnabled(true);
((Interface) environnementGraphique)
.getSupprimerCompetence().setEnabled(true);
((Interface) environnementGraphique)
.getExecuterCompetence().setEnabled(true);
break;
case AgentAtomique.Supprime:
((Interface) environnementGraphique).getSuspendreAgent()
.setEnabled(false);
((Interface) environnementGraphique).getReprendreAgent()
.setEnabled(false);
((Interface) environnementGraphique).getSupprimerAgent()
.setEnabled(false);
((Interface) environnementGraphique).getNom().setEnabled(
false);
((Interface) environnementGraphique).getPriorite()
.setEnabled(false);
((Interface) environnementGraphique).getAjouterCompetence()
.setEnabled(false);
((Interface) environnementGraphique)
.getSupprimerCompetence().setEnabled(false);
((Interface) environnementGraphique)
.getExecuterCompetence().setEnabled(false);
}
}
((JPanelAgent) getEntree()).validate();
((JPanelAgent) getEntree()).repaint();
}
}
/*
* public void supprimerEntree() {}
*/
public void supprimerEntree() {
if (entree != null) {
((Interface) environnementGraphique).getJPanelAgents().remove(
(JPanelAgent) entree);
((Interface) environnementGraphique).getJPanelAgents().validate();
((Interface) environnementGraphique).getJPanelAgents().repaint();
((Interface) environnementGraphique).getJScrollPane().validate();
}
}
/*
* public Object getSortie() { return null; }
*/
public Object getSortie() {
if ((sortie == null) && (environnementGraphique != null)) {
sortie = new JInternalFrameAgent();
((JInternalFrameAgent) sortie).setTitle(getNom());
}
return sortie;
}
/*
* public void ajouterSortie() {}
*/
public void ajouterSortie() {
if (sortie != null) {
((Interface) environnementGraphique).getJPanelExecution().add(
(JInternalFrameAgent) sortie, null);
((Interface) environnementGraphique).getJPanelExecution()
.validate();
((Interface) environnementGraphique).getJScrollPane1().repaint();
}
}
/*
* public void Ecrire() {}
*/
public void ecrireFenetre(String x) {
if (sortie != null) {
((JInternalFrameAgent) sortie).getJTextArea().append(x);
((JInternalFrameAgent) sortie).getJTextArea().append("\r\n");
}
}
/*
* public void removeSortie() {}
*/
public void supprimerSortie() {
if (sortie != null) {
((Interface) environnementGraphique).getJPanelExecution().remove(
(JInternalFrameAgent) sortie);
((Interface) environnementGraphique).getJPanelExecution()
.validate();
((Interface) environnementGraphique).getJScrollPane1().repaint();
}
}
public void ecrireConsole(String x) {
if (environnementGraphique != null)
Interface.jListConsole.append(x + "\r\n");
}
public static Object getEnvironnementGraphique() {
return environnementGraphique;
}
public void MAJlistCompetence(boolean ajouter, String competence) {
if(environnementGraphique !=null)
if (ajouter)
((Interface) environnementGraphique).ListCompetences.addElement(competence);
else
((Interface) environnementGraphique).ListCompetences.removeElement(competence);
}
public void afficherErreur(Exception e)
{
if (environnementGraphique != null)
ecrireConsole(e.getMessage() +"---"+ e.getCause());
else
e.printStackTrace();
}
}