copland 0.8.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/doc/manual-html/chapter-1.html +227 -36
- data/doc/manual-html/chapter-10.html +155 -82
- data/doc/manual-html/chapter-11.html +90 -267
- data/doc/manual-html/chapter-12.html +289 -71
- data/doc/manual-html/chapter-13.html +430 -0
- data/doc/manual-html/chapter-2.html +45 -21
- data/doc/manual-html/chapter-3.html +45 -21
- data/doc/manual-html/chapter-4.html +45 -21
- data/doc/manual-html/chapter-5.html +45 -21
- data/doc/manual-html/chapter-6.html +49 -21
- data/doc/manual-html/chapter-7.html +45 -21
- data/doc/manual-html/chapter-8.html +66 -26
- data/doc/manual-html/chapter-9.html +48 -24
- data/doc/manual-html/index.html +54 -22
- data/doc/manual-html/manual.css +12 -0
- data/doc/manual-html/tutorial-1.html +45 -21
- data/doc/manual-html/tutorial-2.html +45 -21
- data/doc/manual-html/tutorial-3.html +45 -21
- data/doc/manual-html/tutorial-4.html +45 -21
- data/doc/manual-html/tutorial-5.html +45 -21
- data/doc/manual/manual.css +12 -0
- data/doc/manual/manual.rb +1 -1
- data/doc/manual/manual.yml +426 -20
- data/doc/packages/copland.html +41 -9
- data/doc/packages/copland.lib.html +36 -8
- data/doc/packages/copland.remote.html +46 -10
- data/doc/packages/copland.webrick.html +16 -65
- data/doc/packages/index.html +1 -1
- data/doc/presentation/copland.mgp +1083 -0
- data/doc/presentation/to_html.rb +52 -0
- data/lib/copland/configuration-point/common.rb +32 -1
- data/lib/copland/configuration/yaml/service-point.rb +10 -1
- data/lib/copland/log-factory.rb +28 -12
- data/lib/copland/logger.rb +155 -0
- data/lib/copland/models/singleton.rb +8 -2
- data/lib/copland/package.rb +32 -14
- data/lib/copland/service-point.rb +7 -0
- data/lib/copland/thread.rb +104 -0
- data/lib/copland/utils.rb +10 -3
- data/lib/copland/version.rb +2 -2
- data/test/configuration/yaml/tc_service-point-processor.rb +8 -0
- data/test/custom-logger.yml +2 -1
- data/test/impl/tc_logging-interceptor.rb +12 -12
- data/test/logger.yml +1 -1
- data/test/mock.rb +2 -0
- data/test/tc_logger.rb +19 -6
- data/test/tc_package.rb +25 -0
- data/test/tc_queryable-mutex.rb +75 -0
- data/test/tc_registry.rb +8 -4
- metadata +9 -2
@@ -1,6 +1,6 @@
|
|
1
1
|
<html>
|
2
2
|
<head>
|
3
|
-
<title>Copland Manual :: Chapter 11:
|
3
|
+
<title>Copland Manual :: Chapter 11: Service Factories</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.
|
18
|
-
Manual Last Updated: <strong>2004-
|
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">
|
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">
|
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">
|
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">
|
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">
|
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
|
-
|
179
|
+
Logging
|
170
180
|
</a>
|
171
181
|
|
172
182
|
<ol type="1">
|
173
183
|
|
174
|
-
<li><a href="chapter-10.html#s1">
|
184
|
+
<li><a href="chapter-10.html#s1">Log Factory</a></li>
|
175
185
|
|
176
|
-
<li><a href="chapter-10.html#s2">
|
177
|
-
|
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><strong>
|
184
192
|
<a href="chapter-11.html">
|
185
|
-
|
193
|
+
Service Factories
|
186
194
|
</a>
|
187
195
|
</strong> <big>←</big>
|
188
196
|
<ol type="1">
|
189
197
|
|
190
|
-
<li><a href="chapter-11.html#s1">
|
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>
|
208
|
+
<a href="chapter-12.html">
|
209
|
+
Schemas
|
210
|
+
</a>
|
211
|
+
|
212
|
+
<ol type="1">
|
213
|
+
|
214
|
+
<li><a href="chapter-12.html#s1">Basic Format</a></li>
|
191
215
|
|
192
|
-
<li><a href="chapter-
|
216
|
+
<li><a href="chapter-12.html#s2">Subschemas</a></li>
|
193
217
|
|
194
|
-
<li><a href="chapter-
|
218
|
+
<li><a href="chapter-12.html#s3">Arrays</a></li>
|
195
219
|
|
196
|
-
<li><a href="chapter-
|
220
|
+
<li><a href="chapter-12.html#s4">Named vs. Anonymous Schemas</a></li>
|
197
221
|
|
198
|
-
<li><a href="chapter-
|
222
|
+
<li><a href="chapter-12.html#s5">Extending Schemas</a></li>
|
199
223
|
|
200
|
-
<li><a href="chapter-
|
224
|
+
<li><a href="chapter-12.html#s6">Limitations</a></li>
|
201
225
|
|
202
226
|
</ol>
|
203
227
|
</li>
|
204
228
|
|
205
229
|
<li>
|
206
|
-
<a href="chapter-
|
230
|
+
<a href="chapter-13.html">
|
207
231
|
Listeners and Event Producers
|
208
232
|
</a>
|
209
233
|
|
210
234
|
<ol type="1">
|
211
235
|
|
212
|
-
<li><a href="chapter-
|
236
|
+
<li><a href="chapter-13.html#s1">Event Producers</a></li>
|
213
237
|
|
214
|
-
<li><a href="chapter-
|
238
|
+
<li><a href="chapter-13.html#s2">Listeners</a></li>
|
215
239
|
|
216
|
-
<li><a href="chapter-
|
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,302 +315,101 @@
|
|
291
315
|
|
292
316
|
<div id="content">
|
293
317
|
|
294
|
-
<h1>11.
|
318
|
+
<h1>11. Service Factories</h1>
|
295
319
|
|
296
320
|
|
297
321
|
|
298
322
|
<div class="section">
|
299
|
-
<p
|
300
|
-
</p>
|
301
|
-
</div>
|
323
|
+
<p>Sometimes it requires a little more effort (or a lot more effort) to instantiate and initialize a service than simply calling <code>#new</code> on it’s associated class. In such cases, you need to rely on a <em>service factory</em> to instantiate the service.</p>
|
302
324
|
|
325
|
+
<p>A service factory is just a regular service as far as Copland is concerned. It is declared in the usual way. However, a service that will be used as a service factory must implement at least one method: <code>#create_instance</code>. This method should accept two parameters, the <em>service point</em> to instantiate, and the <em>parameters</em> associated with this instantiation. (The <code>parameters</code> parameter will always be a hash.)</p>
|
303
326
|
|
304
|
-
|
305
|
-
<h2>
|
306
|
-
<a name="s1"></a>
|
307
|
-
11.1. Basic Format
|
308
|
-
</h2>
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
<div class="section">
|
313
|
-
<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>
|
327
|
+
<p>Here is an example that implements a trivial service factory:</p>
|
314
328
|
|
315
329
|
<pre>
|
316
|
-
|
317
|
-
type: map
|
318
|
-
schema:
|
319
|
-
definition:
|
320
|
-
user.name:
|
321
|
-
type: string
|
322
|
-
required: true
|
323
|
-
home.directory:
|
324
|
-
type: string
|
325
|
-
user.groups:
|
326
|
-
type: array
|
327
|
-
</pre>
|
328
|
-
|
329
|
-
<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>
|
330
|
-
|
331
|
-
<p>Note the type definitions as well. The recognized types are:</p>
|
332
|
-
|
333
|
-
<ul>
|
334
|
-
<li><code>any</code></li>
|
335
|
-
<li><code>array</code></li>
|
336
|
-
<li><code>configuration</code></li>
|
337
|
-
<li><code>integer</code></li>
|
338
|
-
<li><code>log</code></li>
|
339
|
-
<li><code>hash</code></li>
|
340
|
-
<li><code>real</code></li>
|
341
|
-
<li><code>service</code></li>
|
342
|
-
<li><code>string</code></li>
|
343
|
-
</ul>
|
344
|
-
|
345
|
-
<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>
|
346
|
-
|
347
|
-
<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>
|
348
|
-
</div>
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
<h2>
|
353
|
-
<a name="s2"></a>
|
354
|
-
11.2. Subschemas
|
355
|
-
</h2>
|
356
|
-
|
357
|
-
|
330
|
+
class ExampleServiceFactory
|
358
331
|
|
359
|
-
|
360
|
-
|
332
|
+
def create_instance( point, parms )
|
333
|
+
return { :point => point,
|
334
|
+
:parms => parms }
|
335
|
+
end
|
361
336
|
|
362
|
-
|
363
|
-
MyConfigurationPoint:
|
364
|
-
type: map
|
365
|
-
schema:
|
366
|
-
definition:
|
367
|
-
user.name:
|
368
|
-
type: string
|
369
|
-
required: true
|
370
|
-
home.directory:
|
371
|
-
type: string
|
372
|
-
user.groups:
|
373
|
-
type: array
|
374
|
-
user.address:
|
375
|
-
definition:
|
376
|
-
line1:
|
377
|
-
type: string
|
378
|
-
line2:
|
379
|
-
type: string
|
380
|
-
city:
|
381
|
-
type: string
|
382
|
-
state:
|
383
|
-
type: string
|
384
|
-
zip:
|
385
|
-
type: string
|
337
|
+
end
|
386
338
|
</pre>
|
387
339
|
|
388
|
-
<p>
|
389
|
-
|
390
|
-
<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’ll get an error. You cannot used schema’s to validate any other type of data. (Arrays are a special case—see the next section.)</p>
|
391
|
-
</div>
|
392
|
-
|
340
|
+
<p>This service would be introduced into Copland via the following package descriptor:</p>
|
393
341
|
|
342
|
+
<pre>
|
343
|
+
---
|
344
|
+
id: example
|
394
345
|
|
395
|
-
|
396
|
-
<a name="s3"></a>
|
397
|
-
11.3. Arrays
|
398
|
-
</h2>
|
346
|
+
service-points:
|
399
347
|
|
400
|
-
|
348
|
+
ExampleServiceFactory:
|
349
|
+
implementor: some/file/ExampleServiceFactory
|
350
|
+
</pre>
|
401
351
|
|
402
|
-
|
403
|
-
<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>
|
352
|
+
<p>And it would be employed like this:</p>
|
404
353
|
|
405
354
|
<pre>
|
406
|
-
|
407
|
-
|
408
|
-
schema:
|
409
|
-
definition:
|
410
|
-
name:
|
411
|
-
type: string
|
412
|
-
required: true
|
413
|
-
genre:
|
414
|
-
type: string
|
415
|
-
actors:
|
416
|
-
type: array
|
417
|
-
definition:
|
418
|
-
name:
|
419
|
-
type: string
|
420
|
-
required: true
|
421
|
-
gender:
|
422
|
-
type: string
|
423
|
-
birthdate:
|
424
|
-
type: string
|
425
|
-
</pre>
|
355
|
+
---
|
356
|
+
id: demo
|
426
357
|
|
427
|
-
|
358
|
+
service-points:
|
428
359
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
contributions:
|
433
|
-
|
434
|
-
MoviesILike:
|
435
|
-
- name: Twelve Angry Men
|
436
|
-
genre: Drama
|
437
|
-
actors:
|
438
|
-
- name: Henry Fonda
|
439
|
-
gender: male
|
440
|
-
birthdate: 16 May 1905
|
441
|
-
- name: Jack Klugman
|
442
|
-
birthdate: 27 Apr 1922
|
443
|
-
- name: Ed Binns
|
444
|
-
- name: John Fiedler
|
445
|
-
- name: Lawrence of Arabia
|
446
|
-
actors:
|
447
|
-
- name: Peter O'Toole
|
448
|
-
- name: Alec Guinness
|
449
|
-
birthdate: 2 Apr 1914
|
450
|
-
- name: Remains of the Day
|
360
|
+
ExampleService:
|
361
|
+
implementor:
|
362
|
+
factory: example.ExampleServiceFactory
|
451
363
|
</pre>
|
364
|
+
|
365
|
+
<p>This service factory, when used to instantiate a service, would always return a new Hash object consisting of the service point and its parameters. Thus, the <code>ExampleService</code> service point would, when instantiated, always consist of a hash containing its own service point, and any parameters that were given when it was instantiated (none, in this case). Not a very useful service factory, but it demonstrates what it ought to do.<br />
|
366
|
+
</p>
|
452
367
|
</div>
|
453
368
|
|
454
369
|
|
455
370
|
|
456
371
|
<h2>
|
457
|
-
<a name="
|
458
|
-
11.
|
372
|
+
<a name="s1"></a>
|
373
|
+
11.1. Schemas
|
459
374
|
</h2>
|
460
375
|
|
461
376
|
|
462
377
|
|
463
378
|
<div class="section">
|
464
|
-
<p>
|
465
|
-
|
466
|
-
<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>
|
467
|
-
|
468
|
-
<p>To name a schema, just add a <code>name</code> element at the same level as the <code>definition</code> element:</p>
|
469
|
-
|
470
|
-
<pre>
|
471
|
-
MoviesILike:
|
472
|
-
type: list
|
473
|
-
schema:
|
474
|
-
name: MovieDefinition
|
475
|
-
definition:
|
476
|
-
...
|
477
|
-
</pre>
|
478
|
-
|
479
|
-
<p>Then, you can reuse the schema by putting the schema name after the <code>schema</code> element, instead of a hash:</p>
|
480
|
-
|
481
|
-
<pre>
|
482
|
-
MoviesIHate:
|
483
|
-
type: list
|
484
|
-
schema: MovieDefinition
|
485
|
-
</pre>
|
486
|
-
|
487
|
-
<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>
|
488
|
-
|
489
|
-
<pre>
|
490
|
-
MoviesILike:
|
491
|
-
type: list
|
492
|
-
schema:
|
493
|
-
name: MovieDefinition
|
494
|
-
definition:
|
495
|
-
name:
|
496
|
-
type: string
|
497
|
-
required: true
|
498
|
-
genre:
|
499
|
-
type: string
|
500
|
-
actors:
|
501
|
-
name: ActorDefinition
|
502
|
-
type: array
|
503
|
-
definition:
|
504
|
-
name:
|
505
|
-
type: string
|
506
|
-
required: true
|
507
|
-
gender:
|
508
|
-
type: string
|
509
|
-
birthdate:
|
510
|
-
type: string
|
511
|
-
|
512
|
-
MoviesIHate:
|
513
|
-
type: list
|
514
|
-
schema: MovieDefinition
|
515
|
-
|
516
|
-
FavoriteActors:
|
517
|
-
type: list
|
518
|
-
schema: ActorDefinition
|
519
|
-
|
520
|
-
PartiesAttended:
|
521
|
-
type: list
|
522
|
-
schema:
|
523
|
-
definition:
|
524
|
-
place:
|
525
|
-
type: string
|
526
|
-
host:
|
527
|
-
type: string
|
528
|
-
attendees: ActorDefinition
|
529
|
-
</pre>
|
379
|
+
<p>As mentioned in the chapter on service points, a service point may be associated with a <em>schema</em>. More will be said on schemas (and specifically, on their formats) in the next chapter, but suffice it to say here that the schema allows a service point to specify what parameters it accepts when invoked as a factory service.<br />
|
380
|
+
</p>
|
530
381
|
</div>
|
531
382
|
|
532
383
|
|
533
384
|
|
534
385
|
<h2>
|
535
|
-
<a name="
|
536
|
-
11.
|
386
|
+
<a name="s2"></a>
|
387
|
+
11.2. How do they work?
|
537
388
|
</h2>
|
538
389
|
|
539
390
|
|
540
391
|
|
541
392
|
<div class="section">
|
542
|
-
<p>
|
393
|
+
<p>When you specify a factory service as the implementor of another service, Copland automatically marks that service point as needing a <em>complex instantiator</em>. Thus, when it comes time to instantiate the service point, the parameters are collected, and if the factory has a schema, the parameters are validated against that schema. Then, the parameters are preprocessed (to translate values to their appropriate and expected types), and the factory’s <code>#create_instance</code> method is called. The result of that call is then treated as the new service.</p>
|
543
394
|
|
544
|
-
<
|
545
|
-
|
546
|
-
type: list
|
547
|
-
schema:
|
548
|
-
name: PersonSchema
|
549
|
-
definition:
|
550
|
-
name:
|
551
|
-
required: true
|
552
|
-
type: string
|
553
|
-
gender:
|
554
|
-
required: true
|
555
|
-
type: string
|
556
|
-
|
557
|
-
Employees:
|
558
|
-
type: list
|
559
|
-
schema:
|
560
|
-
name: EmployeeSchema
|
561
|
-
extend: PersonSchema
|
562
|
-
definition:
|
563
|
-
department:
|
564
|
-
required: true
|
565
|
-
type: string
|
566
|
-
</pre>
|
567
|
-
|
568
|
-
<p>In the above instance, the “EmployeeSchema” is exactly like the PersonSchema, except it adds a “department” key.</p>
|
395
|
+
<p>Contrast this with the <em>simple instantiator</em>. When the simple instantiator is used, all it does (more or less) is invoke <code>#new</code> on the named class and return the result. The existence of factory services allows for much more complex (and powerful) behavior.<br />
|
396
|
+
</p>
|
569
397
|
</div>
|
570
398
|
|
571
399
|
|
572
400
|
|
573
401
|
<h2>
|
574
|
-
<a name="
|
575
|
-
11.
|
402
|
+
<a name="s3"></a>
|
403
|
+
11.3. BuilderFactory
|
576
404
|
</h2>
|
577
405
|
|
578
406
|
|
579
407
|
|
580
408
|
<div class="section">
|
581
|
-
<p>
|
409
|
+
<p>Copland comes with one predefined factory service: <code>copland.BuilderFactory</code>. With this factory you can implement most of the more common types of services. (There are always special cases, though—the <code>copland.lib</code>, <code>copland.remote</code> and <code>copland.webrick</code> libraries all define additional factory services for specialized uses.)</p>
|
582
410
|
|
583
|
-
<
|
584
|
-
|
585
|
-
<li>You cannot specify whether a subschema that reuses an existing schema is required or not.</li>
|
586
|
-
<li>You cannot enforce the constraint “any one of a set of keys is required.” The schema subsystem only understands a single key being required or not.</li>
|
587
|
-
</ul>
|
588
|
-
|
589
|
-
<p>For most purposes, however, it is sufficient.</p>
|
411
|
+
<p>The BuilderFactory allows you to not only instantiate a class, but to specify constructor parameters and set properties on the new object. It also allows you to specify methods that should be invoked in order to initialize a service. It is by this means that the “dependency injection” aspect of Copland comes into play.<br />
|
412
|
+
</p>
|
590
413
|
</div>
|
591
414
|
|
592
415
|
|