1require "rss/maker/atom"
2
3module RSS
4  module Maker
5    module Atom
6      class Feed < RSSBase
7        def initialize(feed_version="1.0")
8          super
9          @feed_type = "atom"
10          @feed_subtype = "feed"
11        end
12
13        private
14        def make_feed
15          ::RSS::Atom::Feed.new(@version, @encoding, @standalone)
16        end
17
18        def setup_elements(feed)
19          setup_channel(feed)
20          setup_image(feed)
21          setup_items(feed)
22        end
23
24        class Channel < ChannelBase
25          include SetupDefaultLanguage
26
27          def to_feed(feed)
28            set_default_values do
29              setup_values(feed)
30              feed.dc_dates.clear
31              setup_other_elements(feed)
32              if image_favicon.about
33                icon = feed.class::Icon.new
34                icon.content = image_favicon.about
35                feed.icon = icon
36              end
37              unless have_required_values?
38                raise NotSetError.new("maker.channel",
39                                      not_set_required_variables)
40              end
41            end
42          end
43
44          def have_required_values?
45            super and
46              (!authors.empty? or
47               @maker.items.any? {|item| !item.authors.empty?})
48          end
49
50          private
51          def required_variable_names
52            %w(id updated)
53          end
54
55          def variables
56            super + %w(id updated)
57          end
58
59          def variable_is_set?
60            super or !authors.empty?
61          end
62
63          def not_set_required_variables
64            vars = super
65            if authors.empty? and
66                @maker.items.all? {|item| item.author.to_s.empty?}
67              vars << "author"
68            end
69            vars << "title" unless title {|t| t.have_required_values?}
70            vars
71          end
72
73          def _set_default_values(&block)
74            keep = {
75              :id => id,
76            }
77            self.id ||= about
78            super(&block)
79          ensure
80            self.id = keep[:id]
81          end
82
83          class SkipDays < SkipDaysBase
84            def to_feed(*args)
85            end
86
87            class Day < DayBase
88            end
89          end
90
91          class SkipHours < SkipHoursBase
92            def to_feed(*args)
93            end
94
95            class Hour < HourBase
96            end
97          end
98
99          class Cloud < CloudBase
100            def to_feed(*args)
101            end
102          end
103
104          class Categories < CategoriesBase
105            class Category < CategoryBase
106              include AtomCategory
107
108              def self.not_set_name
109                "maker.channel.category"
110              end
111            end
112          end
113
114          class Links < LinksBase
115            class Link < LinkBase
116              include AtomLink
117
118              def self.not_set_name
119                "maker.channel.link"
120              end
121            end
122          end
123
124          AtomPersons.def_atom_persons(self, "author", "maker.channel.author")
125          AtomPersons.def_atom_persons(self, "contributor",
126                                       "maker.channel.contributor")
127
128          class Generator < GeneratorBase
129            include AtomGenerator
130
131            def self.not_set_name
132              "maker.channel.generator"
133            end
134          end
135
136          AtomTextConstruct.def_atom_text_construct(self, "rights",
137                                                    "maker.channel.copyright",
138                                                    "Copyright")
139          AtomTextConstruct.def_atom_text_construct(self, "subtitle",
140                                                    "maker.channel.description",
141                                                    "Description")
142          AtomTextConstruct.def_atom_text_construct(self, "title",
143                                                    "maker.channel.title")
144        end
145
146        class Image < ImageBase
147          def to_feed(feed)
148            logo = feed.class::Logo.new
149            class << logo
150              alias_method(:url=, :content=)
151            end
152            set = setup_values(logo)
153            class << logo
154              remove_method(:url=)
155            end
156            if set
157              feed.logo = logo
158              set_parent(logo, feed)
159              setup_other_elements(feed, logo)
160            elsif variable_is_set?
161              raise NotSetError.new("maker.image", not_set_required_variables)
162            end
163          end
164
165          private
166          def required_variable_names
167            %w(url)
168          end
169        end
170
171        class Items < ItemsBase
172          def to_feed(feed)
173            normalize.each do |item|
174              item.to_feed(feed)
175            end
176            setup_other_elements(feed, feed.entries)
177          end
178
179          class Item < ItemBase
180            def to_feed(feed)
181              set_default_values do
182                entry = feed.class::Entry.new
183                set = setup_values(entry)
184                entry.dc_dates.clear
185                setup_other_elements(feed, entry)
186                if set
187                  feed.entries << entry
188                  set_parent(entry, feed)
189                elsif variable_is_set?
190                  raise NotSetError.new("maker.item", not_set_required_variables)
191                end
192              end
193            end
194
195            def have_required_values?
196              set_default_values do
197                super and title {|t| t.have_required_values?}
198              end
199            end
200
201            private
202            def required_variable_names
203              %w(id updated)
204            end
205
206            def variables
207              super + ["updated"]
208            end
209
210            def not_set_required_variables
211              vars = super
212              vars << "title" unless title {|t| t.have_required_values?}
213              vars
214            end
215
216            def _set_default_values(&block)
217              keep = {
218                :id => id,
219              }
220              self.id ||= link
221              super(&block)
222            ensure
223              self.id = keep[:id]
224            end
225
226            class Guid < GuidBase
227              def to_feed(feed, current)
228              end
229            end
230
231            class Enclosure < EnclosureBase
232              def to_feed(feed, current)
233              end
234            end
235
236            class Source < SourceBase
237              def to_feed(feed, current)
238                source = current.class::Source.new
239                setup_values(source)
240                current.source = source
241                set_parent(source, current)
242                setup_other_elements(feed, source)
243                current.source = nil if source.to_s == "<source/>"
244              end
245
246              private
247              def required_variable_names
248                []
249              end
250
251              def variables
252                super + ["updated"]
253              end
254
255              AtomPersons.def_atom_persons(self, "author",
256                                           "maker.item.source.author")
257              AtomPersons.def_atom_persons(self, "contributor",
258                                           "maker.item.source.contributor")
259
260              class Categories < CategoriesBase
261                class Category < CategoryBase
262                  include AtomCategory
263
264                  def self.not_set_name
265                    "maker.item.source.category"
266                  end
267                end
268              end
269
270              class Generator < GeneratorBase
271                include AtomGenerator
272
273                def self.not_set_name
274                  "maker.item.source.generator"
275                end
276              end
277
278              class Icon < IconBase
279                def to_feed(feed, current)
280                  icon = current.class::Icon.new
281                  class << icon
282                    alias_method(:url=, :content=)
283                  end
284                  set = setup_values(icon)
285                  class << icon
286                    remove_method(:url=)
287                  end
288                  if set
289                    current.icon = icon
290                    set_parent(icon, current)
291                    setup_other_elements(feed, icon)
292                  elsif variable_is_set?
293                    raise NotSetError.new("maker.item.source.icon",
294                                          not_set_required_variables)
295                  end
296                end
297
298                private
299                def required_variable_names
300                  %w(url)
301                end
302              end
303
304              class Links < LinksBase
305                class Link < LinkBase
306                  include AtomLink
307
308                  def self.not_set_name
309                    "maker.item.source.link"
310                  end
311                end
312              end
313
314              class Logo < LogoBase
315                include AtomLogo
316
317                def self.not_set_name
318                  "maker.item.source.logo"
319                end
320              end
321
322              maker_name_base = "maker.item.source."
323              maker_name = "#{maker_name_base}rights"
324              AtomTextConstruct.def_atom_text_construct(self, "rights",
325                                                        maker_name)
326              maker_name = "#{maker_name_base}subtitle"
327              AtomTextConstruct.def_atom_text_construct(self, "subtitle",
328                                                        maker_name)
329              maker_name = "#{maker_name_base}title"
330              AtomTextConstruct.def_atom_text_construct(self, "title",
331                                                        maker_name)
332            end
333
334            class Categories < CategoriesBase
335              class Category < CategoryBase
336                include AtomCategory
337
338                def self.not_set_name
339                  "maker.item.category"
340                end
341              end
342            end
343
344            AtomPersons.def_atom_persons(self, "author", "maker.item.author")
345            AtomPersons.def_atom_persons(self, "contributor",
346                                         "maker.item.contributor")
347
348            class Links < LinksBase
349              class Link < LinkBase
350                include AtomLink
351
352                def self.not_set_name
353                  "maker.item.link"
354                end
355              end
356            end
357
358            AtomTextConstruct.def_atom_text_construct(self, "rights",
359                                                      "maker.item.rights")
360            AtomTextConstruct.def_atom_text_construct(self, "summary",
361                                                      "maker.item.description",
362                                                      "Description")
363            AtomTextConstruct.def_atom_text_construct(self, "title",
364                                                      "maker.item.title")
365
366            class Content < ContentBase
367              def to_feed(feed, current)
368                content = current.class::Content.new
369                if setup_values(content)
370                  content.src = nil if content.src and content.content
371                  current.content = content
372                  set_parent(content, current)
373                  setup_other_elements(feed, content)
374                elsif variable_is_set?
375                  raise NotSetError.new("maker.item.content",
376                                        not_set_required_variables)
377                end
378              end
379
380              alias_method(:xml, :xml_content)
381
382              private
383              def required_variable_names
384                if out_of_line?
385                  %w(type)
386                elsif xml_type?
387                  %w(xml_content)
388                else
389                  %w(content)
390                end
391              end
392
393              def variables
394                if out_of_line?
395                  super
396                elsif xml_type?
397                  super + %w(xml)
398                else
399                  super
400                end
401              end
402
403              def xml_type?
404                _type = type
405                return false if _type.nil?
406                _type == "xhtml" or
407                  /(?:\+xml|\/xml)$/i =~ _type or
408                  %w(text/xml-external-parsed-entity
409                     application/xml-external-parsed-entity
410                     application/xml-dtd).include?(_type.downcase)
411              end
412            end
413          end
414        end
415
416        class Textinput < TextinputBase
417        end
418      end
419    end
420
421    add_maker("atom", "1.0", Atom::Feed)
422    add_maker("atom:feed", "1.0", Atom::Feed)
423    add_maker("atom1.0", "1.0", Atom::Feed)
424    add_maker("atom1.0:feed", "1.0", Atom::Feed)
425  end
426end
427