From 0dc342de848a642ecce8db697b8fecd83a63e117 Mon Sep 17 00:00:00 2001 From: yugui Date: Mon, 25 Aug 2008 15:02:05 +0000 Subject: added tag v1_9_0_4 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_9_0_4@18845 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- trunk/lib/rss/itunes.rb | 410 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 trunk/lib/rss/itunes.rb (limited to 'trunk/lib/rss/itunes.rb') diff --git a/trunk/lib/rss/itunes.rb b/trunk/lib/rss/itunes.rb new file mode 100644 index 0000000000..f95ca7aa2e --- /dev/null +++ b/trunk/lib/rss/itunes.rb @@ -0,0 +1,410 @@ +require 'rss/2.0' + +module RSS + ITUNES_PREFIX = 'itunes' + ITUNES_URI = 'http://www.itunes.com/dtds/podcast-1.0.dtd' + + Rss.install_ns(ITUNES_PREFIX, ITUNES_URI) + + module ITunesModelUtils + include Utils + + def def_class_accessor(klass, name, type, *args) + normalized_name = name.gsub(/-/, "_") + full_name = "#{ITUNES_PREFIX}_#{normalized_name}" + klass_name = "ITunes#{Utils.to_class_name(normalized_name)}" + + case type + when :element, :attribute + klass::ELEMENTS << full_name + def_element_class_accessor(klass, name, full_name, klass_name, *args) + when :elements + klass::ELEMENTS << full_name + def_elements_class_accessor(klass, name, full_name, klass_name, *args) + else + klass.install_must_call_validator(ITUNES_PREFIX, ITUNES_URI) + klass.install_text_element(normalized_name, ITUNES_URI, "?", + full_name, type, name) + end + end + + def def_element_class_accessor(klass, name, full_name, klass_name, + recommended_attribute_name=nil) + klass.install_have_child_element(name, ITUNES_PREFIX, "?", full_name) + end + + def def_elements_class_accessor(klass, name, full_name, klass_name, + plural_name, recommended_attribute_name=nil) + full_plural_name = "#{ITUNES_PREFIX}_#{plural_name}" + klass.install_have_children_element(name, ITUNES_PREFIX, "*", + full_name, full_plural_name) + end + end + + module ITunesBaseModel + extend ITunesModelUtils + + ELEMENTS = [] + + ELEMENT_INFOS = [["author"], + ["block", :yes_other], + ["explicit", :yes_clean_other], + ["keywords", :csv], + ["subtitle"], + ["summary"]] + end + + module ITunesChannelModel + extend BaseModel + extend ITunesModelUtils + include ITunesBaseModel + + ELEMENTS = [] + + class << self + def append_features(klass) + super + + return if klass.instance_of?(Module) + ELEMENT_INFOS.each do |name, type, *additional_infos| + def_class_accessor(klass, name, type, *additional_infos) + end + end + end + + ELEMENT_INFOS = [ + ["category", :elements, "categories", "text"], + ["image", :attribute, "href"], + ["owner", :element], + ["new-feed-url"], + ] + ITunesBaseModel::ELEMENT_INFOS + + class ITunesCategory < Element + include RSS09 + + @tag_name = "category" + + class << self + def required_prefix + ITUNES_PREFIX + end + + def required_uri + ITUNES_URI + end + end + + [ + ["text", "", true] + ].each do |name, uri, required| + install_get_attribute(name, uri, required) + end + + ITunesCategory = self + install_have_children_element("category", ITUNES_URI, "*", + "#{ITUNES_PREFIX}_category", + "#{ITUNES_PREFIX}_categories") + + def initialize(*args) + if Utils.element_initialize_arguments?(args) + super + else + super() + self.text = args[0] + end + end + + def full_name + tag_name_with_prefix(ITUNES_PREFIX) + end + + private + def maker_target(categories) + if text or !itunes_categories.empty? + categories.new_category + else + nil + end + end + + def setup_maker_attributes(category) + category.text = text if text + end + + def setup_maker_elements(category) + super(category) + itunes_categories.each do |sub_category| + sub_category.setup_maker(category) + end + end + end + + class ITunesImage < Element + include RSS09 + + @tag_name = "image" + + class << self + def required_prefix + ITUNES_PREFIX + end + + def required_uri + ITUNES_URI + end + end + + [ + ["href", "", true] + ].each do |name, uri, required| + install_get_attribute(name, uri, required) + end + + def initialize(*args) + if Utils.element_initialize_arguments?(args) + super + else + super() + self.href = args[0] + end + end + + def full_name + tag_name_with_prefix(ITUNES_PREFIX) + end + + private + def maker_target(target) + if href + target.itunes_image {|image| image} + else + nil + end + end + + def setup_maker_attributes(image) + image.href = href + end + end + + class ITunesOwner < Element + include RSS09 + + @tag_name = "owner" + + class << self + def required_prefix + ITUNES_PREFIX + end + + def required_uri + ITUNES_URI + end + end + + install_must_call_validator(ITUNES_PREFIX, ITUNES_URI) + [ + ["name"], + ["email"], + ].each do |name,| + ITunesBaseModel::ELEMENT_INFOS << name + install_text_element(name, ITUNES_URI, nil, "#{ITUNES_PREFIX}_#{name}") + end + + def initialize(*args) + if Utils.element_initialize_arguments?(args) + super + else + super() + self.itunes_name = args[0] + self.itunes_email = args[1] + end + end + + def full_name + tag_name_with_prefix(ITUNES_PREFIX) + end + + private + def maker_target(target) + target.itunes_owner + end + + def setup_maker_element(owner) + super(owner) + owner.itunes_name = itunes_name + owner.itunes_email = itunes_email + end + end + end + + module ITunesItemModel + extend BaseModel + extend ITunesModelUtils + include ITunesBaseModel + + class << self + def append_features(klass) + super + + return if klass.instance_of?(Module) + ELEMENT_INFOS.each do |name, type| + def_class_accessor(klass, name, type) + end + end + end + + ELEMENT_INFOS = ITunesBaseModel::ELEMENT_INFOS + + [["duration", :element, "content"]] + + class ITunesDuration < Element + include RSS09 + + @tag_name = "duration" + + class << self + def required_prefix + ITUNES_PREFIX + end + + def required_uri + ITUNES_URI + end + + def parse(duration, do_validate=true) + if do_validate and /\A(?: + \d?\d:[0-5]\d:[0-5]\d| + [0-5]?\d:[0-5]\d + )\z/x !~ duration + raise ArgumentError, + "must be one of HH:MM:SS, H:MM:SS, MM::SS, M:SS: " + + duration.inspect + end + + components = duration.split(':') + components[3..-1] = nil if components.size > 3 + + components.unshift("00") until components.size == 3 + + components.collect do |component| + component.to_i + end + end + + def construct(hour, minute, second) + components = [minute, second] + if components.include?(nil) + nil + else + components.unshift(hour) if hour and hour > 0 + components.collect do |component| + "%02d" % component + end.join(":") + end + end + end + + content_setup + alias_method(:value, :content) + remove_method(:content=) + + attr_reader :hour, :minute, :second + def initialize(*args) + if Utils.element_initialize_arguments?(args) + super + else + super() + args = args[0] if args.size == 1 and args[0].is_a?(Array) + if args.size == 1 + self.content = args[0] + elsif args.size > 3 + raise ArgumentError, + "must be (do_validate, params), (content), " + + "(minute, second), ([minute, second]), " + + "(hour, minute, second) or ([hour, minute, second]): " + + args.inspect + else + @second, @minute, @hour = args.reverse + update_content + end + end + end + + def content=(value) + if value.nil? + @content = nil + elsif value.is_a?(self.class) + self.content = value.content + else + begin + @hour, @minute, @second = self.class.parse(value, @do_validate) + rescue ArgumentError + raise NotAvailableValueError.new(tag_name, value) + end + @content = value + end + end + alias_method(:value=, :content=) + + def hour=(hour) + @hour = @do_validate ? Integer(hour) : hour.to_i + update_content + hour + end + + def minute=(minute) + @minute = @do_validate ? Integer(minute) : minute.to_i + update_content + minute + end + + def second=(second) + @second = @do_validate ? Integer(second) : second.to_i + update_content + second + end + + def full_name + tag_name_with_prefix(ITUNES_PREFIX) + end + + private + def update_content + @content = self.class.construct(hour, minute, second) + end + + def maker_target(target) + if @content + target.itunes_duration {|duration| duration} + else + nil + end + end + + def setup_maker_element(duration) + super(duration) + duration.content = @content + end + end + end + + class Rss + class Channel + include ITunesChannelModel + class Item; include ITunesItemModel; end + end + end + + element_infos = + ITunesChannelModel::ELEMENT_INFOS + ITunesItemModel::ELEMENT_INFOS + element_infos.each do |name, type| + case type + when :element, :elements, :attribute + class_name = Utils.to_class_name(name) + BaseListener.install_class_name(ITUNES_URI, name, "ITunes#{class_name}") + else + accessor_base = "#{ITUNES_PREFIX}_#{name.gsub(/-/, '_')}" + BaseListener.install_get_text_element(ITUNES_URI, name, accessor_base) + end + end +end -- cgit v1.2.3