/
PingPongSpace.spec
911 lines (842 loc) · 27.1 KB
/
PingPongSpace.spec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014 Sebastian RODRIGUEZ, Nicolas GAUD, Stéphane GALLAND.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.sarl.docs.tutorials
import com.google.inject.Inject
import io.sarl.docs.utils.SARLParser
import io.sarl.docs.utils.SARLSpecCreator
import org.jnario.runner.CreateWith
import static extension io.sarl.docs.utils.SpecificationTools.*
import static extension org.junit.Assume.*
/* <!-- OUTPUT OUTLINE -->
*
* This document describes how to create a simple
* agent-based application in which agents are
* exchanging basic messages inside a sub-space.
* Before reading this document, it is recommended reading
* the [General Syntax Reference](../reference/GeneralSyntaxReferenceSpec.html).
*
* <div class="bt-download">
* <a href="%sarlmavenrepository%/last-demos-release.jar"><img alt="Download the Binary JAR file" src="%website%/images/download-icon.png"/></a>
* </div>
* The elements that are explained in this tutorial are:
*
* * the definition of an event;
* * the definition of an agent;
* * the creation of a sub-space;
* * the sending of an event occurrence in the default space;
* * the receiving of event occurrences; and
* * the definition of a _proactive_ behavior: waiting for partners.
*
* The source code related to this tutorial may be found
* in the [SARL demos](https://github.com/sarl/sarl-demos/tree/master/src/main/sarl/io/sarl/docs/tutorials/pingpongspace).
*/
@CreateWith(SARLSpecCreator)
describe "Agent Communication in Sub-Space with the Ping Pong Agents"{
@Inject extension SARLParser
/*
* The principle of the application is the following:
*
* * The agents are joining a sub-space given at initialization.
* * The `Ping` agent is sending a `Ping` message to all agents into the sub-space.
* * The `Pong` agent is receiving the `Ping` message, and replies
* with a `Pong` message to the sender of the `Ping` message.
* * The `Ping` agent is receiving a `Pong` message and
* replies to the sender of the `Pong` with a new `Ping` message.
*
* These messages contain an integer number that
* indicates the number of the event.
*
* ![Ping-Pong Example](./pingpongspace.png)
*
* @filter(.*)
*/
fact "Principle of the Application" {
// Test the URLs in the introduction of this page.
"../reference/GeneralSyntaxReferenceSpec.html" should beAccessibleFrom this
"./pingpongspace.png" should beAccessibleFrom this
// The checks are valid only if the macro replacements were done.
// The replacements are done by Maven.
// So, Eclipse Junit tools do not make the replacements.
System.getProperty("sun.java.command", "").startsWith("org.eclipse.jdt.internal.junit.").assumeFalse
//
"%sarlmavenrepository%" should beURL "!file"
"%website%" should beURL "!file"
}
/* First, the `Ping` and `Pong` events must be defined.
*/
context "Event definition" {
/* The `Ping` is an event that contains the
* index of the event. This index indicates
* at which position the event is located in
* the sequence of sent `Ping` event.
*
* The `index` attribute is a _value_, for making
* it unmodifiable after its initialization.
*
* For setting the value of the `index` value,
* it is mandatory to define a constructor.
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Ping Event" {
'''
package io.sarl.docs.tutorials.pingpongspace
event Ping {
val index : int
new(i : int) {
this.index = i
}
}
'''.parseSuccessfully
}
/* The `Pong` is an event that contains the
* index of the `Ping` event for which the
* `Pong` event is created.
*
* The `index` attribute is also a _value_, and
* it must be set in a constructor.
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Pong Event" {
'''
event Pong {
val index : int
new(i : int) {
this.index = i
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace",
// TEXT
""
)
}
}
/* The second step of this tutorial is the definition of the
* agent that is waiting for `Ping` events, and replying
* `Pong` events.
*/
context "Pong agent" {
/* The initial definition of the pong agent is:
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "First definition" {
'''
agent PongAgent {
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace",
// TEXT
""
)
}
/* Because the agents are interacting into a sub-space,
* they must join this sub-space at start-up.
*
* The sub-space is located in the default context.
* For creating or joining it, we must use the
* `getOrCreateSpaceWithSpec` function.
* This function searches for a space, which was
* created with the given specification. If there
* is no space, the space identifier is used
* for creating a new space.
*
* After retrieving the instance of the space,
* it is mandatory to register the agent for
* receiving the events. The spaces of
* type `OpenEventSpaceSpecification` provides
* the `register` function. It takes the
* event listener of the agent (provided by
* the `Behaviors` capacity).
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Join the sub-space" {
'''
agent PongAgent {
uses DefaultContextInteractions, Behaviors
var space : OpenEventSpace
on Initialize {
space = defaultContext.getOrCreateSpaceWithSpec(
typeof(OpenEventSpaceSpecification),
occurrence.parameters.get(0) as UUID)
space.register(asEventListener())
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Initialize
import io.sarl.core.Behaviors
import java.util.UUID
import io.sarl.util.OpenEventSpace
import io.sarl.util.OpenEventSpaceSpecification",
// TEXT
""
)
}
/* The pong agent needs to handle the `Ping` events.
* For that, a "behavior unit" must be defined in the
* agent. According to the
* [Agent Reference](../reference/AgentReferenceSpec.html),
* the `on` keyword followed by the name of the event
* permits to define a handler of events.
* This handler will be invoked by the runtime environment
* each time the agent is receiving a `Ping` event.
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Handling the Ping event" {
'''
agent PongAgent {
uses DefaultContextInteractions, Behaviors
var space : OpenEventSpace
on Initialize {
space = defaultContext.getOrCreateSpaceWithSpec(
typeof(OpenEventSpaceSpecification),
occurrence.parameters.get(0) as UUID)
space.register(asEventListener())
}
on Ping {
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Behaviors
import java.util.UUID
import io.sarl.util.OpenEventSpace
import io.sarl.util.OpenEventSpaceSpecification
import io.sarl.core.Initialize
event Ping {
val index : int
new (i : int) {
this.index = i
}
}",
// TEXT
""
)
"../reference/AgentReferenceSpec.html" should beAccessibleFrom this
}
/* Now, it is time to define how the pong agent
* is replying with a `Pong` message.
*
* First, sending an event in the default space
* must be done with a built-in capacity:
* `DefaultContextInteractions`. This capacity
* provides a collection of functions that
* enable the agent to interact with the
* default context, and its default space.
*
* For using the capacity, it is recommended
* declaring it with the `uses` keyword.
* This keyword permits the agent to directly
* call the functions of the capacity as if
* they were defined as actions in the agent.
*
* The `DefaultContextInteractions` capacity
* provides the function `emit(Event)` for
* sending an event in the default space of the
* default context.
*
* The `Pong` event must be built with
* an index value as argument. This argument
* is the index stored in the `Ping` event.
* For accessing the occurrence of the
* `Ping` event, you must use the special
* keyword `occurrence`.
* In the following example, the `Pong`
* event is built with the index argument
* stored in the received `Ping` event.
* Because an event must always have a source
* and the space is not able to set this source
* for you, you must set the source of the
* event by yourself. The source of the event
* is the address of the pong agent in
* the sub-space. This address is replied
* by the `getAddress` function.
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Replying to Ping with a Pong" {
'''
agent PongAgent {
uses DefaultContextInteractions, Behaviors
var space : OpenEventSpace
on Initialize {
space = defaultContext.getOrCreateSpaceWithSpec(
typeof(OpenEventSpaceSpecification),
occurrence.parameters.get(0) as UUID)
space.register(asEventListener())
}
on Ping {
var evt = new Pong( occurrence.index )
evt.source = space.getAddress(getID)
space.emit( evt )
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Behaviors
import java.util.UUID
import io.sarl.util.OpenEventSpace
import io.sarl.util.OpenEventSpaceSpecification
import io.sarl.core.Initialize
event Ping {
val index : int
new (i : int) {
this.index = i
}
}
event Pong {
val index : int
new (i : int) {
this.index = i
}
}",
// TEXT
""
)
}
/* In the previous code, the event is emitted
* to all the agents belonging to the default
* space, including the pong agent.
*
* For restricting the receiver of the
* `Pong` event to the initial sender of the
* `Ping` event, you must define a scope for
* the `Pong` event.
* The `DefaultContextInteractions` capacity
* provides the function `emit(Event, Scope<Address>)`
* for sending an event with a specific scope.
*
* The SARL SDK contains the class `AddressScope`.
* It is an implementation of a `Scope` on addresses
* (an address is the identifier
* of an agent in the default space). The creation
* of an instance of `AddressScope` is done
* with the utility function `Scopes.addresses(Address*)`,
* which is getting a collection of addresses for building
* the matching predicate in the scope.
*
* In the following code, the scope permits to
* restrict to the initial sender of the `Ping` event.
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Restricting the scope of the Pong event" {
'''
agent PongAgent {
uses DefaultContextInteractions, Behaviors
var space : OpenEventSpace
on Initialize {
space = defaultContext.getOrCreateSpaceWithSpec(
typeof(OpenEventSpaceSpecification),
occurrence.parameters.get(0) as UUID)
space.register(asEventListener())
}
on Ping {
var evt = new Pong( occurrence.index )
evt.source = space.getAddress(getID)
space.emit(
evt,
Scopes.addresses( occurrence.source ))
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Behaviors
import java.util.UUID
import io.sarl.util.OpenEventSpace
import io.sarl.util.OpenEventSpaceSpecification
import io.sarl.core.Initialize
import io.sarl.util.Scopes
event Ping {
val index : int
new (i : int) {
this.index = i
}
}
event Pong {
val index : int
new (i : int) {
this.index = i
}
}",
// TEXT
""
)
}
}
/* The third step of this tutorial is the definition of the
* agent that is sending `Ping` events, and waiting for
* `Pong` events.
*/
context "Ping Agent" {
/* The initial definition of the ping agent is:
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "First definition" {
'''
agent PingAgent {
uses DefaultContextInteractions, Behaviors
var space : OpenEventSpace
on Initialize {
space = defaultContext.getOrCreateSpaceWithSpec(
typeof(OpenEventSpaceSpecification),
occurrence.parameters.get(0) as UUID)
space.register(asEventListener())
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Initialize
import io.sarl.core.Behaviors
import java.util.UUID
import io.sarl.util.OpenEventSpace
import io.sarl.util.OpenEventSpaceSpecification",
// TEXT
""
)
}
/* The ping agent needs to handle the `Pong` events.
* For that, a "behavior unit" must be defined in the
* agent.
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Handling the Pong event" {
'''
agent PingAgent {
uses DefaultContextInteractions, Behaviors
var space : OpenEventSpace
on Initialize {
space = defaultContext.getOrCreateSpaceWithSpec(
typeof(OpenEventSpaceSpecification),
occurrence.parameters.get(0) as UUID)
space.register(asEventListener())
}
on Pong {
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Behaviors
import java.util.UUID
import io.sarl.util.OpenEventSpace
import io.sarl.util.OpenEventSpaceSpecification
import io.sarl.core.Initialize
event Pong {
val index : int
new (i : int) {
this.index = i
}
}",
// TEXT
""
)
}
/* When the ping agent is receiving a
* `Pong` event, it re-sends a `Ping` event
* to the sender of the `Pong` event.
* This new `Ping` event has an index greater
* than the one of the `Pong` event.
*
* The receiving of the `Ping` event is
* restricted to the sender of the
* `Pong` event.
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Re-sending a Ping when receiving a Pong" {
'''
agent PingAgent {
uses DefaultContextInteractions, Behaviors
var space : OpenEventSpace
on Initialize {
space = defaultContext.getOrCreateSpaceWithSpec(
typeof(OpenEventSpaceSpecification),
occurrence.parameters.get(0) as UUID)
space.register(asEventListener())
}
on Pong {
var evt = new Ping( occurrence.index + 1 )
evt.source = space.getAddress(getID)
space.emit(
evt,
Scopes.addresses( occurrence.source )
)
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Behaviors
import java.util.UUID
import io.sarl.util.OpenEventSpace
import io.sarl.util.OpenEventSpaceSpecification
import io.sarl.core.Initialize
import io.sarl.util.Scopes
event Ping {
val index : int
new (i : int) {
this.index = i
}
}
event Pong {
val index : int
new (i : int) {
this.index = i
}
}",
// TEXT
""
)
}
/* For starting the exchanges among the agents,
* it is mandatory to send a first occurrence
* of the `Ping` event.
*
* This emit is done when the ping agent
* is started, i.e. when the agent is
* receiving the `Initialize` event.
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Sending the first Ping" {
'''
agent PingAgent {
uses DefaultContextInteractions, Behaviors
var space : OpenEventSpace
on Initialize {
space = defaultContext.getOrCreateSpaceWithSpec(
typeof(OpenEventSpaceSpecification),
occurrence.parameters.get(0) as UUID)
space.register(asEventListener())
var evt = new Ping(0)
evt.source = space.getAddress(getID)
space.emit( evt )
}
on Pong {
var evt = new Ping( occurrence.index + 1 )
evt.source = space.getAddress(getID)
space.emit(
evt,
Scopes.addresses( occurrence.source )
)
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Behaviors
import java.util.UUID
import io.sarl.util.OpenEventSpace
import io.sarl.util.OpenEventSpaceSpecification
import io.sarl.core.Initialize
import io.sarl.util.Scopes
event Ping {
val index : int
new (i : int) {
this.index = i
}
}
event Pong {
val index : int
new (i : int) {
this.index = i
}
}",
// TEXT
""
)
}
/* The previous code has a major problem:
* if there is no pong agent launched
* when the ping agent is sending
* the first `Ping` event, the application
* will reach a deadlock, even if
* the pong agent is launched later.
*
* For solving this problem, the ping
* agent must wait for sending the initial
* `Ping` event until the pong agent
* is belonging to the default space.
*
* The concrete implementation is based on
* the `Schedules` capacity, which provides
* a collection of functions for creating
* and launching asynchronous tasks.
*
* In the following code, a task is created with
* the name `waiting_for_partner`.
* This task is executed every second with
* the `every` function (given by the `Schedules`
* capacity). The code between
* the brackets contains the statements
* that will be periodically executed.
*
* In this periodically executed code,
* the agent is testing if it is the only
* one agent belonging to the default space.
* If not, the agent is sending the initial
* `Ping` event, and stopping the periodic task.
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Delaying the sending of the first Ping" {
'''
agent PingAgent {
uses DefaultContextInteractions, Behaviors, Schedules
var space : OpenEventSpace
on Initialize {
space = defaultContext.getOrCreateSpaceWithSpec(
typeof(OpenEventSpaceSpecification),
occurrence.parameters.get(0) as UUID)
space.register(asEventListener())
val task = task("waiting_for_partner")
task.every(1000) [
if (defaultSpace.participants.size > 1) {
var evt = new Ping(0)
evt.source = space.getAddress(getID)
space.emit( evt )
task.cancel
}
]
}
on Pong {
var evt = new Ping( occurrence.index + 1 )
evt.source = space.getAddress(getID)
space.emit(
evt,
Scopes.addresses( occurrence.source )
)
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Behaviors
import java.util.UUID
import io.sarl.util.OpenEventSpace
import io.sarl.util.OpenEventSpaceSpecification
import io.sarl.core.Initialize
import io.sarl.core.Schedules
import io.sarl.util.Scopes
event Ping {
val index : int
new (i : int) {
this.index = i
}
}
event Pong {
val index : int
new (i : int) {
this.index = i
}
}",
// TEXT
""
)
}
}
/* The fourth step of this tutorial is the definition
* of the launching process.
* In the rest of this section, we discuss the use
* of the [Janus runtime environment](http://www.janusproject.io)
* for running the agents.
*
*
* The Janus platform is designed to launch a single agent at start-up.
* Then, this launched agent must spawn the other agents in the system.
*
* <importantnote> In this section,
* we explain how to launch the agents from the command line interface.
* For launching the agents from the Eclipse IDE, please read
* ["Run SARL Agent in the Eclipse IDE"](../gettingstarted/RunSARLAgentInTheEclipseIDESpec.html).
* </importantnote>
*/
context "Compile and Launch the agents" {
/* You must have a file that contains
* the compiled files of the tutorial, the Janus platform,
* and all the needed libraries by SARL and Janus.
*
* You could directly download this file by clicking on
* the download icon at the top of this page; or by compiling
* the source code yourself.
*
* If you download the source code of the
* [SARL demos](https://github.com/sarl/sarl-demos), and
* compile them with [Maven](http://maven.apache.org),
* you will obtain a JAR file with all the mandatory elements
* inside. This file is located in the `target` folder,
* and it has a name similar to
* `sarl-demos-0.1.0-with-dependencies.jar`.
*
* @filter(.*)
*/
fact "Compile the code" {
// Test the URL in the introduction of this section
"../gettingstarted/RunSARLAgentInTheEclipseIDESpec.html" should beAccessibleFrom this
}
/* The principle is to run each agent is a different instance of the
* Janus platform.
*/
describe "Method 1: Execute each agent in their own instance of Janus" {
/* Here, there are two assumptions:<ol>
* <li>The file `sarl-demos-0.1.0-with-dependencies.jar`
* is executable, i.e. it can be directly launched by the Java
* Virtual Machine.</li>
* <li>From this file, the JVM is launching the Janus bootstrap automatically, i.e.
* it has a Main-Class set to `io.janusproject.Boot`.</li>
* </ol>
* On the command line, you must launch the Janus instances with:
*
* java -jar sarl-demos-0.1.0-with-dependencies.jar
* io.sarl.docs.tutorials.pingpongspace.PongAgent
*
* and:
*
* java -jar sarl-demos-0.1.0-with-dependencies.jar
* io.sarl.docs.tutorials.pingpongspace.PingAgent
*
* The file `sarl-demos-0.1.0-with-dependencies.jar` is explained above.
* The third arguments are the qualified names of the agents to launch.
*
* @filter(.*)
*/
fact "Execute with a runnable JAR" {
true
}
/* In opposite to the previous section, we assume that
* the file `sarl-demos-0.1.0-with-dependencies.jar`
* is not executable.
* On the command line, you must launch Janus with:
*
* java -cp sarl-demos-0.1.0-with-dependencies.jar
* io.janusproject.Boot
* io.sarl.docs.tutorials.pingpongspace.PongAgent
*
* and:
*
* java -cp sarl-demos-0.1.0-with-dependencies.jar
* io.janusproject.Boot
* io.sarl.docs.tutorials.pingpongspace.PingAgent
*
* The file `sarl-demos-0.1.0-with-dependencies.jar` is explained above.
* The string `io.janusproject.Boot` specifies the Java class to launch: the Janus bootstrap.
* The first arguments after the bootstraps are the qualified name
* of the agents to launch.
*
* @filter(.*)
*/
fact "Execute without a runnable JAR" {
true
}
}
/* The principle is to launch a single instance of Janus, and run all
* the agents inside.
* Because of the design of the Janus platform, we must define an
* agent that will launch the other agents. This agent is named
* `BootAgent`. It is defined below.
*
*/
describe "Method 2: Execute all the agents in a single instance of Janus" {
/* The boot agent uses the `DefaultContextInteractions`
* capacity for launching agents in the default context.
* This capacity provides the function `spawn(Class<? extends Agent>)`
* for launching an agent of the given type.
* When the boot agent has launched the two expected agents,
* it is killing itself. This is done with the `killMe`
* function, which is provided by the `Lifecycle` capacity.
*
* @filter(.* = '''|'''|.parseSuccessfully.*)
*/
fact "Defining the Boot agent" {
'''
agent BootAgent {
uses DefaultContextInteractions, Lifecycle
on Initialize {
spawn( PongAgent )
spawn( PingAgent )
killMe
}
}
'''.parseSuccessfully(
"package io.sarl.docs.tutorials.pingpongspace
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Initialize
import io.sarl.core.Lifecycle
agent PongAgent { }
agent PingAgent { }",
// TEXT
""
)
}
/* Here, there are two assumptions:<ol>
* <li>The file `sarl-demos-0.1.0-with-dependencies.jar`
* is executable, i.e. it can be directly launched by the Java
* Virtual Machine.</li>
* <li>From this file, the JVM is launching the Janus bootstrap automatically, i.e.
* it has a Main-Class set to `io.janusproject.Boot`.</li>
* </ol>
* On the command line, you must launch the Janus instance with:
*
* java -jar sarl-demos-0.1.0-with-dependencies.jar
* io.sarl.docs.tutorials.pingpongspace.BootAgent
*
* The file `sarl-demos-0.1.0-with-dependencies.jar` is explained above.
* The third argument is the qualified name of the agent to launch.
*
* @filter(.*)
*/
fact "Execute with a runnable JAR" {
true
}
/* In opposite to the previous section, we assume that
* the file `sarl-demos-0.1.0-with-dependencies.jar`
* is not executable.
* On the command line, you must launch Janus with:
*
* java -cp sarl-demos-0.1.0-with-dependencies.jar
* io.janusproject.Boot
* io.sarl.docs.tutorials.pingpongspace.BootAgent
*
* The file `sarl-demos-0.1.0-with-dependencies.jar` is explained above.
* The string `io.janusproject.Boot` specifies the Java class to launch: the Janus bootstrap.
* The first argument after the bootstrap is the qualified name of the agent to launch.
*
* @filter(.*)
*/
fact "Execute without a runnable JAR" {
true
}
}
}
}