copland 0.8.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/doc/manual-html/chapter-1.html +227 -36
  2. data/doc/manual-html/chapter-10.html +155 -82
  3. data/doc/manual-html/chapter-11.html +90 -267
  4. data/doc/manual-html/chapter-12.html +289 -71
  5. data/doc/manual-html/chapter-13.html +430 -0
  6. data/doc/manual-html/chapter-2.html +45 -21
  7. data/doc/manual-html/chapter-3.html +45 -21
  8. data/doc/manual-html/chapter-4.html +45 -21
  9. data/doc/manual-html/chapter-5.html +45 -21
  10. data/doc/manual-html/chapter-6.html +49 -21
  11. data/doc/manual-html/chapter-7.html +45 -21
  12. data/doc/manual-html/chapter-8.html +66 -26
  13. data/doc/manual-html/chapter-9.html +48 -24
  14. data/doc/manual-html/index.html +54 -22
  15. data/doc/manual-html/manual.css +12 -0
  16. data/doc/manual-html/tutorial-1.html +45 -21
  17. data/doc/manual-html/tutorial-2.html +45 -21
  18. data/doc/manual-html/tutorial-3.html +45 -21
  19. data/doc/manual-html/tutorial-4.html +45 -21
  20. data/doc/manual-html/tutorial-5.html +45 -21
  21. data/doc/manual/manual.css +12 -0
  22. data/doc/manual/manual.rb +1 -1
  23. data/doc/manual/manual.yml +426 -20
  24. data/doc/packages/copland.html +41 -9
  25. data/doc/packages/copland.lib.html +36 -8
  26. data/doc/packages/copland.remote.html +46 -10
  27. data/doc/packages/copland.webrick.html +16 -65
  28. data/doc/packages/index.html +1 -1
  29. data/doc/presentation/copland.mgp +1083 -0
  30. data/doc/presentation/to_html.rb +52 -0
  31. data/lib/copland/configuration-point/common.rb +32 -1
  32. data/lib/copland/configuration/yaml/service-point.rb +10 -1
  33. data/lib/copland/log-factory.rb +28 -12
  34. data/lib/copland/logger.rb +155 -0
  35. data/lib/copland/models/singleton.rb +8 -2
  36. data/lib/copland/package.rb +32 -14
  37. data/lib/copland/service-point.rb +7 -0
  38. data/lib/copland/thread.rb +104 -0
  39. data/lib/copland/utils.rb +10 -3
  40. data/lib/copland/version.rb +2 -2
  41. data/test/configuration/yaml/tc_service-point-processor.rb +8 -0
  42. data/test/custom-logger.yml +2 -1
  43. data/test/impl/tc_logging-interceptor.rb +12 -12
  44. data/test/logger.yml +1 -1
  45. data/test/mock.rb +2 -0
  46. data/test/tc_logger.rb +19 -6
  47. data/test/tc_package.rb +25 -0
  48. data/test/tc_queryable-mutex.rb +75 -0
  49. data/test/tc_registry.rb +8 -4
  50. metadata +9 -2
@@ -1,6 +1,6 @@
1
1
  <html>
2
2
  <head>
3
- <title>Copland Manual :: Chapter 12: Listeners and Event Producers</title>
3
+ <title>Copland Manual :: Chapter 12: Schemas</title>
4
4
  <link type="text/css" rel="stylesheet" href="manual.css" />
5
5
  </head>
6
6
 
@@ -14,8 +14,8 @@
14
14
  </div>
15
15
  </td><td valign='middle' align='right'>
16
16
  <div class="info">
17
- Copland Version: <strong>0.8.0</strong><br />
18
- Manual Last Updated: <strong>2004-09-27 03:37 GMT</strong>
17
+ Copland Version: <strong>1.0.0</strong><br />
18
+ Manual Last Updated: <strong>2004-10-12 02:22 GMT</strong>
19
19
  </div>
20
20
  </td></tr>
21
21
  </table>
