copland 0.8.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|