Projet

Général

Profil

MAY Tutorial V1 » Historique » Version 6

Anonyme, 06/10/2010 14:38

1 4 Anonyme
h1. Make Agents Yourself Tutorial
2
3
{{>toc}}
4
5
% TODO : exemple complet, clair et qui colle au code
6
%        ajouter utilisation objet commun à plusieurs composants (ou remplacé par un compo (Representation))
7
%        retirer code généré !
8
9
h2. Introduction
10
11
In this tutorial, we are going to see an introduction to MAY.
12
13
This tool was made to build application-specific models of agent and to generate dedicated framework providing them.
14
Such framework would then be usable to program agents compliant with the realised model of agent.
15
16
More specifically, a model of agent is realised by an architecture divided in two levels: "container" (the how), hidden to the user of the framework and "application" (the what) expression what the agent does.
17
These two levels links MuComponents together to form a MuArchitecture realising the model.
18
19
Furthermore, such agents have the possibility to self-adapt at runtime: currently, this means that a MuComponent is able to change the implementation of another MuComponent of the MuArchitecture.
20
21
In practice, these models are described with the help of the MuADL description language, and from this description, the Java code needed to implement the MuComponents is generated.
22
The MuArchitecture itself is generated and is directly usable by setting the implementation of its MuComponents.
23
24
This tool being experimental, several functionalities described are are subject to change in the future.
25
If possible, this will be stated in this document.
26
27
h3. Requirements
28
29
To use MAY, the _Eclipse IDE_ is needed.
30
It can be found at http://www.eclipse.org/.
31
32
h3. Installation
33
34
The installation is done from the _Software Update_ in _Eclipse_ by adding the following _Update Sites_:
35
36
<pre>
37
http://www.irit.fr/PERSONNEL/SMAC/noel/may/update/
38
http://oawbranch.pluginbuilder.org/releases/p2-updateSite/
39
</pre>
40
41
Choose to install _Make Agents Yourself_.
42
43
h3. Upgrades
44
45 5 Anonyme
When upgrades are available, just use the _Update_ feature of _Eclipse_.
46 4 Anonyme
47
h2. Typical Development Process of an Agent with MAY
48
49
As explained before, MAY is a tool usable to description MuArchitectures based on MuComponents to generate a framework that will be distributed to application developers.
50
51
Several phases in the development can be distinguished:
52
53
* Description of the MuComponents and MuArchitectures:
54
55
  * Create a MAY project
56
  * Describe the model with MuADL
57
  * Generate the corresponding Java code
58
* Implantation of the MuComponents with Java
59
* Implantation of a _Factory_ with Java
60
* Generation of the distributable framework in the form of a JAR file
61
62
The following sections will describe in detail these development phases.
63
We will see the tools MAY adds to _Eclipse_, a description of MuADL and some advice to develop an agent and its MuComponents.
64
65
h2. Added Tools to _Eclipse_
66
67
The tools proposed by MAY are the following:
68
69
* Creation of a MAY project
70
* Creation of a textual MuADL description file
71
* Generation of the corresponding code in Java
72
73
74
A graphical editor is currently being worked on.
75
76
h3. Creation of a Project
77
78 6 Anonyme
A MAY project is just a Java _Eclipse_ project with supplementary dependencies and a specific required directory named @src-gen@.
79 1 Anonyme
80 6 Anonyme
Create a new Java Project.
81
Add a source directory named @src-gen@.
82
Add the MuADL library corresponding to the version of the plugin (current is 0.11.0) that can be found at "this place":http://www.irit.fr/PERSONNEL/SMAC/noel/maven-repos/fr/irit/smac/muadl/muadl-impl/ as a JAR (_e.g._ @0.11.0/muadl-impl-0.11.0.jar@)
83 4 Anonyme
84
h3. Creation of a Textual MuADL Description File
85
86
The description of a model of agent is represented by a text file containing the description of MuComponents and MuArchitectures with MuADL (presented Sect.~\ref{muadl}).
87
The extension of these files is @muadlt@.
88
The editor features syntactic colouration, completion and validation of MuArchitectures.
89
90
To create a new MuADL file, go to _File_, _New_, _Others..._, _Make Agents Yourself_ category and choose _MuADL Text file_.
91
Follow the instructions.
92
93
h3. Generation of the corresponding code in Java
94
95
This action generates the classes required for the implementation of the MuComponents described in the MuADL file (the @QuasiComponent@), the class representing the mediator of the MuArchitecture and the class façade representing an agent compliant with the MuArchitecture.
96
97
To generate the corresponding code of a MuADL file (a file ending in @.muadlt@), do a right click on it and in the sub-menu _Make Agents Yourself_, choose _Generate QC and Architecture_.
98
99
The generated code will be in the @src-gen@ directory.
100
101
It is important to notice that the content of this directory must never be modified.
102
103
h2. MuADL: Description Language for Agent Architectures
104
105
As said before, MAY, using MuADL, make possible to describe:
106
107
* MuComponents that: \todo{MuADL does not permit to specify how they will be implemented (no information of the constructors, the class attributes or private methods)}
108
109
  * Provides operations
