Projet

Général

Profil

MAY Tutorial V1 » Historique » Version 5

Anonyme, 26/07/2010 13:36

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
A MAY project is just a Java _Eclipse_ project with supplementary dependencies, an empty MuADL description file and the required directories already created.
79
80
To create a new project, go to _File_ menu, _New_, _Project..._, _Make Agents Yourself_ category and choose _MAY Project_.
81
Follow the instruction.
82
83
h3. Creation of a Textual MuADL Description File
84
85
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}).
86
The extension of these files is @muadlt@.
87
The editor features syntactic colouration, completion and validation of MuArchitectures.
88
89
To create a new MuADL file, go to _File_, _New_, _Others..._, _Make Agents Yourself_ category and choose _MuADL Text file_.
90
Follow the instructions.
91
92
h3. Generation of the corresponding code in Java
93
94
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.
95
96
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_.
97
98
The generated code will be in the @src-gen@ directory.
99
100
It is important to notice that the content of this directory must never be modified.
101
102
h2. MuADL: Description Language for Agent Architectures
103
104
As said before, MAY, using MuADL, make possible to describe:
105
106
* 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)}
107
108
  * Provides operations
109
  * Requires (from the MuArchitecture) operations
110
  * Requires (from the MuArchitecture) the possibility to change other MuComponents
111
  * Have a state that must be persisted by the MuArchitecture when their implementation is changed at runtime
112
* MuArchitectures containing MuComponents and divided in two levels
113
* Datatypes use by MuComponents and corresponding to Java types (classes or interfaces).
114
115
We detail here how to describe these elements.
116
117
h3. DataTypes
118
119
To refer to Java types, we give them a name in the MuADL file.
120
121
The syntax is as following:
122
123
<pre>
124
DataType AliasLocal : package.NomClass
125
DataType AliasLocal : package.NomClass<Generique>
126
DataType AliasLocal : package.NomClass<package.Generique>
127
128
// examples
129
DataType String : String
130
DataType Int : int
131
DataType Msg : my.package.Msg
132
DataType ListString : java.util.List<String>
133
DataType MailBox : java.util.List<my.package.Msg>
134
</pre>
135
136
\todo{Currently, no verification is done on the existence of these classes}
137
138
It is important to understand that DataTypes are just aliases, they can't be used inside generics parameters.
139
140
h3. MuComponents
141
142
Elements of a MuComponent :
143
144
* A name
145
* Provided operations (@provided@)
146
* Required operations (@required@)
147
* Attributes that must be persisted between runtime replacement of implementations (@persistent@)
148
* A set of MuComponents whose implementation could be changed at runtime \todo{This point is likely to change in the future} (@change@)
149
150
The MuComponents operations are similar to Java methods: they have a name, ordered typed parameters and a return type.
151
To refer to a method, it is only needed to know its name, its ordered parameter types and its return type.
152
153
An example of MuComponent :
154
<pre>
155
MuComponent Message {
156
  package a.test.package
157
  provided send(mess : String)
158
  provided receive() : String
159
  persistent mailbox : MailBox
160
  required do(String) : Int
161
  change LifeCycle
162
}
163
</pre>
164
165
h3. MuArchitectures
166
167
A MuArchitecture have:
168
169
* A name
170
* A set of MuComponents in the container level (@container@)
171
* A set of MuComponents in the application level (@application@)
172
* A set of visibility modifiers on th MuComponents operations (@visibility@)
173
174
175
The MuComponents can be specified as changeable (with @changeable@) by other MuComponents.
176
MuComponents can only change MuComponents of the same level.
177
178
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.
179
This fact can be changed by specifying (with @application@ visibility) that an operation of the container level is visible in the application level.
180
181
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}).
182
183
An example of MuArchitecture :
184
185
<pre>
186
MuArchitecture MyAgent {
187
  package another.test.package
188
  container {
189
    changeable LifeCycle
190
    Message
191
  }
192
  application {
193
    Behavior
194
  }
195
  visibility {
196
    external Message.send(String)
197
    application Message.receive() : String
198
  }
199
}
200
</pre>
201
202
Notice that :
203
204
* If a MuComponent @A@ requires an operation @0@, then a MuComponent providing @0@ must be present in the MuArchitecture.
205
* Requirements are only validated in the MuArchitecture.
206
* Two MuComponents can't provide the same operation.
207
208
h3. Complementary Informations
209
210
MuADL allows for comments :
211
212
<pre>
213
  // a comment
