blockenspiel 0.3.3-java → 0.4.0-java

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.
@@ -0,0 +1,361 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Blockenspiel DSL definition
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2008-2010 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ require 'thread'
38
+
39
+
40
+ module Blockenspiel
41
+
42
+
43
+ # === DSL setup methods
44
+ #
45
+ # These class methods are available after you have included the
46
+ # Blockenspiel::DSL module.
47
+ #
48
+ # By default, a class that has DSL capability will automatically make
49
+ # all public methods available to parameterless blocks, except for the
50
+ # +initialize+ method, any methods whose names begin with an underscore,
51
+ # and any methods whose names end with an equals sign.
52
+ #
53
+ # If you want to change this behavior, use the directives defined here to
54
+ # control exactly which methods are available to parameterless blocks.
55
+
56
+ module DSLSetupMethods
57
+
58
+
59
+ # :stopdoc:
60
+
61
+ # Called when DSLSetupMethods extends a class.
62
+ # This sets up the current class, and adds a hook that causes
63
+ # any subclass of the current class also to be set up.
64
+
65
+ def self.extended(klass_)
66
+ unless klass_.instance_variable_defined?(:@_blockenspiel_module)
67
+ _setup_class(klass_)
68
+ def klass_.inherited(subklass_)
69
+ ::Blockenspiel::DSLSetupMethods._setup_class(subklass_)
70
+ super
71
+ end
72
+ class << klass_
73
+ unless private_method_defined?(:_blockenspiel_default_include)
74
+ alias_method :_blockenspiel_default_include, :include
75
+ alias_method :include, :_blockenspiel_custom_include
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ # :startdoc:
82
+
83
+
84
+ # Set up a class.
85
+ # Creates a DSL module for this class, optionally delegating to the superclass's module.
86
+ # Also initializes the class's methods hash and active flag.
87
+
88
+ def self._setup_class(klass_) # :nodoc:
89
+ superclass_ = klass_.superclass
90
+ superclass_ = nil unless superclass_.respond_to?(:_get_blockenspiel_module)
91
+ mod_ = ::Module.new
92
+ if superclass_
93
+ mod_.module_eval do
94
+ include superclass_._get_blockenspiel_module
95
+ end
96
+ end
97
+ klass_.instance_variable_set(:@_blockenspiel_superclass, superclass_)
98
+ klass_.instance_variable_set(:@_blockenspiel_module, mod_)
99
+ klass_.instance_variable_set(:@_blockenspiel_methods, {})
100
+ klass_.instance_variable_set(:@_blockenspiel_active, nil)
101
+ end
102
+
103
+
104
+ # Automatically make the given method a DSL method according to the current setting.
105
+
106
+ def _blockenspiel_auto_dsl_method(symbol_) # :nodoc:
107
+ if @_blockenspiel_active
108
+ dsl_method(symbol_)
109
+ elsif @_blockenspiel_active.nil?
110
+ if symbol_ != :initialize && symbol_.to_s !~ /^_/ && symbol_.to_s !~ /=$/
111
+ dsl_method(symbol_)
112
+ end
113
+ end
114
+ end
115
+
116
+
117
+ # Hook called when a method is added.
118
+ # This calls _blockenspiel_auto_dsl_method to auto-handle the method,
119
+ # possibly making it a DSL method according to the current setting.
120
+
121
+ def method_added(symbol_) # :nodoc:
122
+ _blockenspiel_auto_dsl_method(symbol_)
123
+ super
124
+ end
125
+
126
+
127
+ # Custom include method. Calls the main include implementation, but also
128
+ # goes through the public methods of the included module and calls
129
+ # _blockenspiel_auto_dsl_method on each to make them DSL methods
130
+ # (possibly) according to the current setting.
131
+
132
+ def _blockenspiel_custom_include(*modules_) # :nodoc:
133
+ _blockenspiel_default_include(*modules_)
134
+ modules_.reverse_each do |mod_|
135
+ mod_.public_instance_methods.each do |method_|
136
+ _blockenspiel_auto_dsl_method(method_)
137
+ end
138
+ end
139
+ end
140
+
141
+
142
+ # Get this class's corresponding DSL module
143
+
144
+ def _get_blockenspiel_module # :nodoc:
145
+ @_blockenspiel_module
146
+ end
147
+
148
+
149
+ # Get information on the given DSL method name.
150
+ # Possible values are the name of the delegate method, false for method disabled,
151
+ # or nil for method never defined.
152
+
153
+ def _get_blockenspiel_delegate(name_) # :nodoc:
154
+ delegate_ = @_blockenspiel_methods[name_]
155
+ if delegate_.nil? && @_blockenspiel_superclass
156
+ @_blockenspiel_superclass._get_blockenspiel_delegate(name_)
157
+ else
158
+ delegate_
159
+ end
160
+ end
161
+
162
+
163
+ # Make a particular method available to parameterless DSL blocks.
164
+ #
165
+ # To explicitly make a method available to parameterless blocks:
166
+ # dsl_method :my_method
167
+ #
168
+ # To explicitly exclude a method from parameterless blocks:
169
+ # dsl_method :my_method, false
170
+ #
171
+ # To explicitly make a method available to parameterless blocks, but
172
+ # point it to a method of a different name on the target class:
173
+ # dsl_method :my_method, :target_class_method
174
+
175
+ def dsl_method(name_, delegate_=nil)
176
+ name_ = name_.to_sym
177
+ if delegate_
178
+ delegate_ = delegate_.to_sym
179
+ elsif delegate_.nil?
180
+ delegate_ = name_
181
+ end
182
+ @_blockenspiel_methods[name_] = delegate_
183
+ unless @_blockenspiel_module.public_method_defined?(name_)
184
+ @_blockenspiel_module.module_eval("def #{name_}(*params_, &block_); val_ = ::Blockenspiel._target_dispatch(self, :#{name_}, params_, block_); ::Blockenspiel::NO_VALUE.equal?(val_) ? super(*params_, &block_) : val_; end\n")
185
+ end
186
+ end
187
+
188
+
189
+ # Control the behavior of methods with respect to parameterless blocks,
190
+ # or make a list of methods available to parameterless blocks in bulk.
191
+ #
192
+ # To enable automatic exporting of methods to parameterless blocks.
193
+ # After executing this command, all public methods defined in the class
194
+ # will be available on parameterless blocks, until
195
+ # <tt>dsl_methods false</tt> is called:
196
+ # dsl_methods true
197
+ #
198
+ # To disable automatic exporting of methods to parameterless blocks.
199
+ # After executing this command, methods defined in this class will be
200
+ # excluded from parameterless blocks, until <tt>dsl_methods true</tt>
201
+ # is called:
202
+ # dsl_methods false
203
+ #
204
+ # To make a list of methods available to parameterless blocks in bulk:
205
+ # dsl_methods :my_method1, :my_method2, ...
206
+ #
207
+ # You can also point dsl methods to a method of a different name on the
208
+ # target class, by using a hash syntax, as follows:
209
+ # dsl_methods :my_method1 => :target_class_method1,
210
+ # :my_method2 => :target_class_method2
211
+ #
212
+ # You can mix non-renamed and renamed method declarations as long as
213
+ # the renamed (hash) methods are at the end. e.g.:
214
+ # dsl_methods :my_method1, :my_method2 => :target_class_method2
215
+
216
+ def dsl_methods(*names_)
217
+ if names_.size == 0 || names_ == [true]
218
+ @_blockenspiel_active = true
219
+ elsif names_ == [false]
220
+ @_blockenspiel_active = false
221
+ else
222
+ if names_.last.kind_of?(::Hash)
223
+ names_.pop.each do |name_, delegate_|
224
+ dsl_method(name_, delegate_)
225
+ end
226
+ end
227
+ names_.each do |name_|
228
+ dsl_method(name_, name_)
229
+ end
230
+ end
231
+ end
232
+
233
+
234
+ # A DSL-friendly attr_accessor.
235
+ #
236
+ # This creates the usual "name" and "name=" methods in the current
237
+ # class that can be used in the usual way. However, its implementation
238
+ # of the "name" method (the getter) also takes an optional parameter
239
+ # that causes it to behave as a setter. This is done because the usual
240
+ # setter syntax cannot be used in a parameterless block, since it is
241
+ # syntactically indistinguishable from a local variable assignment.
242
+ # The "name" method is exposed as a dsl_method.
243
+ #
244
+ # For example:
245
+ #
246
+ # dsl_attr_accessor :foo
247
+ #
248
+ # enables the following:
249
+ #
250
+ # my_block do |param|
251
+ # param.foo = 1 # Usual setter syntax works
252
+ # param.foo 2 # Alternate setter syntax also works
253
+ # puts param.foo # Usual getter syntax still works
254
+ # end
255
+ #
256
+ # my_block do
257
+ # # foo = 1 # Usual setter syntax does NOT work since it
258
+ # # looks like a local variable assignment
259
+ # foo 2 # Alternate setter syntax does work
260
+ # puts foo # Usual getter syntax still works
261
+ # end
262
+
263
+ def dsl_attr_accessor(*names_)
264
+ names_.each do |name_|
265
+ unless name_.kind_of?(::String) || name_.kind_of?(::Symbol)
266
+ raise ::TypeError, "#{name_.inspect} is not a symbol"
267
+ end
268
+ unless name_.to_s =~ /^[_a-zA-Z]\w+$/
269
+ raise ::NameError, "invalid attribute name #{name_.inspect}"
270
+ end
271
+ module_eval("def #{name_}(value_=::Blockenspiel::NO_VALUE); ::Blockenspiel::NO_VALUE.equal?(value_) ? @#{name_} : @#{name_} = value_; end\n")
272
+ alias_method("#{name_}=", name_)
273
+ dsl_method(name_)
274
+ end
275
+ end
276
+
277
+
278
+ # A DSL-friendly attr_writer.
279
+ #
280
+ # This creates the usual "name=" method in the current class that can
281
+ # be used in the usual way. However, it also creates the method "name",
282
+ # which also functions as a setter (but not a getter). This is done
283
+ # because the usual setter syntax cannot be used in a parameterless
284
+ # block, since it is syntactically indistinguishable from a local
285
+ # variable assignment. The "name" method is exposed as a dsl_method.
286
+ #
287
+ # For example:
288
+ #
289
+ # dsl_attr_writer :foo
290
+ #
291
+ # is functionally equivalent to:
292
+ #
293
+ # attr_writer :foo
294
+ # alias_method :foo, :foo=
295
+ # dsl_method :foo
296
+ #
297
+ # which enables the following:
298
+ #
299
+ # my_block do |param|
300
+ # param.foo = 1 # Usual setter syntax works
301
+ # param.foo 2 # Alternate setter syntax also works
302
+ # end
303
+ # my_block do
304
+ # # foo = 1 # Usual setter syntax does NOT work since it
305
+ # # looks like a local variable assignment
306
+ # foo(2) # Alternate setter syntax does work
307
+ # end
308
+
309
+ def dsl_attr_writer(*names_)
310
+ names_.each do |name_|
311
+ attr_writer(name_)
312
+ alias_method(name_, "#{name_}=")
313
+ dsl_method(name_)
314
+ end
315
+ end
316
+
317
+
318
+ end
319
+
320
+
321
+ # === DSL activation module
322
+ #
323
+ # Include this module in a class to mark this class as a DSL class and
324
+ # make it possible for its methods to be called from a block that does not
325
+ # take a parameter.
326
+ #
327
+ # After you include this module, you can use the directives defined in
328
+ # DSLSetupMethods to control what methods are available to DSL blocks
329
+ # that do not take parameters.
330
+
331
+ module DSL
332
+
333
+ def self.included(klass_) # :nodoc:
334
+ unless klass_.kind_of?(::Class)
335
+ raise ::Blockenspiel::BlockenspielError, "You cannot include Blockenspiel::DSL in a module (yet)"
336
+ end
337
+ klass_.extend(::Blockenspiel::DSLSetupMethods)
338
+ end
339
+
340
+ end
341
+
342
+
343
+ # === DSL activation base class
344
+ #
345
+ # Subclasses of this base class are considered DSL classes.
346
+ # Methods of the class can be made available to be called from a block that
347
+ # doesn't take an explicit block parameter.
348
+ # You may use the directives defined in DSLSetupMethods to control how
349
+ # methods of the class are handled in such blocks.
350
+ #
351
+ # Subclassing this base class is functionally equivalent to simply
352
+ # including Blockenspiel::DSL in the class.
353
+
354
+ class Base
355
+
356
+ include ::Blockenspiel::DSL
357
+
358
+ end
359
+
360
+
361
+ end
@@ -0,0 +1,61 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Blockenspiel error classes
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2008-2010 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ module Blockenspiel
38
+
39
+
40
+ # Base exception for all exceptions raised by Blockenspiel
41
+
42
+ class BlockenspielError < ::RuntimeError
43
+ end
44
+
45
+
46
+ # This exception is rasied when attempting to use the <tt>:proxy</tt> or
47
+ # <tt>:mixin</tt> parameterless behavior with a target that does not have
48
+ # the DSL module included. It is an error made by the DSL implementor.
49
+
50
+ class DSLMissingError < ::Blockenspiel::BlockenspielError
51
+ end
52
+
53
+
54
+ # This exception is raised when the block provided does not take the
55
+ # expected number of parameters. It is an error made by the caller.
56
+
57
+ class BlockParameterError < ::Blockenspiel::BlockenspielError
58
+ end
59
+
60
+
61
+ end