@@ -39,13 +39,21 @@
39
39
 
40
40
  <li><a href="chapter-1.html#s1">What is Copland?</a></li>
41
41
 
42
- <li><a href="chapter-1.html#s2">Features</a></li>
42
+ <li><a href="chapter-1.html#s2">What Can Copland Do For Me?</a></li>
43
43
 
44
- <li><a href="chapter-1.html#s3">Getting Copland</a></li>
44
+ <li><a href="chapter-1.html#s3">Copland <em>sans</em> Buzzwords</a></li>
45
45
 
46
- <li><a href="chapter-1.html#s4">License Information</a></li>
46
+ <li><a href="chapter-1.html#s4">Copland <em>avec</em> Buzzwords</a></li>
47
47
 
48
- <li><a href="chapter-1.html#s5">Support</a></li>
48
+ <li><a href="chapter-1.html#s5">The Buzzwords Themselves</a></li>
49
+
50
+ <li><a href="chapter-1.html#s6">Features</a></li>
51
+
52
+ <li><a href="chapter-1.html#s7">Getting Copland</a></li>
53
+
54
+ <li><a href="chapter-1.html#s8">License Information</a></li>
55
+
56
+ <li><a href="chapter-1.html#s9">Support</a></li>
49
57
 
50
58
  </ol>
51
59
  </li>
@@ -149,7 +157,9 @@
149
157
 
150
158
  <li><a href="chapter-8.html#s1">Descriptor Syntax</a></li>
151
159
 
152
- <li><a href="chapter-8.html#s2">DefaultSymbolSource</a></li>
160
+ <li><a href="chapter-8.html#s2">FactoryDefaults</a></li>
161
+
162
+ <li><a href="chapter-8.html#s3">ApplicationDefaults</a></li>
153
163
 
154
164
  </ol>
155
165
  </li>
@@ -166,54 +176,68 @@
166
176
 
167
177
  <li>
168
178
  <a href="chapter-10.html">
169
- Service Factories
179
+ Logging
170
180
  </a>
171
181
 
172
182
  <ol type="1">
173
183
 
174
- <li><a href="chapter-10.html#s1">Schemas</a></li>
175
-
176
- <li><a href="chapter-10.html#s2">How do they work?</a></li>
184
+ <li><a href="chapter-10.html#s1">Log Factory</a></li>
177
185
 
178
- <li><a href="chapter-10.html#s3">BuilderFactory</a></li>
186
+ <li><a href="chapter-10.html#s2">Configuration</a></li>
179
187
 
180
188
  </ol>
181
189
  </li>
182
190
 
183
191
  <li>
184
192
  <a href="chapter-11.html">
185
- Schemas
193
+ Service Factories
186
194
  </a>
187
195
 
188
196
  <ol type="1">
189
197
 
190
- <li><a href="chapter-11.html#s1">Basic Format</a></li>
198
+ <li><a href="chapter-11.html#s1">Schemas</a></li>
199
+
200
+ <li><a href="chapter-11.html#s2">How do they work?</a></li>
201
+
202
+ <li><a href="chapter-11.html#s3">BuilderFactory</a></li>
203
+
204
+ </ol>
205
+ </li>
206
+
207
+ <li><strong>
208
+ <a href="chapter-12.html">
209
+ Schemas
210
+ </a>
211
+ </strong> <big>&larr;</big>
212
+ <ol type="1">
213
+
214
+ <li><a href="chapter-12.html#s1">Basic Format</a></li>
191
215
 
192
- <li><a href="chapter-11.html#s2">Subschemas</a></li>
216
+ <li><a href="chapter-12.html#s2">Subschemas</a></li>
193
217
 
194
- <li><a href="chapter-11.html#s3">Arrays</a></li>
218
+ <li><a href="chapter-12.html#s3">Arrays</a></li>
195
219
 