214
  /*
215
  a multi-line
216
  comment
217
  */
218
</pre>
219
220
221
h2. Implantation of MuComponents, use of MuArchitectures and Framework Distribution
222
223
After the Java code from a MuADL file was generated (see \ref{generation}), MuComponents implementation and MuArchitectures instantiation is possible.
224
225
The generation result in a set of Java classes situated in the @src-gen@ directory.
226
To implement MuComponents, we will write Java classes (typically in the @src@ directory) that extends some of these generated classes.
227
228
h3. MuComponents Implementations
229
230
For each MuComponent @X@ defined in the MuADL file, MAY generates a class @QuasiComponentX@ and a class @AdapterX@.
231
The first must be extended to implement @X@.
232
233
For example, there is the two generated classes for a component @LifeCyle@:
234
235
<pre>
236
public abstract class QuasiComponentLifeCycle
237
    extends QuasiComponent<AdapterLifeCycle>  {
238
  abstract public void suicide();
239
}
240
</pre>
241
242
243
<pre>
244
public interface AdapterLifeCycle extends Adapter {
245
  public void cycle(java.lang.String arg0);
246
  public java.lang.String receive();
247
}
248
</pre>
249
250
251
Thus, by extending @QuasiComponentLifeCycle@, one can use the required methods of the MuComponent by using the architecture through the method @this.architecture()@.
252
253
There is an example of this MuComponent :
254
<pre>
255
public class LifeCycle extends QuasiComponentLifeCycle {
256
  private boolean alive = true;
257
258
  @Override
259
  public void start() {
260
    Runnable me = new Runnable() {
261
      public void run() {
262
        while (alive) {
263
          String msg = architecture().receive();
264
          architecture().cycle(msg);
265
        }
266
      }
267
    };
268
    new Thread(me).start();
269
  }
270
271
  public void suicide() {
272
    alive = false;
273
  }
274
}
275
</pre>
276
277
278
The important points to notice are:
279
280
* A method @void start()@ is present to execute instructions at the start of the agent
281
* @this.architecture()@ gives access to required methods through the MuArchitecture
282
283
There is an example of a generated MuComponent with a persistent state:
284
285
<pre>
286
public abstract class QuasiComponentMessage
287
    extends QuasiComponent<AdapterMessage>
