2004-10-31 09:14:21 -05:00
|
|
|
require 'forwardable'
|
|
|
|
|
|
|
|
require 'rss/rss'
|
|
|
|
|
|
|
|
module RSS
|
|
|
|
module Maker
|
|
|
|
|
|
|
|
module Base
|
|
|
|
|
|
|
|
def self.append_features(klass)
|
|
|
|
super
|
|
|
|
|
|
|
|
klass.module_eval(<<-EOC, __FILE__, __LINE__)
|
|
|
|
|
|
|
|
OTHER_ELEMENTS = []
|
|
|
|
NEED_INITIALIZE_VARIABLES = []
|
|
|
|
|
|
|
|
def self.inherited(subclass)
|
2004-11-03 01:43:18 -05:00
|
|
|
subclass.const_set("OTHER_ELEMENTS", [])
|
|
|
|
subclass.const_set("NEED_INITIALIZE_VARIABLES", [])
|
|
|
|
|
|
|
|
subclass.module_eval(<<-EOEOC, __FILE__, __LINE__)
|
|
|
|
def self.other_elements
|
|
|
|
const_get("OTHER_ELEMENTS") + super
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.need_initialize_variables
|
|
|
|
const_get("NEED_INITIALIZE_VARIABLES") + super
|
|
|
|
end
|
|
|
|
EOEOC
|
2004-10-31 09:14:21 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.add_other_element(variable_name)
|
|
|
|
const_get("OTHER_ELEMENTS") << variable_name
|
|
|
|
end
|
2004-11-03 01:43:18 -05:00
|
|
|
|
2004-10-31 09:14:21 -05:00
|
|
|
def self.other_elements
|
2004-11-03 01:43:18 -05:00
|
|
|
OTHER_ELEMENTS
|
2004-10-31 09:14:21 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.add_need_initialize_variable(variable_name)
|
|
|
|
const_get("NEED_INITIALIZE_VARIABLES") << variable_name
|
|
|
|
end
|
2004-11-03 01:43:18 -05:00
|
|
|
|
2004-10-31 09:14:21 -05:00
|
|
|
def self.need_initialize_variables
|
2004-11-03 01:43:18 -05:00
|
|
|
NEED_INITIALIZE_VARIABLES
|
2004-10-31 09:14:21 -05:00
|
|
|
end
|
|
|
|
EOC
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize(maker)
|
|
|
|
@maker = maker
|
|
|
|
initialize_variables
|
|
|
|
end
|
|
|
|
|
|
|
|
def have_required_values?
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
def initialize_variables
|
|
|
|
self.class.need_initialize_variables.each do |variable_name|
|
|
|
|
instance_eval("@#{variable_name} = nil", __FILE__, __LINE__)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def setup_other_elements(rss)
|
|
|
|
self.class.other_elements.each do |element|
|
|
|
|
__send__("setup_#{element}", rss, current_element(rss))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def setup_values(target)
|
|
|
|
set = false
|
|
|
|
if have_required_values?
|
|
|
|
variables.each do |var|
|
|
|
|
setter = "#{var}="
|
|
|
|
if target.respond_to?(setter)
|
|
|
|
value = self.__send__(var)
|
|
|
|
if value
|
|
|
|
target.__send__(setter, value)
|
|
|
|
set = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
set
|
|
|
|
end
|
|
|
|
|
|
|
|
def variables
|
|
|
|
self.class.need_initialize_variables
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
2004-11-03 01:43:18 -05:00
|
|
|
|
2004-10-31 09:14:21 -05:00
|
|
|
class RSSBase
|
|
|
|
include Base
|
2004-11-03 01:43:18 -05:00
|
|
|
|
2004-10-31 09:14:21 -05:00
|
|
|
class << self
|
|
|
|
def make(&block)
|
|
|
|
new.make(&block)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
attr_reader :rss_version, :xml_stylesheets
|
|
|
|
attr_reader :channel, :image, :items, :textinput
|
|
|
|
|
|
|
|
attr_accessor :version, :encoding, :standalone
|
|
|
|
|
|
|
|
def initialize(rss_version)
|
|
|
|
super(self)
|
|
|
|
@rss_version = rss_version
|
|
|
|
@version = "1.0"
|
|
|
|
@encoding = "UTF-8"
|
|
|
|
@standalone = nil
|
|
|
|
@xml_stylesheets = make_xml_stylesheets
|
|
|
|
@channel = make_channel
|
|
|
|
@image = make_image
|
|
|
|
@items = make_items
|
|
|
|
@textinput = make_textinput
|
|
|
|
end
|
|
|
|
|
|
|
|
def make(&block)
|
|
|
|
block.call(self) if block
|
|
|
|
to_rss
|
|
|
|
end
|
|
|
|
|
|
|
|
def current_element(rss)
|
|
|
|
rss
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
def make_xml_stylesheets
|
|
|
|
XMLStyleSheets.new(self)
|
|
|
|
end
|
|
|
|
|
|
|
|
def make_channel
|
|
|
|
self.class::Channel.new(self)
|
|
|
|
end
|
|
|
|
|
|
|
|
def make_image
|
|
|
|
self.class::Image.new(self)
|
|
|
|
end
|
|
|
|
|
|
|
|
def make_items
|
|
|
|
self.class::Items.new(self)
|
|
|
|
end
|
|
|
|
|
|
|
|
def make_textinput
|
|
|
|
self.class::Textinput.new(self)
|
|
|
|
end
|
|
|
|
|
|
|
|
def setup_xml_stylesheets(rss)
|
2004-11-01 08:30:08 -05:00
|
|
|
@xml_stylesheets.to_rss(rss)
|
2004-10-31 09:14:21 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
class XMLStyleSheets
|
|
|
|
include Base
|
|
|
|
|
2004-11-03 01:43:18 -05:00
|
|
|
include Enumerable
|
2004-10-31 09:14:21 -05:00
|
|
|
extend Forwardable
|
|
|
|
|
2004-11-01 08:30:08 -05:00
|
|
|
def_delegators(:@xml_stylesheets, :<<, :[], :[]=, :first, :last)
|
|
|
|
def_delegators(:@xml_stylesheets, :push, :pop, :shift, :unshift)
|
2004-11-03 01:43:18 -05:00
|
|
|
def_delegators(:@xml_stylesheets, :each)
|
2004-10-31 09:14:21 -05:00
|
|
|
|
|
|
|
def initialize(maker)
|
|
|
|
super
|
|
|
|
@xml_stylesheets = []
|
|
|
|
end
|
2004-11-01 08:30:08 -05:00
|
|
|
|
|
|
|
def to_rss(rss)
|
|
|
|
@xml_stylesheets.each do |xss|
|
|
|
|
xss.to_rss(rss)
|
2004-10-31 09:14:21 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2004-11-01 08:30:08 -05:00
|
|
|
def new_xml_stylesheet
|
|
|
|
xss = XMLStyleSheet.new(@maker)
|
|
|
|
@xml_stylesheets << xss
|
|
|
|
xss
|
|
|
|
end
|
|
|
|
|
|
|
|
class XMLStyleSheet
|
|
|
|
include Base
|
|
|
|
|
|
|
|
::RSS::XMLStyleSheet::ATTRIBUTES.each do |attribute|
|
|
|
|
attr_accessor attribute
|
|
|
|
add_need_initialize_variable(attribute)
|
|
|
|
end
|
|
|
|
|
|
|
|
def to_rss(rss)
|
|
|
|
xss = ::RSS::XMLStyleSheet.new
|
2004-11-03 01:43:18 -05:00
|
|
|
guess_type_if_need(xss)
|
2004-11-01 08:30:08 -05:00
|
|
|
set = setup_values(xss)
|
|
|
|
if set
|
|
|
|
rss.xml_stylesheets << xss
|
|
|
|
end
|
|
|
|
end
|
2004-11-03 01:43:18 -05:00
|
|
|
|
|
|
|
def have_required_values?
|
|
|
|
@href and @type
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
def guess_type_if_need(xss)
|
|
|
|
if @type.nil?
|
|
|
|
xss.href = @href
|
|
|
|
@type = xss.type
|
|
|
|
end
|
|
|
|
end
|
2004-10-31 09:14:21 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class ChannelBase
|
|
|
|
include Base
|
|
|
|
|
|
|
|
attr_reader :cloud
|
|
|
|
|
|
|
|
%w(about title link description language copyright
|
|
|
|
managingEditor webMaster rating docs skipDays
|
|
|
|
skipHours date lastBuildDate category generator ttl
|
|
|
|
).each do |element|
|
|
|
|
attr_accessor element
|
|
|
|
add_need_initialize_variable(element)
|
|
|
|
end
|
|
|
|
|
2004-11-03 01:43:18 -05:00
|
|
|
alias_method(:pubDate, :date)
|
|
|
|
alias_method(:pubDate=, :date=)
|
|
|
|
|
2004-10-31 09:14:21 -05:00
|
|
|
def initialize(maker)
|
|
|
|
super
|
|
|
|
@cloud = make_cloud
|
|
|
|
end
|
|
|
|
|
|
|
|
def current_element(rss)
|
|
|
|
rss.channel
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
def make_cloud
|
|
|
|
self.class::Cloud.new(@maker)
|
|
|
|
end
|
|
|
|
|
|
|
|
class CloudBase
|
|
|
|
include Base
|
|
|
|
|
|
|
|
%w(domain port path registerProcedure protocol).each do |element|
|
|
|
|
attr_accessor element
|
|
|
|
add_need_initialize_variable(element)
|
|
|
|
end
|
|
|
|
|
|
|
|
def current_element(rss)
|
|
|
|
rss.channel.cloud
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class ImageBase
|
|
|
|
include Base
|
|
|
|
|
|
|
|
%w(title url width height description).each do |element|
|
|
|
|
attr_accessor element
|
|
|
|
add_need_initialize_variable(element)
|
|
|
|
end
|
|
|
|
|
|
|
|
def link
|
|
|
|
@maker.channel.link
|
|
|
|
end
|
|
|
|
|
|
|
|
def current_element(rss)
|
|
|
|
rss.image
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class ItemsBase
|
|
|
|
include Base
|
|
|
|
|
2004-11-03 01:43:18 -05:00
|
|
|
include Enumerable
|
2004-10-31 09:14:21 -05:00
|
|
|
extend Forwardable
|
|
|
|
|
|
|
|
def_delegators(:@items, :<<, :[], :[]=, :first, :last)
|
|
|
|
def_delegators(:@items, :push, :pop, :shift, :unshift)
|
2004-11-03 01:43:18 -05:00
|
|
|
def_delegators(:@items, :each)
|
2004-10-31 09:14:21 -05:00
|
|
|
|
2004-11-03 01:43:18 -05:00
|
|
|
attr_accessor :do_sort
|
2004-10-31 09:14:21 -05:00
|
|
|
|
|
|
|
def initialize(maker)
|
|
|
|
super
|
|
|
|
@items = []
|
2004-11-03 01:43:18 -05:00
|
|
|
@do_sort = false
|
2004-10-31 09:14:21 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def normalize
|
|
|
|
sort_if_need
|
|
|
|
end
|
|
|
|
|
|
|
|
def current_element(rss)
|
|
|
|
rss.items
|
|
|
|
end
|
|
|
|
|
|
|
|
def new_item
|
|
|
|
item = self.class::Item.new(@maker)
|
|
|
|
@items << item
|
|
|
|
item
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
def sort_if_need
|
2004-11-03 01:43:18 -05:00
|
|
|
if @do_sort.respond_to?(:call)
|
2004-10-31 09:14:21 -05:00
|
|
|
@items.sort do |x, y|
|
2004-11-03 01:43:18 -05:00
|
|
|
@do_sort.call(x, y)
|
2004-10-31 09:14:21 -05:00
|
|
|
end
|
2004-11-03 01:43:18 -05:00
|
|
|
elsif @do_sort
|
2004-10-31 09:14:21 -05:00
|
|
|
@items.sort do |x, y|
|
|
|
|
y <=> x
|
|
|
|
end
|
|
|
|
else
|
|
|
|
@items
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class ItemBase
|
|
|
|
include Base
|
|
|
|
|
|
|
|
%w(guid enclosure source category).each do |element|
|
|
|
|
attr_reader element
|
|
|
|
add_other_element(element)
|
|
|
|
module_eval(<<-EOC, __FILE__, __LINE__)
|
|
|
|
private
|
|
|
|
def setup_#{element}(rss, current)
|
|
|
|
@#{element}.to_rss(rss, current)
|
|
|
|
end
|
|
|
|
|
|
|
|
def make_#{element}
|
|
|
|
self.class::#{element[0,1].upcase}#{element[1..-1]}.new(@maker)
|
|
|
|
end
|
|
|
|
EOC
|
|
|
|
end
|
|
|
|
|
|
|
|
%w(title link description date author comments).each do |element|
|
|
|
|
attr_accessor element
|
|
|
|
add_need_initialize_variable(element)
|
|
|
|
end
|
|
|
|
|
2004-11-03 01:43:18 -05:00
|
|
|
alias_method(:pubDate, :date)
|
|
|
|
alias_method(:pubDate=, :date=)
|
|
|
|
|
2004-10-31 09:14:21 -05:00
|
|
|
def initialize(maker)
|
|
|
|
super
|
|
|
|
@guid = make_guid
|
|
|
|
@enclosure = make_enclosure
|
|
|
|
@source = make_source
|
|
|
|
@category = make_category
|
|
|
|
end
|
|
|
|
|
|
|
|
def <=>(other)
|
|
|
|
if @date and other.date
|
|
|
|
@date <=> other.date
|
|
|
|
elsif @date
|
|
|
|
1
|
|
|
|
elsif other.date
|
|
|
|
-1
|
|
|
|
else
|
|
|
|
0
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def current_element(rss)
|
|
|
|
rss.items.last
|
|
|
|
end
|
|
|
|
|
|
|
|
class GuidBase
|
|
|
|
include Base
|
|
|
|
|
|
|
|
%w(isPermaLink content).each do |element|
|
|
|
|
attr_accessor element
|
|
|
|
add_need_initialize_variable(element)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class EnclosureBase
|
|
|
|
include Base
|
|
|
|
|
|
|
|
%w(url length type).each do |element|
|
|
|
|
attr_accessor element
|
|
|
|
add_need_initialize_variable(element)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class SourceBase
|
|
|
|
include Base
|
|
|
|
|
|
|
|
%w(url content).each do |element|
|
|
|
|
attr_accessor element
|
|
|
|
add_need_initialize_variable(element)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class CategoryBase
|
|
|
|
include Base
|
|
|
|
|
|
|
|
%w(domain content).each do |element|
|
|
|
|
attr_accessor element
|
|
|
|
add_need_initialize_variable(element)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class TextinputBase
|
|
|
|
include Base
|
|
|
|
|
|
|
|
%w(title description name link).each do |element|
|
|
|
|
attr_accessor element
|
|
|
|
add_need_initialize_variable(element)
|
|
|
|
end
|
|
|
|
|
|
|
|
def current_element(rss)
|
|
|
|
rss.textinput
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|