196
- <li><a href="chapter-11.html#s4">Named vs. Anonymous Schemas</a></li>
220
+ <li><a href="chapter-12.html#s4">Named vs. Anonymous Schemas</a></li>
197
221
 
198
- <li><a href="chapter-11.html#s5">Extending Schemas</a></li>
222
+ <li><a href="chapter-12.html#s5">Extending Schemas</a></li>
199
223
 
200
- <li><a href="chapter-11.html#s6">Limitations</a></li>
224
+ <li><a href="chapter-12.html#s6">Limitations</a></li>
201
225
 
202
226
  </ol>
203
227
  </li>
204
228
 
205
- <li><strong>
206
- <a href="chapter-12.html">
229
+ <li>
230
+ <a href="chapter-13.html">
207
231
  Listeners and Event Producers
208
232
  </a>
209
- </strong> <big>&larr;</big>
233
+
210
234
  <ol type="1">
211
235
 
212
- <li><a href="chapter-12.html#s1">Event Producers</a></li>
236
+ <li><a href="chapter-13.html#s1">Event Producers</a></li>
213
237
 
214
- <li><a href="chapter-12.html#s2">Listeners</a></li>
238
+ <li><a href="chapter-13.html#s2">Listeners</a></li>
215
239
 
216
- <li><a href="chapter-12.html#s3">The Registry as an Event Producer</a></li>
240
+ <li><a href="chapter-13.html#s3">The Registry as an Event Producer</a></li>
217
241
 
218
242
  </ol>
219
243
  </li>
@@ -291,12 +315,12 @@
291
315
 
292
316
  <div id="content">
293
317
 
294
- <h1>12. Listeners and Event Producers</h1>
318
+ <h1>12. Schemas</h1>
295
319
 
296
320
 
297
321
 
298
322
  <div class="section">
299
- <p>Sometimes, you may have a service that produces events. In terms of a <span class="caps">GUI</span>, you might have a button that emits events liked &#8220;clicked&#8221;, &#8220;mouse over&#8221;, &#8220;mouse out&#8221;, &#8220;mouse down&#8221;, and so forth. Copland provides a framework for indicating that instances of a particular service point should listen for events from instances of another service point.<br />
323
+ <p>&#8220;Schemas&#8221; are the mechanism by which you can restrict what values are contributed to configuration points, or which parameters are acceptable to a service constructed via a factory service.<br />
300
324
  </p>
301
325
  </div>
302
326
 
@@ -304,95 +328,289 @@
304
328
 
305
329
  <h2>
306
330
  <a name="s1"></a>
307
- 12.1. Event Producers
331
+ 12.1. Basic Format
332
+ </h2>
333
+
334
+
335
+
336
+ <div class="section">
337
+ <p>In <span class="caps">YAML</span> terminology, a schema is simply a map that follows a special format. Consider the following configuration point:</p>
338
+
339
+ <pre>
340
+ MyConfigurationPoint:
341
+ type: map
342
+ schema:
343
+ definition:
344
+ user.name:
345
+ type: string
346
+ required: true
347
+ home.directory:
348
+ type: string
349
+ user.groups:
350
+ type: array
351
+ </pre>
352
+
353
+ <p>This configuration point is a map that only allows three keys: <code>user.name</code>, <code>home.directory</code>, and <code>user.groups</code>. Any contribution made to this configuration point <em>must not</em> contain any keys other than these values. And since the <code>user.name</code> key is marked as required, any contribution to this configuration point <em>must</em> contain at least that key.</p>
354
+
355
+ <p>Note the type definitions as well. The recognized types are:</p>
356
+
357
+ <ul>
358
+ <li><code>any</code></li>
359
+ <li><code>array</code></li>
360
+ <li><code>configuration</code></li>
361
+ <li><code>integer</code></li>
362
+ <li><code>log</code></li>
363
+ <li><code>hash</code></li>
364
+ <li><code>real</code></li>
365
+ <li><code>service</code></li>
366
+ <li><code>string</code></li>
367
+ </ul>
368
+
369
+ <p>If the type is left out, it defaults to <code>any</code>. If a value is contributed to that key that is not of the required type, a validation error results.</p>
370
+
371
+ <p>Note that schemas may be applied to service points as well, in identical fashion to that of configuration points. (That is to say, they are introduced by the <code>schema</code> descriptor element.) In that case, the schema applies to the parameters of any service point that uses this service point as its factory service.</p>
372
+ </div>
373
+
374
+
375
+
376
+ <h2>
377
+ <a name="s2"></a>
378
+ 12.2. Subschemas
308
379
  </h2>