110
  * Requires (from the MuArchitecture) operations
111
  * Requires (from the MuArchitecture) the possibility to change other MuComponents
112
  * Have a state that must be persisted by the MuArchitecture when their implementation is changed at runtime
113
* MuArchitectures containing MuComponents and divided in two levels
114
* Datatypes use by MuComponents and corresponding to Java types (classes or interfaces).
115
116
We detail here how to describe these elements.
117
118
h3. DataTypes
119
120
To refer to Java types, we give them a name in the MuADL file.
121
122
The syntax is as following:
123
124
<pre>
125
DataType AliasLocal : package.NomClass
126
DataType AliasLocal : package.NomClass<Generique>
127
DataType AliasLocal : package.NomClass<package.Generique>
128
129
// examples
130
DataType String : String
131
DataType Int : int
132
DataType Msg : my.package.Msg
133
DataType ListString : java.util.List<String>
134
DataType MailBox : java.util.List<my.package.Msg>
135
</pre>
136
137
\todo{Currently, no verification is done on the existence of these classes}
138
139
It is important to understand that DataTypes are just aliases, they can't be used inside generics parameters.
140
141
h3. MuComponents
142
143
Elements of a MuComponent :
144
145
* A name
146
* Provided operations (@provided@)
147
* Required operations (@required@)
148
* Attributes that must be persisted between runtime replacement of implementations (@persistent@)
149
* A set of MuComponents whose implementation could be changed at runtime \todo{This point is likely to change in the future} (@change@)
150
151
The MuComponents operations are similar to Java methods: they have a name, ordered typed parameters and a return type.
152
To refer to a method, it is only needed to know its name, its ordered parameter types and its return type.
153
154
An example of MuComponent :
155
<pre>
156
MuComponent Message {
157
  package a.test.package
158
  provided send(mess : String)
159
  provided receive() : String
160
  persistent mailbox : MailBox
161
  required do(String) : Int
162
  change LifeCycle
163
}
164
</pre>
165
166
h3. MuArchitectures
167
168
A MuArchitecture have:
169
170
* A name
171
* A set of MuComponents in the container level (@container@)
172
* A set of MuComponents in the application level (@application@)
173
* A set of visibility modifiers on th MuComponents operations (@visibility@)
174
175
176
The MuComponents can be specified as changeable (with @changeable@) by other MuComponents.
177
MuComponents can only change MuComponents of the same level.
178
179
By default, a MuComponent operation of the application level is visible by every MuComponents of the MuArchitecture, and a MuComponent operation of the container level is only visible by the MuComponents of the container level.
180
This fact can be changed by specifying (with @application@ visibility) that an operation of the container level is visible in the application level.
181
182
An operation of the MuArchitecture can be specified as being available from outside of the agent (with @external@ \todo{This is susceptible to change in the future}).
183
184
An example of MuArchitecture :
185
186
<pre>
187
MuArchitecture MyAgent {
188
  package another.test.package
189
  container {
190
    changeable LifeCycle
191
    Message
192
  }
193
  application {
194
    Behavior
195
  }
196
  visibility {
197
    external Message.send(String)
198
    application Message.receive() : String
199
  }
200
}
201
</pre>
202
203
Notice that :
204
205
* If a MuComponent @A@ requires an operation @0@, then a MuComponent providing @0@ must be present in the MuArchitecture.
206
* Requirements are only validated in the MuArchitecture.
207
* Two MuComponents can't provide the same operation.
208
209
h3. Complementary Informations
210
211
MuADL allows for comments :
212
213
<pre>
214
  // a comment