288
    implements WithPersistentState<PersistentStateMessage> {
289
290
  abstract public void send(java.lang.String message);
291
  abstract public java.lang.String receive();
292
}
293
</pre>
294
295
<pre>
296
public interface AdapterMessage extends Adapter {}
297
</pre>
298
299
300
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).
301
302
There is an example of implementation for this MuComponent:
303
304
<pre>
305
public class Message extends QuasiComponentMessage {
306
307
  private ArrayBlockingQueue<String> messageBox =
308
    new ArrayBlockingQueue<String>(100);
309
310
  public void send(String message) {
311
    try {
312
      messageBox.put(message);
313
    } catch (InterruptedException e) {
314
      e.printStackTrace();
315
    }
316
  }
317
318
  public PersistentStateMessage getPersistentState() {
319
    return new PersistentStateMessage(
320
                new ArrayList<String>(messageBox)
321
           );
322
  }
323
324
  public void setPersistentState(PersistentStateMessage state) {
325
    messageBox =
326
      new ArrayBlockingQueue<String>(10, false, state.messageBox);
327
    System.out.println("Message Component started with "+
328
                        messageBox.size()+ " messages");
329
  }
330
331
  public String receive() {
332
    try {
333
      return messageBox.take();
334
    } catch (InterruptedException e) {
335
      e.printStackTrace();
336
      return "";
337
    }
338
  }
339
}
340
</pre>
341
342
Notice that we use an object of type @PersistentStateMessage@ to store and read the persistent state.
343
344
There is an example of a generated MuComponent changing another MuComponent implementation:
345
346
<pre>
347
public abstract class QuasiComponentAdaptation
348
    extends QuasiComponent<AdapterAdaptation>  {
349
  abstract public void adapt();
350
}
351
</pre>
352
353
354
<pre>
355
public interface AdapterAdaptation extends Adapter {
356
  public void change(QuasiComponentMessage _comp);
357
}
358
</pre>
359
360
Notice that a @void change(QuasiComponentMessage _comp)@ method is present to give access to the replacement functionalities of the MuArchitecture.
361
362
There is an example of implementation of this MuComponent:
363
364
<pre>
365
public class Adaptation extends QuasiComponentAdaptation {
366
  public void adapt() {
367
    architecture().change(new Message());
368
  }
369
}
370
</pre>
371
372
373
We can also see here for the first time the instantiation of a MuComponent.
374
375
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@.
376
377
h3. MuArchitecture Use
378
379
To use a MuArchitecture is to create an agent complying to this MuArchitecture by instantiating each of its MuComponents.
380
381
For this, the generated code of a MuArchitecture @X@ consists into 2 classes: @XMediator@ and @X@.
382
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.}.
383
384
Thus, to create an agent compliant with a MuArchitecture @SimpleAgent@ with 4 MuComponents @Adaptation@, @Message@, @LifeCycle@ and @Behavior@ is done like this:
385
386
<pre>
387
  SimpleAgent agent1 = new SimpleAgent(
388
                          new Message(),
389
                          new LifeCycle(),
390
                          new Adaptation(),
391
                          new Behavior());
392
  agent1.start();
393
</pre>
394
395
396
Notice the call to @start()@ that starts each of the MuComponents and thus the agent.
397
398
h3. _Factory_
399
400
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.
401
These will then be directly usable by users by choosing the remaining MuComponent implementations.
402
403
This is done by using a _Factory_, which currently must be built by hand.
404
405
A factory is only a class providing one (or several) static methods instantiating some MuComponents and an agent.
406
For example:
407
408
<pre>
409
public class MySimpleAgent {
410
  public static SimpleAgent create(QuasiComponentBehavior behavior) {
411
    SimpleAgent agent = new SimpleAgent(new Message(),
412
                                        new LifeCycle(),
413
                                        new Adaptation(),
414
                                        behavior);
415
    agent.start();
416
    return agent;
417
  }
418
}
419
</pre>
420
421
Thus, to create an agent, one just need to know @MySimpleAgent.create(...)@.
422
423
For example:
424
<pre>
425
public class Main {
426
  public static void main(String[] args) {
427
    SimpleAgent agent1 = create(new Behavior2("agent1"));
428
    SimpleAgent agent2 = create(new Behavior("agent2", agent1));
429
430
    agent2.send("hello");
431
  }
432
}
433
</pre>
434
435
h3. Framework Distribution
436
437
The created classes in the previous sections form a framework usable by a user of the model of agent to create agents.
438
439
Delivering them to such an user is to export the _Eclipse_ project as a JAR using its export facilities:
440
right-click on the project, choose _Export..._, in the _Java_ category, choose _JAR File_ and follow the instructions.
441
442
The resulting JAR file will only need the _fr.irit.smac.muadl.impl_X.X.X.jar_ file available of the MAY website.
443
For example they can both be added to a classic _Eclipse_ Java project as dependencies.