309
380
 
310
381
 
311
382
 
312
383
  <div class="section">
313
- <p>At one end of this functionality is the <em>event producer</em>. Using the above example, this would be the button. It is the service that generates and emits the events.</p>
384
+ <p>Schemas may be nested, to allow for arbitrarily deep schema &#8220;trees&#8221;. Consider the following example:</p>
385
+
386
+ <pre>
387
+ MyConfigurationPoint:
388
+ type: map
389
+ schema:
390
+ definition:
391
+ user.name:
392
+ type: string
393
+ required: true
394
+ home.directory:
395
+ type: string
396
+ user.groups:
397
+ type: array
398
+ user.address:
399
+ definition:
400
+ line1:
401
+ type: string
402
+ line2:
403
+ type: string
404
+ city:
405
+ type: string
406
+ state:
407
+ type: string
408
+ zip:
409
+ type: string
410
+ </pre>
411
+
412
+ <p>In this case, the <code>user.address</code> element of the schema is itself <em>another schema</em>. That is to say, any element that it matches must be a hash, which may be empty, but which may contain no keys other than those specified (<code>line1</code>, <code>line2</code>, <code>city</code>, <code>state</code>, and <code>zip</code>).</p>
413
+
414
+ <p>If you specify a subschema definintion (via the <code>definition</code> keyword), and the same element is of any type other than <code>hash</code> or <code>array</code>, you&#8217;ll get an error. You cannot used schema&#8217;s to validate any other type of data. (Arrays are a special case&#8212;see the next section.)</p>
415
+ </div>
416
+
314
417
 
315
- <p>Any service can be an event producer&#8212;all it requires is that the service implement an <code>#add_listener</code> method by which other services may be added as interested parties. Also, although there is nothing that prevents you from using non-singleton services as event producers, it really only works correctly with services using the <code>singleton</code> and <code>singleton-deferred</code> model.</p>
316
418
 
317
- <p>When an event occurs, the producer should notify those registered listeners by invoking a method on them. The method should be named &#8220;on_#{event}&#8221; (where event is the name of the event), and it should accept the producer as the first argument, followed by any number of other arguments (as needed for the given event). The listener method should only be invoked if the listener responds to that method; otherwise, it should be silently skipped.</p>
419
+ <h2>
420
+ <a name="s3"></a>
421
+ 12.3. Arrays
422
+ </h2>
318
423
 
319
- <p>Optionally, if a listener does not respond to a specific event, the producer may look for a method called &#8220;on_any_event&#8221;; if the listener responds to that, that method may be invoked instead, with the producer as the first parameter and the event as the second, followed by any additional arguments.</p>
424
+
320
425
 
321
- <p>To make it easier to create event producers, you can mixin the Copland::EventProducer module into your existing services. It provides several methods, including <code>#add_listener</code> and <code>#fire_event</code>.</p>
426
+ <div class="section">
427
+ <p>When you specify a schema for an array (or for a configuration point of type <code>list</code>), the schema will be applied to every element of any array that is contributed. For example, consider this:</p>
322
428
 
323
429
  <pre>
324
- require 'copland/event-producer'
430
+ MoviesILike:
431
+ type: list
432
+ schema:
433
+ definition:
434
+ name:
435
+ type: string
436
+ required: true
437
+ genre:
438
+ type: string
439
+ actors:
440
+ type: array
441
+ definition:
442
+ name:
443
+ type: string
444
+ required: true
445
+ gender:
446
+ type: string
447
+ birthdate:
448
+ type: string
449
+ </pre>
325
450
 