215
  /*
216
  a multi-line
217
  comment
218
  */
219
</pre>
220
221
222
h2. Implantation of MuComponents, use of MuArchitectures and Framework Distribution
223
224
After the Java code from a MuADL file was generated (see \ref{generation}), MuComponents implementation and MuArchitectures instantiation is possible.
225
226
The generation result in a set of Java classes situated in the @src-gen@ directory.
227
To implement MuComponents, we will write Java classes (typically in the @src@ directory) that extends some of these generated classes.
228
229
h3. MuComponents Implementations
230
231
For each MuComponent @X@ defined in the MuADL file, MAY generates a class @QuasiComponentX@ and a class @AdapterX@.
232
The first must be extended to implement @X@.
233
234
For example, there is the two generated classes for a component @LifeCyle@:
235
236
<pre>
237
public abstract class QuasiComponentLifeCycle
238
    extends QuasiComponent<AdapterLifeCycle>  {
239
  abstract public void suicide();
240
}
241
</pre>
242
243
244
<pre>
245
public interface AdapterLifeCycle extends Adapter {
246
  public void cycle(java.lang.String arg0);
247
  public java.lang.String receive();
248
}
249
</pre>
250
251
252
Thus, by extending @QuasiComponentLifeCycle@, one can use the required methods of the MuComponent by using the architecture through the method @this.architecture()@.
253
254
There is an example of this MuComponent :
255
<pre>
256
public class LifeCycle extends QuasiComponentLifeCycle {
257
  private boolean alive = true;
258
259
  @Override
260
  public void start() {
261
    Runnable me = new Runnable() {
262
      public void run() {
263
        while (alive) {
264
          String msg = architecture().receive();
265
          architecture().cycle(msg);
266
        }
267
      }
268
    };
269
    new Thread(me).start();
270
  }
271
272
  public void suicide() {
273
    alive = false;
274
  }
275
}
276
</pre>
277
278
279
The important points to notice are:
280
281
* A method @void start()@ is present to execute instructions at the start of the agent
282
* @this.architecture()@ gives access to required methods through the MuArchitecture
283
284
There is an example of a generated MuComponent with a persistent state:
285
286
<pre>
287
public abstract class QuasiComponentMessage
288
    extends QuasiComponent<AdapterMessage>
