copland 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/README +88 -0
- data/doc/manual-html/chapter-1.html +454 -0
- data/doc/manual-html/chapter-10.html +399 -0
- data/doc/manual-html/chapter-11.html +600 -0
- data/doc/manual-html/chapter-12.html +406 -0
- data/doc/manual-html/chapter-2.html +382 -0
- data/doc/manual-html/chapter-3.html +424 -0
- data/doc/manual-html/chapter-4.html +432 -0
- data/doc/manual-html/chapter-5.html +381 -0
- data/doc/manual-html/chapter-6.html +364 -0
- data/doc/manual-html/chapter-7.html +434 -0
- data/doc/manual-html/chapter-8.html +373 -0
- data/doc/manual-html/chapter-9.html +324 -0
- data/doc/manual-html/copland.png +0 -0
- data/doc/manual-html/index.html +331 -0
- data/doc/manual-html/manual.css +179 -0
- data/doc/manual-html/tutorial-1.html +407 -0
- data/doc/manual-html/tutorial-2.html +451 -0
- data/doc/manual-html/tutorial-3.html +484 -0
- data/doc/manual-html/tutorial-4.html +446 -0
- data/doc/manual-html/tutorial-5.html +520 -0
- data/doc/manual/chapter.erb +18 -0
- data/doc/manual/example.erb +18 -0
- data/doc/manual/img/copland.png +0 -0
- data/doc/manual/index.erb +30 -0
- data/doc/manual/manual.css +179 -0
- data/doc/manual/manual.rb +239 -0
- data/doc/manual/manual.yml +2643 -0
- data/doc/manual/page.erb +102 -0
- data/doc/manual/tutorial.erb +30 -0
- data/doc/packages/copland.html +764 -0
- data/doc/packages/copland.lib.html +439 -0
- data/doc/packages/copland.remote.html +2096 -0
- data/doc/packages/copland.webrick.html +925 -0
- data/doc/packages/index.html +49 -0
- data/doc/packages/packrat.css +125 -0
- data/examples/calc/calc.rb +47 -0
- data/examples/calc/package.yml +35 -0
- data/examples/calc/services.rb +74 -0
- data/examples/solitaire-cipher/README +11 -0
- data/examples/solitaire-cipher/Rakefile +57 -0
- data/examples/solitaire-cipher/bin/main.rb +14 -0
- data/examples/solitaire-cipher/lib/cipher.rb +230 -0
- data/examples/solitaire-cipher/lib/cli.rb +24 -0
- data/examples/solitaire-cipher/lib/package.yml +106 -0
- data/examples/solitaire-cipher/test/tc_deck.rb +30 -0
- data/examples/solitaire-cipher/test/tc_key-stream.rb +19 -0
- data/examples/solitaire-cipher/test/tc_keying-algorithms.rb +31 -0
- data/examples/solitaire-cipher/test/tc_solitaire-cipher.rb +66 -0
- data/examples/solitaire-cipher/test/tc_unkeyed-algorithm.rb +17 -0
- data/examples/solitaire-cipher/test/tests.rb +2 -0
- data/lib/copland.rb +56 -0
- data/lib/copland/class-factory.rb +95 -0
- data/lib/copland/configuration-point.rb +38 -0
- data/lib/copland/configuration-point/common.rb +203 -0
- data/lib/copland/configuration-point/errors.rb +44 -0
- data/lib/copland/configuration-point/list.rb +59 -0
- data/lib/copland/configuration-point/map.rb +59 -0
- data/lib/copland/configuration/errors.rb +43 -0
- data/lib/copland/configuration/loader.rb +113 -0
- data/lib/copland/configuration/yaml/configuration-point.rb +87 -0
- data/lib/copland/configuration/yaml/implementor.rb +134 -0
- data/lib/copland/configuration/yaml/interceptor.rb +63 -0
- data/lib/copland/configuration/yaml/listener.rb +56 -0
- data/lib/copland/configuration/yaml/loader.rb +122 -0
- data/lib/copland/configuration/yaml/package.rb +125 -0
- data/lib/copland/configuration/yaml/parser.rb +71 -0
- data/lib/copland/configuration/yaml/schema.rb +165 -0
- data/lib/copland/configuration/yaml/service-point.rb +116 -0
- data/lib/copland/configuration/yaml/utils.rb +82 -0
- data/lib/copland/default-schema-processor.rb +144 -0
- data/lib/copland/errors.rb +82 -0
- data/lib/copland/event-producer.rb +95 -0
- data/lib/copland/impl/builder-factory.rb +112 -0
- data/lib/copland/impl/copland-config.yml +1 -0
- data/lib/copland/impl/include-exclude.rb +140 -0
- data/lib/copland/impl/logging-interceptor.rb +106 -0
- data/lib/copland/impl/package.yml +217 -0
- data/lib/copland/impl/startup.rb +116 -0
- data/lib/copland/impl/symbol-source-manager.rb +131 -0
- data/lib/copland/impl/symbol-source.rb +63 -0
- data/lib/copland/instantiator.rb +38 -0
- data/lib/copland/instantiator/abstract.rb +91 -0
- data/lib/copland/instantiator/complex.rb +96 -0
- data/lib/copland/instantiator/identity.rb +58 -0
- data/lib/copland/instantiator/simple.rb +68 -0
- data/lib/copland/interceptor-chain.rb +166 -0
- data/lib/copland/interceptor.rb +139 -0
- data/lib/copland/log-factory.rb +206 -0
- data/lib/copland/models.rb +39 -0
- data/lib/copland/models/abstract.rb +78 -0
- data/lib/copland/models/prototype-deferred.rb +58 -0
- data/lib/copland/models/prototype.rb +58 -0
- data/lib/copland/models/proxy.rb +100 -0
- data/lib/copland/models/singleton-deferred.rb +59 -0
- data/lib/copland/models/singleton.rb +77 -0
- data/lib/copland/models/threaded.rb +65 -0
- data/lib/copland/ordering.rb +123 -0
- data/lib/copland/package.rb +246 -0
- data/lib/copland/registry.rb +368 -0
- data/lib/copland/schema.rb +206 -0
- data/lib/copland/service-point.rb +282 -0
- data/lib/copland/utils.rb +221 -0
- data/lib/copland/version.rb +47 -0
- data/test/conf-test/list-bad-key.yml +30 -0
- data/test/conf-test/list-bad-missing.yml +28 -0
- data/test/conf-test/list-bad-type.yml +28 -0
- data/test/conf-test/list-good.yml +29 -0
- data/test/conf-test/map-bad-key.yml +25 -0
- data/test/conf-test/map-bad-missing.yml +24 -0
- data/test/conf-test/map-bad-type.yml +23 -0
- data/test/conf-test/map-good.yml +25 -0
- data/test/configuration-point/package.yml +52 -0
- data/test/configuration/yaml/config/copland-config.yml +2 -0
- data/test/configuration/yaml/config/module.yml +2 -0
- data/test/configuration/yaml/config/subdir/copland-config.yml +2 -0
- data/test/configuration/yaml/config/subdir/package.yml +4 -0
- data/test/configuration/yaml/defaults/package.yml +5 -0
- data/test/configuration/yaml/defaults/subdir/package.yml +4 -0
- data/test/configuration/yaml/tc_config-loader.rb +86 -0
- data/test/configuration/yaml/tc_configuration-point-processor.rb +134 -0
- data/test/configuration/yaml/tc_implementor-processor.rb +104 -0
- data/test/configuration/yaml/tc_interceptor-processor.rb +85 -0
- data/test/configuration/yaml/tc_listener-processor.rb +69 -0
- data/test/configuration/yaml/tc_loader.rb +74 -0
- data/test/configuration/yaml/tc_package-processor.rb +120 -0
- data/test/configuration/yaml/tc_parser.rb +94 -0
- data/test/configuration/yaml/tc_schema-parser.rb +160 -0
- data/test/configuration/yaml/tc_service-point-processor.rb +104 -0
- data/test/configuration/yaml/tc_type-validator.rb +90 -0
- data/test/custom-logger.yml +3 -0
- data/test/impl/logging/package.yml +44 -0
- data/test/impl/logging/services.rb +84 -0
- data/test/impl/startup/package.yml +46 -0
- data/test/impl/startup/services.rb +47 -0
- data/test/impl/symbols/package.yml +24 -0
- data/test/impl/symbols/services.rb +38 -0
- data/test/impl/tc_builder-factory.rb +173 -0
- data/test/impl/tc_logging-interceptor.rb +148 -0
- data/test/impl/tc_startup.rb +59 -0
- data/test/impl/tc_symbol-sources.rb +61 -0
- data/test/logger.yml +6 -0
- data/test/mock.rb +201 -0
- data/test/schema/bad-package.yml +65 -0
- data/test/schema/package.yml +102 -0
- data/test/schema/services.rb +5 -0
- data/test/services/package.yml +79 -0
- data/test/services/simple.rb +87 -0
- data/test/tc_class-factory.rb +93 -0
- data/test/tc_complex-instantiator.rb +107 -0
- data/test/tc_configuration-point-contrib.rb +74 -0
- data/test/tc_configuration-point-schema.rb +122 -0
- data/test/tc_configuration-point.rb +91 -0
- data/test/tc_default-schema-processor.rb +297 -0
- data/test/tc_identity-instantiator.rb +61 -0
- data/test/tc_interceptors.rb +84 -0
- data/test/tc_logger.rb +131 -0
- data/test/tc_models.rb +176 -0
- data/test/tc_package.rb +165 -0
- data/test/tc_proxy.rb +65 -0
- data/test/tc_registry.rb +141 -0
- data/test/tc_schema.rb +78 -0
- data/test/tc_service-point.rb +178 -0
- data/test/tc_service.rb +70 -0
- data/test/tc_simple-instantiator.rb +61 -0
- data/test/tests.rb +93 -0
- data/tutorial/01/main.rb +7 -0
- data/tutorial/01/package.yml +8 -0
- data/tutorial/01/tutorial.rb +7 -0
- data/tutorial/02/main.rb +10 -0
- data/tutorial/02/package.yml +27 -0
- data/tutorial/02/tutorial.rb +46 -0
- data/tutorial/03/main.rb +24 -0
- data/tutorial/03/package.yml +29 -0
- data/tutorial/03/tutorial.rb +48 -0
- data/tutorial/04/main.rb +24 -0
- data/tutorial/04/package.yml +35 -0
- data/tutorial/04/tutorial.rb +48 -0
- data/tutorial/05/functions/package.yml +16 -0
- data/tutorial/05/functions/services.rb +15 -0
- data/tutorial/05/main.rb +10 -0
- data/tutorial/05/package.yml +35 -0
- data/tutorial/05/tutorial.rb +53 -0
- metadata +260 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Package Reference for Copland</title>
|
4
|
+
<link rel="stylesheet" type="text/css" href="packrat.css" />
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<h1><a name="top"></a>Package Reference for Copland</h1>
|
8
|
+
|
9
|
+
|
10
|
+
<h2><a href="copland.html">copland</a></h2>
|
11
|
+
|
12
|
+
|
13
|
+
<div class="description">
|
14
|
+
The copland package is the standard package defined by the Copland distribution. It includes the core services and interceptors, such as the BuilderFactory and the LoggingInterceptor.
|
15
|
+
</div>
|
16
|
+
|
17
|
+
|
18
|
+
<h2><a href="copland.lib.html">copland.lib</a></h2>
|
19
|
+
|
20
|
+
|
21
|
+
<div class="description">
|
22
|
+
This package contains additional services, providing functionality beyond that given by the core set of services in Copland itself. These additional services include a multicast service factory, a synchronizing interceptor, and more.
|
23
|
+
</div>
|
24
|
+
|
25
|
+
|
26
|
+
<h2><a href="copland.remote.html">copland.remote</a></h2>
|
27
|
+
|
28
|
+
|
29
|
+
<div class="description">
|
30
|
+
The copland.remote package is where standard Copland services dealing with remote access to services or servers are kept.
|
31
|
+
</div>
|
32
|
+
|
33
|
+
|
34
|
+
<h2><a href="copland.webrick.html">copland.webrick</a></h2>
|
35
|
+
|
36
|
+
|
37
|
+
<div class="description">
|
38
|
+
Various Copland services related to dealing with WEBrick servers and servlets.
|
39
|
+
</div>
|
40
|
+
|
41
|
+
|
42
|
+
<div class="generated-by">
|
43
|
+
Generated by
|
44
|
+
<a href="http://copland.rubyforge.org">Copland</a>'s
|
45
|
+
Packrat documentation extractor
|
46
|
+
on Sun Sep 26 21:37:13 MDT 2004
|
47
|
+
</div>
|
48
|
+
</body>
|
49
|
+
</html>
|
@@ -0,0 +1,125 @@
|
|
1
|
+
body {
|
2
|
+
margin: 0px;
|
3
|
+
background: #FFF;
|
4
|
+
color: #000;
|
5
|
+
font-family: verdana, arial, sans-serif;
|
6
|
+
}
|
7
|
+
|
8
|
+
a[href] {
|
9
|
+
color: #00F;
|
10
|
+
text-decoration: none;
|
11
|
+
}
|
12
|
+
|
13
|
+
a[href]:hover {
|
14
|
+
text-decoration: underline;
|
15
|
+
}
|
16
|
+
|
17
|
+
h1 {
|
18
|
+
background: #007;
|
19
|
+
color: #FFF;
|
20
|
+
font-weight: bold;
|
21
|
+
border-bottom: 1px solid #000;
|
22
|
+
padding: 0.5em;
|
23
|
+
font-size: xx-large;
|
24
|
+
}
|
25
|
+
|
26
|
+
h2 {
|
27
|
+
background: #007;
|
28
|
+
color: #FFF;
|
29
|
+
font-weight: bold;
|
30
|
+
border-top: 1px solid #000;
|
31
|
+
border-bottom: 1px solid #000;
|
32
|
+
padding: 0.25em;
|
33
|
+
padding-left: 1em;
|
34
|
+
font-size: x-large;
|
35
|
+
}
|
36
|
+
|
37
|
+
h3 {
|
38
|
+
background: #FFA;
|
39
|
+
color: #000;
|
40
|
+
font-weight: bold;
|
41
|
+
border-top: 1px solid #000;
|
42
|
+
border-bottom: 1px solid #000;
|
43
|
+
padding: 0.25em;
|
44
|
+
padding-left: 1em;
|
45
|
+
font-size: large;
|
46
|
+
}
|
47
|
+
|
48
|
+
h4 {
|
49
|
+
background: #FFD;
|
50
|
+
color: #000;
|
51
|
+
font-weight: bold;
|
52
|
+
border: 1px solid #000;
|
53
|
+
padding: 0.25em;
|
54
|
+
padding-left: 1em;
|
55
|
+
font-size: normal;
|
56
|
+
}
|
57
|
+
|
58
|
+
h1 a[href], h2 a[href], h3 a[href] {
|
59
|
+
color: #FF0;
|
60
|
+
}
|
61
|
+
|
62
|
+
.item-body {
|
63
|
+
margin-left: 1em;
|
64
|
+
margin-right: 1em;
|
65
|
+
}
|
66
|
+
|
67
|
+
.description {
|
68
|
+
margin-left: 1em;
|
69
|
+
margin-right: 1em;
|
70
|
+
border: 1px dotted #777;
|
71
|
+
background: #FFE;
|
72
|
+
padding: 1em;
|
73
|
+
}
|
74
|
+
|
75
|
+
.definition-item {
|
76
|
+
margin-left: 2em;
|
77
|
+
}
|
78
|
+
|
79
|
+
.definition-item li {
|
80
|
+
margin-top: 0.25em;
|
81
|
+
}
|
82
|
+
|
83
|
+
.schema-item-title {
|
84
|
+
color: #000;
|
85
|
+
font-style: italic;
|
86
|
+
padding-left: 1em;
|
87
|
+
font-size: normal;
|
88
|
+
}
|
89
|
+
|
90
|
+
.schema-item {
|
91
|
+
padding: 0.5em;
|
92
|
+
margin-left: 1em;
|
93
|
+
border-left: 1px dashed #777;
|
94
|
+
}
|
95
|
+
|
96
|
+
.subschema-name {
|
97
|
+
font-weight: bold;
|
98
|
+
}
|
99
|
+
|
100
|
+
.subschema {
|
101
|
+
margin-left: 1em;
|
102
|
+
margin-top: 0.25em;
|
103
|
+
}
|
104
|
+
|
105
|
+
.subschema .description {
|
106
|
+
margin-right: 1em;
|
107
|
+
margin-left: 0em;
|
108
|
+
border: none;
|
109
|
+
background: #FFF;
|
110
|
+
padding: 0.5em;
|
111
|
+
}
|
112
|
+
|
113
|
+
.nav {
|
114
|
+
text-align: right;
|
115
|
+
font-style: italic;
|
116
|
+
margin: 2em;
|
117
|
+
}
|
118
|
+
|
119
|
+
.generated-by {
|
120
|
+
font-size: small;
|
121
|
+
font-style: italic;
|
122
|
+
margin-top: 2em;
|
123
|
+
padding: 1em;
|
124
|
+
border-top: 1px solid #000;
|
125
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# * Redistributions of source code must retain the above copyright notice,
|
10
|
+
# this list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# * Redistributions in binary form must reproduce the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer in the
|
14
|
+
# documentation and/or other materials provided with the distribution.
|
15
|
+
#
|
16
|
+
# * The names of its contributors may not be used to endorse or promote
|
17
|
+
# products derived from this software without specific prior written
|
18
|
+
# permission.
|
19
|
+
#
|
20
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
24
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
25
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
26
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
27
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
28
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
29
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
30
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
# =============================================================================
|
32
|
+
#++
|
33
|
+
|
34
|
+
$:.unshift "../../lib"
|
35
|
+
|
36
|
+
require 'copland'
|
37
|
+
|
38
|
+
registry = Copland::Registry.build :log_device => STDOUT
|
39
|
+
|
40
|
+
calc = registry.service( "calc.Calculator" )
|
41
|
+
|
42
|
+
p calc.add( 5, 8 )
|
43
|
+
p calc.subtract( 5, 8 )
|
44
|
+
p calc.multiply( 5, 8 )
|
45
|
+
p calc.divide( 5, 8 )
|
46
|
+
|
47
|
+
registry.shutdown
|
@@ -0,0 +1,35 @@
|
|
1
|
+
---
|
2
|
+
id: calc
|
3
|
+
|
4
|
+
configuration-points:
|
5
|
+
|
6
|
+
Operations:
|
7
|
+
type: map
|
8
|
+
|
9
|
+
contributions:
|
10
|
+
|
11
|
+
Operations:
|
12
|
+
:add: !!service Adder
|
13
|
+
:subtract: !!service Subtractor
|
14
|
+
:multiply: !!service Multiplier
|
15
|
+
:divide: !!service Divider
|
16
|
+
|
17
|
+
service-points:
|
18
|
+
|
19
|
+
Adder:
|
20
|
+
implementor: services/Adder
|
21
|
+
|
22
|
+
Subtractor:
|
23
|
+
implementor: services/Subtractor
|
24
|
+
|
25
|
+
Multiplier:
|
26
|
+
implementor: services/Multiplier
|
27
|
+
|
28
|
+
Divider:
|
29
|
+
implementor: services/Divider
|
30
|
+
|
31
|
+
Calculator:
|
32
|
+
implementor:
|
33
|
+
class: services/Calculator
|
34
|
+
parameters:
|
35
|
+
- !!configuration Operations
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# * Redistributions of source code must retain the above copyright notice,
|
10
|
+
# this list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# * Redistributions in binary form must reproduce the above copyright
|
13
|
+
# notice, this list of conditions and the following disclaimer in the
|
14
|
+
# documentation and/or other materials provided with the distribution.
|
15
|
+
#
|
16
|
+
# * The names of its contributors may not be used to endorse or promote
|
17
|
+
# products derived from this software without specific prior written
|
18
|
+
# permission.
|
19
|
+
#
|
20
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
24
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
25
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
26
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
27
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
28
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
29
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
30
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
# =============================================================================
|
32
|
+
#++
|
33
|
+
|
34
|
+
class Adder
|
35
|
+
def compute( a, b )
|
36
|
+
a.to_f + b.to_f
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Subtractor
|
41
|
+
def compute( a, b )
|
42
|
+
a.to_f - b.to_f
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Multiplier
|
47
|
+
def compute( a, b )
|
48
|
+
a.to_f * b.to_f
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Divider
|
53
|
+
def compute( a, b )
|
54
|
+
a.to_f / b.to_f
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class Calculator
|
59
|
+
def initialize( operations )
|
60
|
+
@operations = operations
|
61
|
+
end
|
62
|
+
|
63
|
+
def method_missing( op, *args )
|
64
|
+
if @operations.has_key?( op )
|
65
|
+
@operations[ op ].compute( *args )
|
66
|
+
else
|
67
|
+
super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def respond_to?( op )
|
72
|
+
super || @operations.has_key?( op )
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
This example was originally submitted as a solution for the first Ruby Quiz
|
2
|
+
(http://www.grayproductions.net/ruby_quiz/). Although the scope of the
|
3
|
+
problem is really too small to adequately demonstrate IoC, it does show
|
4
|
+
a few features and is a good "bite-sized" example.
|
5
|
+
|
6
|
+
For a complete description of the problem this example solves, see:
|
7
|
+
|
8
|
+
http://www.grayproductions.net/ruby_quiz/quiz1.html
|
9
|
+
|
10
|
+
- Jamis Buck
|
11
|
+
26 Sep 2004
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
def can_require( file )
|
6
|
+
begin
|
7
|
+
require file
|
8
|
+
return true
|
9
|
+
rescue LoadError
|
10
|
+
return false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Default task"
|
15
|
+
task :default => [ :demo ]
|
16
|
+
|
17
|
+
desc "Demonstration of the application"
|
18
|
+
task :demo do
|
19
|
+
puts "================================================================="
|
20
|
+
puts "This is a demonstration of Jamis Buck's solution to Ruby Quiz #1,"
|
21
|
+
puts "\"The Solitaire Cipher\". To run it yourself, invoke the script"
|
22
|
+
puts "\"bin/main.rb\", and pass the message(s) you want to encrypt or"
|
23
|
+
puts "decrypt as parameters."
|
24
|
+
puts "================================================================="
|
25
|
+
puts
|
26
|
+
sh 'ruby bin/main.rb "The rain in Spain stays mainly in the plain" ' +
|
27
|
+
'"CLEPK HHNIY CFPWH FDFEH"'
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Build documentation"
|
31
|
+
task :doc => [ :rdoc, :packrat ]
|
32
|
+
|
33
|
+
task :rdoc => Dir["lib/*.rb"]
|
34
|
+
|
35
|
+
desc "Clean generated files"
|
36
|
+
task :clean do
|
37
|
+
rm_rf "doc/api"
|
38
|
+
rm_rf "doc/packages"
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "Generate the package reference documentation"
|
42
|
+
task :packrat => [ "doc/packages/index.html" ]
|
43
|
+
|
44
|
+
file "doc/packages/index.html" do
|
45
|
+
sh "packrat -o doc/packages -v -T 'Ruby Quiz #1: The Solitaire Cipher' lib"
|
46
|
+
end
|
47
|
+
|
48
|
+
Rake::TestTask.new do |t|
|
49
|
+
t.test_files = [ "test/tests.rb" ]
|
50
|
+
t.verbose = true
|
51
|
+
end
|
52
|
+
|
53
|
+
Rake::RDocTask.new do |rdoc|
|
54
|
+
rdoc.rdoc_dir = 'doc/api'
|
55
|
+
rdoc.title = "Ruby Quiz #1: The Solitaire Cipher"
|
56
|
+
rdoc.rdoc_files.include('lib/*.rb')
|
57
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.join( File.dirname( __FILE__ ), "..", "..", "..", "lib" )
|
4
|
+
require 'copland'
|
5
|
+
|
6
|
+
libdir = File.join( File.dirname( __FILE__ ), "..", "lib" )
|
7
|
+
$: << libdir
|
8
|
+
|
9
|
+
registry = Copland::Registry.build libdir, :log_device => STDOUT
|
10
|
+
|
11
|
+
cli = registry.service( "solitaire.cipher.CLI" )
|
12
|
+
cli.run
|
13
|
+
|
14
|
+
registry.shutdown
|
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
class Deck
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@deck = (1..52).to_a + [ "A", "B" ]
|
7
|
+
@length = @deck.length
|
8
|
+
end
|
9
|
+
|
10
|
+
def cipher_shuffle!
|
11
|
+
# move joker A down one card, circularly
|
12
|
+
reposition_card( "A", 1 )
|
13
|
+
|
14
|
+
# move joker B down two cards, circularly
|
15
|
+
reposition_card( "B", 2 )
|
16
|
+
|
17
|
+
joker_A = @deck.index( "A" )
|
18
|
+
joker_B = @deck.index( "B" )
|
19
|
+
|
20
|
+
# move all cards above the top-most joker, below the bottom-most joker, and
|
21
|
+
# all cards below the bottom-most joker, above the top-most joker.
|
22
|
+
top = ( joker_A < joker_B ? joker_A : joker_B )
|
23
|
+
bottom = ( joker_A > joker_B ? joker_A : joker_B )
|
24
|
+
@deck = @deck[bottom+1..-1] + @deck[top..bottom] + @deck[0,top]
|
25
|
+
|
26
|
+
# take value of the bottom-most card, and cut that many cards off the
|
27
|
+
# top, inserting them just before the bottom-most card.
|
28
|
+
cut = @deck.last
|
29
|
+
@deck = @deck[cut..-2] + @deck[0,cut] + [ @deck.last ]
|
30
|
+
end
|
31
|
+
|
32
|
+
def cipher_letter
|
33
|
+
count = @deck.first
|
34
|
+
count = 53 if count.is_a?( String )
|
35
|
+
result = @deck[ count ]
|
36
|
+
return nil unless result.is_a? Fixnum
|
37
|
+
result -= 26 while result > 26
|
38
|
+
return (result+64).chr
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_a
|
42
|
+
@deck.dup
|
43
|
+
end
|
44
|
+
|
45
|
+
def cards=( deck )
|
46
|
+
@deck = deck
|
47
|
+
@length = @deck.length
|
48
|
+
raise "the deck must contain an 'A' joker" unless @deck.include?("A")
|
49
|
+
raise "the deck must contain a 'B' joker" unless @deck.include?("B")
|
50
|
+
end
|
51
|
+
|
52
|
+
def reposition_card( card, delta )
|
53
|
+
pos = @deck.index card
|
54
|
+
@deck.delete_at pos
|
55
|
+
new_pos = pos + delta
|
56
|
+
new_pos = 1 + new_pos % @length if new_pos >= @length
|
57
|
+
@deck.insert new_pos, card
|
58
|
+
new_pos
|
59
|
+
end
|
60
|
+
private :reposition_card
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
class KeyingAlgorithms
|
65
|
+
|
66
|
+
attr_writer :algorithms
|
67
|
+
attr_writer :registry
|
68
|
+
|
69
|
+
def get( name )
|
70
|
+
svc_name = @algorithms[ name ]
|
71
|
+
raise "No such algorithm #{name.inspect}" if svc_name.nil?
|
72
|
+
|
73
|
+
return @registry.service( svc_name )
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
class UnkeyedAlgorithm
|
79
|
+
|
80
|
+
def new_deck
|
81
|
+
Deck.new
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
class KeyStream
|
87
|
+
|
88
|
+
attr_writer :deck
|
89
|
+
|
90
|
+
def next
|
91
|
+
loop do
|
92
|
+
@deck.cipher_shuffle!
|
93
|
+
letter = @deck.cipher_letter
|
94
|
+
return letter if letter
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
class SolitaireCipher
|
101
|
+
|
102
|
+
attr_writer :algorithms
|
103
|
+
attr_writer :stream
|
104
|
+
|
105
|
+
def initialize( default_algorithm )
|
106
|
+
@algorithm = default_algorithm
|
107
|
+
end
|
108
|
+
|
109
|
+
def use_algorithm( keying_algorithm )
|
110
|
+
@algorithm = @algorithms.get( keying_algorithm )
|
111
|
+
end
|
112
|
+
|
113
|
+
def encrypt( message )
|
114
|
+
reset
|
115
|
+
|
116
|
+
chars = message.split(//).map { |c| c.upcase }. reject { |c| c !~ /[A-Z]/ }
|
117
|
+
chars.concat ["X"] * ( 5 - chars.length % 5 ) if chars.length % 5 > 0
|
118
|
+
chars.map! { |c| c[0] - 64 }
|
119
|
+
key = generate_key( chars.length )
|
120
|
+
code = chars.zip( key ).map { |c,k| ( c + k > 26 ? c + k - 26 : c + k ) }.map { |c| (c+64).chr }
|
121
|
+
|
122
|
+
msg = ""
|
123
|
+
(code.length/5).times do
|
124
|
+
msg << " " if msg.length > 0
|
125
|
+
5.times { msg << code.shift }
|
126
|
+
end
|
127
|
+
|
128
|
+
return msg
|
129
|
+
end
|
130
|
+
|
131
|
+
def decrypt( message )
|
132
|
+
raise "bad decrypt message: #{message.inspect}" if message =~ /[^A-Z ]/
|
133
|
+
|
134
|
+
reset
|
135
|
+
chars = message.split(//).reject { |c| c == " " }.map { |c| c[0] - 64 }
|
136
|
+
key = generate_key( chars.length )
|
137
|
+
chars.zip( key ).map { |c,k| ( k >= c ? c + 26 - k : c - k ) }.map { |c| (c+64).chr }.join
|
138
|
+
end
|
139
|
+
|
140
|
+
def generate_key( length )
|
141
|
+
key = []
|
142
|
+
length.times { key << @stream.next }
|
143
|
+
key.map { |c| c[0] - 64 }
|
144
|
+
end
|
145
|
+
private :generate_key
|
146
|
+
|
147
|
+
def reset
|
148
|
+
@stream.deck = @algorithm.new_deck
|
149
|
+
end
|
150
|
+
private :reset
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
class Options
|
155
|
+
|
156
|
+
attr_reader :strings
|
157
|
+
attr_reader :keying_algorithm
|
158
|
+
|
159
|
+
def initialize( argv = ARGV )
|
160
|
+
@named_options = Hash.new
|
161
|
+
@run_app = true
|
162
|
+
@keying_algorithm = "unkeyed"
|
163
|
+
|
164
|
+
OptionParser.new do |opts|
|
165
|
+
opts.banner = "Usage: #{$0} [options] [strings]"
|
166
|
+
opts.separator ""
|
167
|
+
|
168
|
+
opts.on( "-o", "--option NAME=VALUE",
|
169
|
+
"Specify a named value, for use by a component of the cipher."
|
170
|
+
) do |pair|
|
171
|
+
name, value = pair.split( / *= */, 2 )
|
172
|
+
@named_options[ name ] = value
|
173
|
+
end
|
174
|
+
|
175
|
+
opts.on( "-k", "--key NAME", "Specify the keying algorithm to use" ) do |value|
|
176
|
+
@keying_algorithm = value
|
177
|
+
end
|
178
|
+
|
179
|
+
opts.separator ""
|
180
|
+
|
181
|
+
opts.on_tail( "-h", "--help", "This help text" ) do
|
182
|
+
puts opts
|
183
|
+
@run_app = false
|
184
|
+
end
|
185
|
+
|
186
|
+
opts.parse!( argv )
|
187
|
+
end
|
188
|
+
|
189
|
+
@strings = argv
|
190
|
+
end
|
191
|
+
|
192
|
+
def []( value )
|
193
|
+
@named_options[ value ]
|
194
|
+
end
|
195
|
+
|
196
|
+
def run_app?
|
197
|
+
@run_app
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
class BackwardsAlgorithm
|
204
|
+
|
205
|
+
def new_deck
|
206
|
+
deck = Deck.new
|
207
|
+
deck.cards = deck.to_a.reverse
|
208
|
+
deck
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
class ShuffleAlgorithm
|
214
|
+
|
215
|
+
attr_writer :options
|
216
|
+
|
217
|
+
def new_deck
|
218
|
+
deck = Deck.new
|
219
|
+
cards = deck.to_a
|
220
|
+
|
221
|
+
seed = ( @options[ "seed" ] || 0 ).to_i
|
222
|
+
srand seed
|
223
|
+
|
224
|
+
7.times { cards.sort! { rand(3)-1 } }
|
225
|
+
deck.cards = cards
|
226
|
+
|
227
|
+
return deck
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|