326
- class MyProducerService
327
- include Copland::EventProducer
451
+ <p>This configuration point is a <code>list</code>. Every element that is contributed to it must conform to the given schema. Note, too, that the <code>actors</code> element of the schema expects an array, and that each element of <em>that</em> array must conform to the given subschema.</p>
328
452
 
329
- def click
330
- do_something_about_it
331
- fire_event :clicked
332
- end
453
+ <p>Given that schema, the following contribution would be valid:</p>
333
454
 
334
- def mouse_over
335
- do_something_else_about_it
336
- fire_event :mouse_over
337
- end
338
- end
455
+ <pre>
456
+ contributions:
457
+
458
+ MoviesILike:
459
+ - name: Twelve Angry Men
460
+ genre: Drama
461
+ actors:
462
+ - name: Henry Fonda
463
+ gender: male
464
+ birthdate: 16 May 1905
465
+ - name: Jack Klugman
466
+ birthdate: 27 Apr 1922
467
+ - name: Ed Binns
468
+ - name: John Fiedler
469
+ - name: Lawrence of Arabia
470
+ actors:
471
+ - name: Peter O'Toole
472
+ - name: Alec Guinness
473
+ birthdate: 2 Apr 1914
474
+ - name: Remains of the Day
339
475
  </pre>
340
476
  </div>
341
477
 
342
478
 
343
479
 
344
480
  <h2>
345
- <a name="s2"></a>
346
- 12.2. Listeners
481
+ <a name="s4"></a>
482
+ 12.4. Named vs. Anonymous Schemas
347
483
  </h2>
348
484
 
349
485
 
350
486
 
351
487
  <div class="section">
352
- <p>Listeners are at the other end of the producer/listener link. As with the event producer, any service can be a listener. It just needs to implement a method for each event that it is interested in, and then indicate (in its service point) that it wants to be registered as a listener of a particular service. Unlike event producers, the listeners can use any service model they like.</p>
488
+ <p>The schemas that have been shown so far have been <em>anonymous</em>. This is fine for schemas that are very specific and have a very special purpose. However, sometimes, you want several configuration points of service points to have the same schema. To accomplish this, you need to give your schemas names.</p>
489
+
490
+ <p>Named schemas are owned by the package in which they are defined, but once named they may be used in any package (just like service points and configuration points).</p>
353
491
 
354
- <p>As described above, the listener methods are named &#8220;on_#{event}&#8221;, where &#8220;event&#8221; is the name of the event to listen to. Alternatively, a listener may declare a method called &#8220;on_any_event&#8221;, which will be called for any event that does not have an explicit listener method declared for.</p>
492
+ <p>To name a schema, just add a <code>name</code> element at the same level as the <code>definition</code> element:</p>
355
493
 
356
494
  <pre>
357
- class MyListenerService
358
- def on_click( producer, *args )
359
- puts "Argh! It was clicked!"
360
- end
361
-
362
- def on_any_event( producer, event, *args )
363
- puts "Something happened: #{event}"
364
- end
365
- end
495
+ MoviesILike:
496
+ type: list
497
+ schema:
498
+ name: MovieDefinition
499
+ definition:
500
+ ...
366
501
  </pre>
367
502
 
368
- <p>To register interest in the producer, use the <code>listen-to</code> element when defining the service point. This element expects an array of service point names. Every time the service point is instantiated, the list of <code>listen-to</code> elements will be processed and the new service will be added to each of those service points in turn, as a listener:</p>
503
+ <p>Then, you can reuse the schema by putting the schema name after the <code>schema</code> element, instead of a hash:</p>
369
504
 
370
505
  <pre>
371
- service-points:
506
+ MoviesIHate:
507
+ type: list
508
+ schema: MovieDefinition
509
+ </pre>
372
510
 