289
    implements WithPersistentState<PersistentStateMessage> {
290
291
  abstract public void send(java.lang.String message);
292
  abstract public java.lang.String receive();
293
}
294
</pre>
295
296
<pre>
297
public interface AdapterMessage extends Adapter {}
298
</pre>
299
300
301
When implementing it, one has access to the methods needed for the handling of the persistent state (automatically called by the architecture if the MuComponent implementation is changed at runtime).
302
303
There is an example of implementation for this MuComponent:
304
305
<pre>
306
public class Message extends QuasiComponentMessage {
307
308
  private ArrayBlockingQueue<String> messageBox =
309
    new ArrayBlockingQueue<String>(100);
310
311
  public void send(String message) {
312
    try {
313
      messageBox.put(message);
314
    } catch (InterruptedException e) {
315
      e.printStackTrace();
316
    }
317
  }
318
319
  public PersistentStateMessage getPersistentState() {
320
    return new PersistentStateMessage(
321
                new ArrayList<String>(messageBox)
322
           );
323
  }
324
325
  public void setPersistentState(PersistentStateMessage state) {
326
    messageBox =
327
      new ArrayBlockingQueue<String>(10, false, state.messageBox);
328
    System.out.println("Message Component started with "+
329
                        messageBox.size()+ " messages");
330
  }
331
332
  public String receive() {
333
    try {
334
      return messageBox.take();
335
    } catch (InterruptedException e) {
336
      e.printStackTrace();
337
      return "";
338
    }
339
  }
340
}
341
</pre>
342
343
Notice that we use an object of type @PersistentStateMessage@ to store and read the persistent state.
344
345
There is an example of a generated MuComponent changing another MuComponent implementation:
346
347
<pre>
348
public abstract class QuasiComponentAdaptation
349
    extends QuasiComponent<AdapterAdaptation>  {
350
  abstract public void adapt();
351
}
352
</pre>
353
354
355
<pre>
356
public interface AdapterAdaptation extends Adapter {
357
  public void change(QuasiComponentMessage _comp);
358
}
359
</pre>
360
361
Notice that a @void change(QuasiComponentMessage _comp)@ method is present to give access to the replacement functionalities of the MuArchitecture.
362
363
There is an example of implementation of this MuComponent:
364
365
<pre>
366
public class Adaptation extends QuasiComponentAdaptation {
367
  public void adapt() {
368
    architecture().change(new Message());
369
  }
370
}
371
</pre>
372
373
374
We can also see here for the first time the instantiation of a MuComponent.
375
376
When calling @change(...)@, the MuArchitecture will get the current state of @Message@ and will inject it in the new implementation with the methods we defined previously in @Message@.
377
378
h3. MuArchitecture Use
379
380
To use a MuArchitecture is to create an agent complying to this MuArchitecture by instantiating each of its MuComponents.
381
382
For this, the generated code of a MuArchitecture @X@ consists into 2 classes: @XMediator@ and @X@.
383
The first one is the implementation of the MuArchitecture itself, and the second one is a façade providing the external methods of the agent \todo{This will change in the future.}.
384
385
Thus, to create an agent compliant with a MuArchitecture @SimpleAgent@ with 4 MuComponents @Adaptation@, @Message@, @LifeCycle@ and @Behavior@ is done like this:
386
387
<pre>
388
  SimpleAgent agent1 = new SimpleAgent(
389
                          new Message(),
390
                          new LifeCycle(),
391
                          new Adaptation(),
392
                          new Behavior());
393
  agent1.start();
394
</pre>
395
396
397
Notice the call to @start()@ that starts each of the MuComponents and thus the agent.
398
399
h3. _Factory_
400
401
One of the objectives of MAY being to reduce the development effort by distributing models of agents ready to use, it is necessary to be able to provide partially instantiated MuArchitecture where some of the MuComponents implementation are already fixed.
402
These will then be directly usable by users by choosing the remaining MuComponent implementations.
403
404
This is done by using a _Factory_, which currently must be built by hand.
405
406
A factory is only a class providing one (or several) static methods instantiating some MuComponents and an agent.
407
For example:
408
409
<pre>
410
public class MySimpleAgent {
411
  public static SimpleAgent create(QuasiComponentBehavior behavior) {
412
    SimpleAgent agent = new SimpleAgent(new Message(),
413
                                        new LifeCycle(),
414
                                        new Adaptation(),
415
                                        behavior);
416
    agent.start();
417
    return agent;
418
  }
419
}
420
</pre>
421
422
Thus, to create an agent, one just need to know @MySimpleAgent.create(...)@.
423
424
For example:
425
<pre>
426
public class Main {
427
  public static void main(String[] args) {
428
    SimpleAgent agent1 = create(new Behavior2("agent1"));
429
    SimpleAgent agent2 = create(new Behavior("agent2", agent1));
430
431
    agent2.send("hello");
432
  }
433
}
434
</pre>
435
436
h3. Framework Distribution
437
438
The created classes in the previous sections form a framework usable by a user of the model of agent to create agents.
439
440
Delivering them to such an user is to export the _Eclipse_ project as a JAR using its export facilities:
441
right-click on the project, choose _Export..._, in the _Java_ category, choose _JAR File_ and follow the instructions.
442
443
The resulting JAR file will only need the _fr.irit.smac.muadl.impl_X.X.X.jar_ file available of the MAY website.
444
For example they can both be added to a classic _Eclipse_ Java project as dependencies.