source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/rss/maker/base.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 11.8 KB
Line 
1require 'forwardable'
2
3require 'rss/rss'
4
5module RSS
6 module Maker
7
8 module Base
9
10 def self.append_features(klass)
11 super
12
13 klass.module_eval(<<-EOC, __FILE__, __LINE__)
14
15 OTHER_ELEMENTS = []
16 NEED_INITIALIZE_VARIABLES = []
17
18 def self.inherited(subclass)
19 subclass.const_set("OTHER_ELEMENTS", [])
20 subclass.const_set("NEED_INITIALIZE_VARIABLES", [])
21
22 subclass.module_eval(<<-EOEOC, __FILE__, __LINE__)
23 def self.other_elements
24 OTHER_ELEMENTS + super
25 end
26
27 def self.need_initialize_variables
28 NEED_INITIALIZE_VARIABLES + super
29 end
30 EOEOC
31 end
32
33 def self.add_other_element(variable_name)
34 OTHER_ELEMENTS << variable_name
35 end
36
37 def self.other_elements
38 OTHER_ELEMENTS
39 end
40
41 def self.add_need_initialize_variable(variable_name, init_value="nil")
42 NEED_INITIALIZE_VARIABLES << [variable_name, init_value]
43 end
44
45 def self.need_initialize_variables
46 NEED_INITIALIZE_VARIABLES
47 end
48
49 def self.def_array_element(name)
50 include Enumerable
51 extend Forwardable
52
53 def_delegators("@\#{name}", :<<, :[], :[]=, :first, :last)
54 def_delegators("@\#{name}", :push, :pop, :shift, :unshift)
55 def_delegators("@\#{name}", :each, :size)
56
57 add_need_initialize_variable(name, "[]")
58 end
59 EOC
60 end
61
62 def initialize(maker)
63 @maker = maker
64 initialize_variables
65 end
66
67 def have_required_values?
68 true
69 end
70
71 private
72 def initialize_variables
73 self.class.need_initialize_variables.each do |variable_name, init_value|
74 instance_eval("@#{variable_name} = #{init_value}", __FILE__, __LINE__)
75 end
76 end
77
78 def setup_other_elements(rss)
79 self.class.other_elements.each do |element|
80 __send__("setup_#{element}", rss, current_element(rss))
81 end
82 end
83
84 def current_element(rss)
85 rss
86 end
87
88 def setup_values(target)
89 set = false
90 if have_required_values?
91 variables.each do |var|
92 setter = "#{var}="
93 if target.respond_to?(setter)
94 value = __send__(var)
95 if value
96 target.__send__(setter, value)
97 set = true
98 end
99 end
100 end
101 end
102 set
103 end
104
105 def variables
106 self.class.need_initialize_variables.find_all do |name, init|
107 "nil" == init
108 end.collect do |name, init|
109 name
110 end
111 end
112
113 def variable_is_set?
114 variables.find {|var| !__send__(var).nil?}
115 end
116
117 def not_set_required_variables
118 required_variable_names.find_all do |var|
119 __send__(var).nil?
120 end
121 end
122
123 def required_variables_are_set?
124 required_variable_names.each do |var|
125 return false if __send__(var).nil?
126 end
127 true
128 end
129
130 end
131
132 class RSSBase
133 include Base
134
135 class << self
136 def make(&block)
137 new.make(&block)
138 end
139 end
140
141 %w(xml_stylesheets channel image items textinput).each do |element|
142 attr_reader element
143 add_need_initialize_variable(element, "make_#{element}")
144 module_eval(<<-EOC, __FILE__, __LINE__)
145 private
146 def setup_#{element}(rss)
147 @#{element}.to_rss(rss)
148 end
149
150 def make_#{element}
151 self.class::#{Utils.to_class_name(element)}.new(self)
152 end
153EOC
154 end
155
156 attr_reader :rss_version
157 attr_accessor :version, :encoding, :standalone
158
159 def initialize(rss_version)
160 super(self)
161 @rss_version = rss_version
162 @version = "1.0"
163 @encoding = "UTF-8"
164 @standalone = nil
165 end
166
167 def make
168 if block_given?
169 yield(self)
170 to_rss
171 else
172 nil
173 end
174 end
175
176 def to_rss
177 rss = make_rss
178 setup_xml_stylesheets(rss)
179 setup_elements(rss)
180 setup_other_elements(rss)
181 if rss.channel
182 rss
183 else
184 nil
185 end
186 end
187
188 private
189 remove_method :make_xml_stylesheets
190 def make_xml_stylesheets
191 XMLStyleSheets.new(self)
192 end
193
194 end
195
196 class XMLStyleSheets
197 include Base
198
199 def_array_element("xml_stylesheets")
200
201 def to_rss(rss)
202 @xml_stylesheets.each do |xss|
203 xss.to_rss(rss)
204 end
205 end
206
207 def new_xml_stylesheet
208 xss = XMLStyleSheet.new(@maker)
209 @xml_stylesheets << xss
210 if block_given?
211 yield xss
212 else
213 xss
214 end
215 end
216
217 class XMLStyleSheet
218 include Base
219
220 ::RSS::XMLStyleSheet::ATTRIBUTES.each do |attribute|
221 attr_accessor attribute
222 add_need_initialize_variable(attribute)
223 end
224
225 def to_rss(rss)
226 xss = ::RSS::XMLStyleSheet.new
227 guess_type_if_need(xss)
228 set = setup_values(xss)
229 if set
230 rss.xml_stylesheets << xss
231 end
232 end
233
234 def have_required_values?
235 @href and @type
236 end
237
238 private
239 def guess_type_if_need(xss)
240 if @type.nil?
241 xss.href = @href
242 @type = xss.type
243 end
244 end
245 end
246 end
247
248 class ChannelBase
249 include Base
250
251 %w(cloud categories skipDays skipHours).each do |element|
252 attr_reader element
253 add_other_element(element)
254 add_need_initialize_variable(element, "make_#{element}")
255 module_eval(<<-EOC, __FILE__, __LINE__)
256 private
257 def setup_#{element}(rss, current)
258 @#{element}.to_rss(rss, current)
259 end
260
261 def make_#{element}
262 self.class::#{Utils.to_class_name(element)}.new(@maker)
263 end
264EOC
265 end
266
267 %w(about title link description language copyright
268 managingEditor webMaster rating docs date
269 lastBuildDate generator ttl).each do |element|
270 attr_accessor element
271 add_need_initialize_variable(element)
272 end
273
274 alias_method(:pubDate, :date)
275 alias_method(:pubDate=, :date=)
276
277 def current_element(rss)
278 rss.channel
279 end
280
281 class SkipDaysBase
282 include Base
283
284 def_array_element("days")
285
286 def new_day
287 day = self.class::Day.new(@maker)
288 @days << day
289 if block_given?
290 yield day
291 else
292 day
293 end
294 end
295
296 def current_element(rss)
297 rss.channel.skipDays
298 end
299
300 class DayBase
301 include Base
302
303 %w(content).each do |element|
304 attr_accessor element
305 add_need_initialize_variable(element)
306 end
307
308 def current_element(rss)
309 rss.channel.skipDays.last
310 end
311
312 end
313 end
314
315 class SkipHoursBase
316 include Base
317
318 def_array_element("hours")
319
320 def new_hour
321 hour = self.class::Hour.new(@maker)
322 @hours << hour
323 if block_given?
324 yield hour
325 else
326 hour
327 end
328 end
329
330 def current_element(rss)
331 rss.channel.skipHours
332 end
333
334 class HourBase
335 include Base
336
337 %w(content).each do |element|
338 attr_accessor element
339 add_need_initialize_variable(element)
340 end
341
342 def current_element(rss)
343 rss.channel.skipHours.last
344 end
345
346 end
347 end
348
349 class CloudBase
350 include Base
351
352 %w(domain port path registerProcedure protocol).each do |element|
353 attr_accessor element
354 add_need_initialize_variable(element)
355 end
356
357 def current_element(rss)
358 rss.channel.cloud
359 end
360
361 end
362
363 class CategoriesBase
364 include Base
365
366 def_array_element("categories")
367
368 def new_category
369 category = self.class::Category.new(@maker)
370 @categories << category
371 if block_given?
372 yield category
373 else
374 category
375 end
376 end
377
378 class CategoryBase
379 include Base
380
381 %w(domain content).each do |element|
382 attr_accessor element
383 add_need_initialize_variable(element)
384 end
385 end
386 end
387 end
388
389 class ImageBase
390 include Base
391
392 %w(title url width height description).each do |element|
393 attr_accessor element
394 add_need_initialize_variable(element)
395 end
396
397 def link
398 @maker.channel.link
399 end
400
401 def current_element(rss)
402 rss.image
403 end
404 end
405
406 class ItemsBase
407 include Base
408
409 def_array_element("items")
410
411 attr_accessor :do_sort, :max_size
412
413 def initialize(maker)
414 super
415 @do_sort = false
416 @max_size = -1
417 end
418
419 def normalize
420 if @max_size >= 0
421 sort_if_need[0...@max_size]
422 else
423 sort_if_need[0..@max_size]
424 end
425 end
426
427 def current_element(rss)
428 rss.items
429 end
430
431 def new_item
432 item = self.class::Item.new(@maker)
433 @items << item
434 if block_given?
435 yield item
436 else
437 item
438 end
439 end
440
441 private
442 def sort_if_need
443 if @do_sort.respond_to?(:call)
444 @items.sort do |x, y|
445 @do_sort.call(x, y)
446 end
447 elsif @do_sort
448 @items.sort do |x, y|
449 y <=> x
450 end
451 else
452 @items
453 end
454 end
455
456 class ItemBase
457 include Base
458
459 %w(guid enclosure source categories).each do |element|
460 attr_reader element
461 add_other_element(element)
462 add_need_initialize_variable(element, "make_#{element}")
463 module_eval(<<-EOC, __FILE__, __LINE__)
464 private
465 def setup_#{element}(rss, current)
466 @#{element}.to_rss(rss, current)
467 end
468
469 def make_#{element}
470 self.class::#{Utils.to_class_name(element)}.new(@maker)
471 end
472EOC
473 end
474
475 %w(title link description date author comments).each do |element|
476 attr_accessor element
477 add_need_initialize_variable(element)
478 end
479
480 alias_method(:pubDate, :date)
481 alias_method(:pubDate=, :date=)
482
483 def <=>(other)
484 if date and other.date
485 date <=> other.date
486 elsif date
487 1
488 elsif other.date
489 -1
490 else
491 0
492 end
493 end
494
495 def current_element(rss)
496 rss.items.last
497 end
498
499 class GuidBase
500 include Base
501
502 %w(isPermaLink content).each do |element|
503 attr_accessor element
504 add_need_initialize_variable(element)
505 end
506 end
507
508 class EnclosureBase
509 include Base
510
511 %w(url length type).each do |element|
512 attr_accessor element
513 add_need_initialize_variable(element)
514 end
515 end
516
517 class SourceBase
518 include Base
519
520 %w(url content).each do |element|
521 attr_accessor element
522 add_need_initialize_variable(element)
523 end
524 end
525
526 CategoriesBase = ChannelBase::CategoriesBase
527
528 end
529 end
530
531 class TextinputBase
532 include Base
533
534 %w(title description name link).each do |element|
535 attr_accessor element
536 add_need_initialize_variable(element)
537 end
538
539 def current_element(rss)
540 rss.textinput
541 end
542
543 end
544
545 end
546end
Note: See TracBrowser for help on using the repository browser.