373
- Producer:
374
- implementor: MyProducerService
511
+ <p>This second configuration point will reuse the <code>MovieDefinition</code> schema. Note that you can specify an existing schema (or name a schema) at any level of a schema definition:</p>
375
512
 
376
- Listener:
377
- implementor: MyListenerService
378
- listen-to:
379
- - Producer
513
+ <pre>
514
+ MoviesILike:
515
+ type: list
516
+ schema:
517
+ name: MovieDefinition
518
+ definition:
519
+ name:
520
+ type: string
521
+ required: true
522
+ genre:
523
+ type: string
524
+ actors:
525
+ name: ActorDefinition
526
+ type: array
527
+ definition:
528
+ name:
529
+ type: string
530
+ required: true
531
+ gender:
532
+ type: string
533
+ birthdate:
534
+ type: string
535
+
536
+ MoviesIHate:
537
+ type: list
538
+ schema: MovieDefinition
539
+
540
+ FavoriteActors:
541
+ type: list
542
+ schema: ActorDefinition
543
+
544
+ PartiesAttended:
545
+ type: list
546
+ schema:
547
+ definition:
548
+ place:
549
+ type: string
550
+ host:
551
+ type: string
552
+ attendees: ActorDefinition
380
553
  </pre>
381
554
  </div>
382
555
 
383
556
 
384
557
 
385
558
  <h2>
386
- <a name="s3"></a>
387
- 12.3. The Registry as an Event Producer
559
+ <a name="s5"></a>
560
+ 12.5. Extending Schemas
561
+ </h2>
562
+
563
+
564
+
565
+ <div class="section">
566
+ <p>Sometimes it happens that you want to create a schema that is <em>almost</em> like an existing schema, but adds one or two new elements. You can do this in Copland by <em>extending</em> the existing schema:</p>
567
+
568
+ <pre>
569
+ People:
570
+ type: list
571
+ schema:
572
+ name: PersonSchema
573
+ definition:
574
+ name:
575
+ required: true
576
+ type: string
577
+ gender:
578
+ required: true
579
+ type: string
580
+
581
+ Employees:
582
+ type: list
583
+ schema:
584
+ name: EmployeeSchema
585
+ extend: PersonSchema
586
+ definition:
587
+ department:
588
+ required: true
589
+ type: string
590
+ </pre>
591
+
592
+ <p>In the above instance, the &#8220;EmployeeSchema&#8221; is exactly like the PersonSchema, except it adds a &#8220;department&#8221; key.</p>
593
+ </div>
594
+
595
+
596
+
597
+ <h2>
598
+ <a name="s6"></a>
599
+ 12.6. Limitations
388
600
  </h2>
389
601
 
390
602
 
391
603
 
392
604
  <div class="section">
393
- <p>Currently, Copland only comes with one event producer built in&#8212;the registry itself. Every time you instantiate a registry, it adds itself to itself as the &#8220;copland.Registry&#8221; service. When the registry is shutdown, it emits a <code>:registry_shutdown</code> event to all of its listeners.</p>
605
+ <p>The existing schema implementation is sufficient for most purposes, but it has some limitations:</p>
606
+
607
+ <ul>
608
+ <li>You cannot specify a format for a non-hash value.</li>
609
+ <li>You cannot specify whether a subschema that reuses an existing schema is required or not.</li>
610
+ <li>You cannot enforce the constraint &#8220;any one of a set of keys is required.&#8221; The schema subsystem only understands a single key being required or not.</li>
611
+ </ul>
394
612
 
395
- <p>Thus, if you have a service that you want to be able to do some cleanup when the registry is being shutdown, you can have that service listen to &#8220;copland.Registry&#8221;, and implement a listener method called <code>on_registry_shutdown</code> (or <code>on_any_event</code>).</p>
613
+ <p>For most purposes, however, it is sufficient.</p>
396
614
  </div>
397
615
 
398
616