proteus 0.9.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/COPYING +674 -0
- data/README +88 -0
- data/Rakefile +33 -0
- data/bin/pro +189 -0
- data/lib/ClassParser.rb +84 -0
- data/lib/ComponentClass.rb +51 -0
- data/lib/ComponentInstance.rb +76 -0
- data/lib/DefinitionHelper.rb +157 -0
- data/lib/DefinitionParser.rb +107 -0
- data/lib/Facade.rb +116 -0
- data/lib/FileHelper.rb +80 -0
- data/lib/InputParser.rb +241 -0
- data/lib/InstanceParser.rb +65 -0
- data/lib/InstanceProxy.rb +100 -0
- data/lib/PropertyHash.rb +64 -0
- data/lib/TemplateRenderer.rb +128 -0
- data/lib/exceptions.rb +50 -0
- data/test/spec/ClassParser_spec.rb +314 -0
- data/test/spec/ComponentClass_spec.rb +44 -0
- data/test/spec/ComponentInstance_spec.rb +50 -0
- data/test/spec/DefinitionHelper_spec.rb +134 -0
- data/test/spec/DefinitionParser_spec.rb +236 -0
- data/test/spec/Facade_spec.rb +44 -0
- data/test/spec/FileHelper_spec.rb +113 -0
- data/test/spec/InputParser_spec.rb +424 -0
- data/test/spec/InstanceParser_spec.rb +125 -0
- data/test/spec/TemplateRenderer_spec.rb +54 -0
- data/test/spec/lib/NS1/TestComponent10.def +4 -0
- data/test/spec/lib/NS1/TestComponent11.def +4 -0
- data/test/spec/lib/NS1/TestComponent4.def +4 -0
- data/test/spec/lib/NS1/TestComponent5.def +4 -0
- data/test/spec/lib/NS1/TestComponent8.def +4 -0
- data/test/spec/lib/NS1/TestComponent9.def +4 -0
- data/test/spec/lib/NS2/TestComponent6.def +4 -0
- data/test/spec/lib/TestComponent1.def +4 -0
- data/test/spec/lib/TestComponent3.def +4 -0
- data/test/spec/test_lib_dir1/File1.def +0 -0
- data/test/spec/test_lib_dir1/File3.def +0 -0
- data/test/spec/test_lib_dir1/NS1/File4.def +0 -0
- data/test/spec/test_lib_dir1/NS1/NS2/File5.def +0 -0
- data/test/spec/test_lib_dir2/File1.def +0 -0
- data/test/spec/test_lib_dir2/File2.def +0 -0
- metadata +113 -0
data/lib/PropertyHash.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
################################################################################
|
2
|
+
# PropertyHash.rb
|
3
|
+
#
|
4
|
+
# Wraps the properties of an instance used in the InstanceProxy, rendering its
|
5
|
+
# values before returning them.
|
6
|
+
# -----------------------------------------------------------------------------
|
7
|
+
# (C) Copyright 2009 William Madden
|
8
|
+
#
|
9
|
+
# This file is part of Proteus.
|
10
|
+
#
|
11
|
+
# Proteus is free software: you can redistribute it and/or modify it under the
|
12
|
+
# terms of the GNU General Public License as published by the Free Software
|
13
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
14
|
+
# version.
|
15
|
+
#
|
16
|
+
# Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
|
17
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
18
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
19
|
+
#
|
20
|
+
# You should have received a copy of the GNU General Public License along with
|
21
|
+
# Proteus. If not, see <http://www.gnu.org/licenses/>.
|
22
|
+
################################################################################
|
23
|
+
|
24
|
+
|
25
|
+
module Proteus
|
26
|
+
|
27
|
+
#
|
28
|
+
# Wraps the properties of an instance used in the InstanceProxy, rendering its
|
29
|
+
# values before returning them.
|
30
|
+
#
|
31
|
+
class PropertyHash < Hash
|
32
|
+
|
33
|
+
#---------------------------------------------------------------------------
|
34
|
+
#
|
35
|
+
# Constructor
|
36
|
+
#
|
37
|
+
#---------------------------------------------------------------------------
|
38
|
+
|
39
|
+
def initialize( properties, renderer )
|
40
|
+
super( properties )
|
41
|
+
@renderer = renderer
|
42
|
+
end
|
43
|
+
|
44
|
+
#---------------------------------------------------------------------------
|
45
|
+
#
|
46
|
+
# Methods
|
47
|
+
#
|
48
|
+
#---------------------------------------------------------------------------
|
49
|
+
|
50
|
+
public
|
51
|
+
|
52
|
+
#
|
53
|
+
# Overrides the default [] operator to render values before they're
|
54
|
+
# returned.
|
55
|
+
#
|
56
|
+
def []( val )
|
57
|
+
result = super[val]
|
58
|
+
return @renderer.render( result )
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,128 @@
|
|
1
|
+
################################################################################
|
2
|
+
# TemplateRenderer.rb
|
3
|
+
#
|
4
|
+
# Renders the document tree using component templates and ERB.
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# (C) Copyright 2009 William Madden
|
7
|
+
#
|
8
|
+
# This file is part of Proteus.
|
9
|
+
#
|
10
|
+
# Proteus is free software: you can redistribute it and/or modify it under the
|
11
|
+
# terms of the GNU General Public License as published by the Free Software
|
12
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
13
|
+
# version.
|
14
|
+
#
|
15
|
+
# Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
17
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License along with
|
20
|
+
# Proteus. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
################################################################################
|
22
|
+
|
23
|
+
require 'erb'
|
24
|
+
|
25
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'ComponentInstance.rb') )
|
26
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'InstanceProxy.rb') )
|
27
|
+
|
28
|
+
|
29
|
+
module Proteus
|
30
|
+
|
31
|
+
#
|
32
|
+
# Renders a document tree.
|
33
|
+
#
|
34
|
+
class TemplateRenderer
|
35
|
+
|
36
|
+
TEMPLATE_PROPERTY = "template"
|
37
|
+
|
38
|
+
#---------------------------------------------------------------------------
|
39
|
+
#
|
40
|
+
# Methods
|
41
|
+
#
|
42
|
+
#---------------------------------------------------------------------------
|
43
|
+
|
44
|
+
public
|
45
|
+
|
46
|
+
#
|
47
|
+
# Renders a document tree.
|
48
|
+
#
|
49
|
+
def render( tree )
|
50
|
+
|
51
|
+
case
|
52
|
+
when tree.is_a?( ComponentInstance ):
|
53
|
+
return render_instance( tree )
|
54
|
+
|
55
|
+
when tree.is_a?( Array ):
|
56
|
+
return render_array( tree )
|
57
|
+
|
58
|
+
when tree.is_a?( Hash ):
|
59
|
+
return render_hash( tree )
|
60
|
+
|
61
|
+
when tree.nil?:
|
62
|
+
return ''
|
63
|
+
|
64
|
+
else
|
65
|
+
return render_scalar( tree )
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
#
|
73
|
+
# Renders a hash.
|
74
|
+
#
|
75
|
+
def render_hash( hash )
|
76
|
+
|
77
|
+
for pair in hash
|
78
|
+
hash[ pair[0] ] = render( pair[1] )
|
79
|
+
end
|
80
|
+
|
81
|
+
return hash.to_s
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Renders an array.
|
87
|
+
#
|
88
|
+
def render_array( array )
|
89
|
+
|
90
|
+
result = ''
|
91
|
+
|
92
|
+
array.each do |elem|
|
93
|
+
result += render( elem )
|
94
|
+
end
|
95
|
+
|
96
|
+
return result
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Renders a scalar.
|
102
|
+
#
|
103
|
+
def render_scalar( scalar )
|
104
|
+
return scalar.to_s
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Renders an instance.
|
109
|
+
#
|
110
|
+
def render_instance( instance )
|
111
|
+
|
112
|
+
result = ''
|
113
|
+
template = instance.final_properties[ TEMPLATE_PROPERTY ]
|
114
|
+
|
115
|
+
if template != nil
|
116
|
+
proxy = InstanceProxy.new( self, instance )
|
117
|
+
|
118
|
+
e = ERB.new( template )
|
119
|
+
result = e.result( proxy.instance_env() )
|
120
|
+
end
|
121
|
+
|
122
|
+
return result
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
data/lib/exceptions.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Exceptions.rb
|
3
|
+
#
|
4
|
+
# Provides exception definitions.
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# (C) Copyright 2009 William Madden
|
7
|
+
#
|
8
|
+
# This file is part of Proteus.
|
9
|
+
#
|
10
|
+
# Proteus is free software: you can redistribute it and/or modify it under the
|
11
|
+
# terms of the GNU General Public License as published by the Free Software
|
12
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
13
|
+
# version.
|
14
|
+
#
|
15
|
+
# Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
17
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License along with
|
20
|
+
# Proteus. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
################################################################################
|
22
|
+
|
23
|
+
module Proteus
|
24
|
+
|
25
|
+
module Exceptions
|
26
|
+
|
27
|
+
class DefinitionMalformed < Exception
|
28
|
+
end
|
29
|
+
|
30
|
+
class RenderError < Exception
|
31
|
+
end
|
32
|
+
|
33
|
+
class RecursiveDefinition < Exception
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Raised when a component identifier can't be properly parsed.
|
38
|
+
#
|
39
|
+
class InvalidComponentIdentifier < Exception
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Raised when the definition of a component can't be found.
|
44
|
+
#
|
45
|
+
class DefinitionUnavailable < Exception
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,314 @@
|
|
1
|
+
################################################################################
|
2
|
+
# (C) Copyright 2009 William Madden
|
3
|
+
#
|
4
|
+
# This file is part of Proteus.
|
5
|
+
#
|
6
|
+
# Proteus is free software: you can redistribute it and/or modify it under the
|
7
|
+
# terms of the GNU General Public License as published by the Free Software
|
8
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
9
|
+
# version.
|
10
|
+
#
|
11
|
+
# Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
|
12
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
13
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License along with
|
16
|
+
# Proteus. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
################################################################################
|
18
|
+
|
19
|
+
require File.expand_path( 'lib/ClassParser.rb' )
|
20
|
+
|
21
|
+
include Proteus
|
22
|
+
|
23
|
+
|
24
|
+
describe ClassParser do
|
25
|
+
|
26
|
+
#-----------------------------------------------------------------------------
|
27
|
+
#
|
28
|
+
# Input Constants
|
29
|
+
#
|
30
|
+
#-----------------------------------------------------------------------------
|
31
|
+
|
32
|
+
@@NIL = nil
|
33
|
+
|
34
|
+
@@SCALAR_1 = "some scalar"
|
35
|
+
|
36
|
+
@@LIST_1 = [ "a", "b", "c" ]
|
37
|
+
|
38
|
+
@@VALID_NAME = "SomeComponent"
|
39
|
+
|
40
|
+
@@VALID_PARENT = "ParentComponent"
|
41
|
+
|
42
|
+
@@LONG_HASH = {
|
43
|
+
"key1" => "value1",
|
44
|
+
"key2" => "value2"
|
45
|
+
}
|
46
|
+
|
47
|
+
@@HASH_MISSING_NAME = {
|
48
|
+
"" => {}
|
49
|
+
}
|
50
|
+
|
51
|
+
@@HASH_BAD_NAME = {
|
52
|
+
"this name is invalid" => {}
|
53
|
+
}
|
54
|
+
|
55
|
+
@@HASH_MISSING_PARENT = {
|
56
|
+
@@VALID_NAME + " < " => {}
|
57
|
+
}
|
58
|
+
|
59
|
+
@@HASH_BAD_PARENT = {
|
60
|
+
@@VALID_NAME + " < bad parent" => {}
|
61
|
+
}
|
62
|
+
|
63
|
+
@@HASH_OF_NIL = {
|
64
|
+
@@VALID_NAME => @@NIL
|
65
|
+
}
|
66
|
+
|
67
|
+
@@HASH_OF_SCALAR = {
|
68
|
+
@@VALID_NAME => @@SCALAR_1
|
69
|
+
}
|
70
|
+
|
71
|
+
@@HASH_OF_LIST = {
|
72
|
+
@@VALID_NAME => @@LIST_1
|
73
|
+
}
|
74
|
+
|
75
|
+
@@HASH_OF_HASH = {
|
76
|
+
@@VALID_NAME => {}
|
77
|
+
}
|
78
|
+
|
79
|
+
@@PROPERTIES = {
|
80
|
+
"property1" => "value1",
|
81
|
+
"property2" => "value2",
|
82
|
+
"property3" => "value3",
|
83
|
+
}
|
84
|
+
|
85
|
+
@@CHILDREN = [
|
86
|
+
"child1",
|
87
|
+
"child2",
|
88
|
+
"child3"
|
89
|
+
]
|
90
|
+
|
91
|
+
@@PROPERTIES_WITH_CHILDREN = {
|
92
|
+
"property1" => "value1",
|
93
|
+
"property2" => "value2",
|
94
|
+
"property3" => "value3",
|
95
|
+
"children" => @@CHILDREN
|
96
|
+
}
|
97
|
+
|
98
|
+
@@HASH_OF_PROPS = {
|
99
|
+
@@VALID_NAME => @@PROPERTIES
|
100
|
+
}
|
101
|
+
|
102
|
+
@@HASH_WITH_PARENT = {
|
103
|
+
@@VALID_NAME + " < " + @@VALID_PARENT => {}
|
104
|
+
}
|
105
|
+
|
106
|
+
@@HASH_WITH_CHILDREN = {
|
107
|
+
@@VALID_NAME => @@PROPERTIES_WITH_CHILDREN
|
108
|
+
}
|
109
|
+
|
110
|
+
#-----------------------------------------------------------------------------
|
111
|
+
#
|
112
|
+
# Set up, tear down
|
113
|
+
#
|
114
|
+
#-----------------------------------------------------------------------------
|
115
|
+
|
116
|
+
#------------------------------
|
117
|
+
# before(:all)
|
118
|
+
#------------------------------
|
119
|
+
|
120
|
+
before(:all) do
|
121
|
+
@class_parser = ClassParser.new()
|
122
|
+
end
|
123
|
+
|
124
|
+
#------------------------------
|
125
|
+
# after(:all)
|
126
|
+
#------------------------------
|
127
|
+
|
128
|
+
after(:all) do
|
129
|
+
end
|
130
|
+
|
131
|
+
#-----------------------------------------------------------------------------
|
132
|
+
#
|
133
|
+
# Tests
|
134
|
+
#
|
135
|
+
#-----------------------------------------------------------------------------
|
136
|
+
|
137
|
+
# Only accept correctly formed definitions.
|
138
|
+
#
|
139
|
+
# Do not accept:
|
140
|
+
# nil
|
141
|
+
# scalar
|
142
|
+
# list
|
143
|
+
# empty name
|
144
|
+
# malformed name
|
145
|
+
# empty parent name
|
146
|
+
# malformed parent name
|
147
|
+
# hash of scalar
|
148
|
+
# hash of list
|
149
|
+
# hash longer than one element
|
150
|
+
#
|
151
|
+
# Accept:
|
152
|
+
# hash of nothing
|
153
|
+
# hash of hash
|
154
|
+
#
|
155
|
+
|
156
|
+
it "should reject nil" do
|
157
|
+
begin
|
158
|
+
@class_parser.parse_yaml( @@NIL )
|
159
|
+
rescue Exceptions::DefinitionMalformed
|
160
|
+
success = true
|
161
|
+
end
|
162
|
+
|
163
|
+
success.should == true
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
it "should reject scalar" do
|
168
|
+
begin
|
169
|
+
@class_parser.parse_yaml( @@SCALAR_1 )
|
170
|
+
rescue Exceptions::DefinitionMalformed
|
171
|
+
success = true
|
172
|
+
end
|
173
|
+
|
174
|
+
success.should == true
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
it "should reject list" do
|
179
|
+
begin
|
180
|
+
@class_parser.parse_yaml( @@LIST_1 )
|
181
|
+
rescue Exceptions::DefinitionMalformed
|
182
|
+
success = true
|
183
|
+
end
|
184
|
+
|
185
|
+
success.should == true
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
it "should reject hash longer than one element" do
|
190
|
+
begin
|
191
|
+
@class_parser.parse_yaml( @@LONG_HASH )
|
192
|
+
rescue Exceptions::DefinitionMalformed
|
193
|
+
success = true
|
194
|
+
end
|
195
|
+
|
196
|
+
success.should == true
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
it "should reject missing name" do
|
201
|
+
begin
|
202
|
+
@class_parser.parse_yaml( @@HASH_MISSING_NAME )
|
203
|
+
rescue Exceptions::DefinitionMalformed
|
204
|
+
success = true
|
205
|
+
end
|
206
|
+
|
207
|
+
success.should == true
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
it "should reject malformed name" do
|
212
|
+
begin
|
213
|
+
@class_parser.parse_yaml( @@HASH_BAD_NAME )
|
214
|
+
rescue Exceptions::DefinitionMalformed
|
215
|
+
success = true
|
216
|
+
end
|
217
|
+
|
218
|
+
success.should == true
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
it "should reject empty parent name" do
|
223
|
+
begin
|
224
|
+
@class_parser.parse_yaml( @@HASH_MISSING_PARENT )
|
225
|
+
rescue Exceptions::DefinitionMalformed
|
226
|
+
success = true
|
227
|
+
end
|
228
|
+
|
229
|
+
success.should == true
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
it "should reject malformed parent name" do
|
234
|
+
begin
|
235
|
+
@class_parser.parse_yaml( @@HASH_BAD_PARENT )
|
236
|
+
rescue Exceptions::DefinitionMalformed
|
237
|
+
success = true
|
238
|
+
end
|
239
|
+
|
240
|
+
success.should == true
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
it "should reject hash of scalar" do
|
245
|
+
begin
|
246
|
+
@class_parser.parse_yaml( @@HASH_OF_SCALAR )
|
247
|
+
rescue Exceptions::DefinitionMalformed
|
248
|
+
success = true
|
249
|
+
end
|
250
|
+
|
251
|
+
success.should == true
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
it "should reject hash of list" do
|
256
|
+
begin
|
257
|
+
@class_parser.parse_yaml( @@HASH_OF_LIST )
|
258
|
+
rescue Exceptions::DefinitionMalformed
|
259
|
+
success = true
|
260
|
+
end
|
261
|
+
|
262
|
+
success.should == true
|
263
|
+
end
|
264
|
+
|
265
|
+
|
266
|
+
|
267
|
+
it "should accept valid empty hash" do
|
268
|
+
|
269
|
+
result = @class_parser.parse_yaml( @@HASH_OF_NIL )
|
270
|
+
|
271
|
+
end
|
272
|
+
|
273
|
+
|
274
|
+
it "should accept a hash of a hash" do
|
275
|
+
|
276
|
+
result = @class_parser.parse_yaml( @@HASH_OF_HASH )
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
it "should parse names in the form 'Name < Parent'" do
|
282
|
+
|
283
|
+
result = @class_parser.parse_yaml( @@HASH_WITH_PARENT )
|
284
|
+
|
285
|
+
result.name.should == @@VALID_NAME
|
286
|
+
result.parent.should == @@VALID_PARENT
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
|
291
|
+
it "should interpret the inner hash as properties" do
|
292
|
+
|
293
|
+
result = @class_parser.parse_yaml( @@HASH_OF_PROPS )
|
294
|
+
|
295
|
+
result.properties.should == @@PROPERTIES
|
296
|
+
|
297
|
+
end
|
298
|
+
|
299
|
+
it "should interpret the 'children' property as children" do
|
300
|
+
|
301
|
+
result = @class_parser.parse_yaml( @@HASH_WITH_CHILDREN )
|
302
|
+
|
303
|
+
result.children.should == [
|
304
|
+
"child1",
|
305
|
+
"child2",
|
306
|
+
"child3"
|
307
|
+
]
|
308
|
+
result.properties.should == @@PROPERTIES
|
309
|
+
|
310
|
+
end
|
311
|
+
|
312
|
+
|
313
|
+
end
|
314
|
+
|