1require 'rss/1.0'
2require 'rss/2.0'
3
4module RSS
5
6  TRACKBACK_PREFIX = 'trackback'
7  TRACKBACK_URI = 'http://madskills.com/public/xml/rss/module/trackback/'
8
9  RDF.install_ns(TRACKBACK_PREFIX, TRACKBACK_URI)
10  Rss.install_ns(TRACKBACK_PREFIX, TRACKBACK_URI)
11
12  module TrackBackUtils
13    private
14    def trackback_validate(ignore_unknown_element, tags, uri)
15      return if tags.nil?
16      if tags.find {|tag| tag == "about"} and
17          !tags.find {|tag| tag == "ping"}
18        raise MissingTagError.new("#{TRACKBACK_PREFIX}:ping", tag_name)
19      end
20    end
21  end
22
23  module BaseTrackBackModel
24
25    ELEMENTS = %w(ping about)
26
27    def append_features(klass)
28      super
29
30      unless klass.class == Module
31        klass.module_eval {include TrackBackUtils}
32
33        klass.install_must_call_validator(TRACKBACK_PREFIX, TRACKBACK_URI)
34        %w(ping).each do |name|
35          var_name = "#{TRACKBACK_PREFIX}_#{name}"
36          klass_name = "TrackBack#{Utils.to_class_name(name)}"
37          klass.install_have_child_element(name, TRACKBACK_URI, "?", var_name)
38          klass.module_eval(<<-EOC, __FILE__, __LINE__)
39            remove_method :#{var_name}
40            def #{var_name}
41              @#{var_name} and @#{var_name}.value
42            end
43
44            remove_method :#{var_name}=
45            def #{var_name}=(value)
46              @#{var_name} = Utils.new_with_value_if_need(#{klass_name}, value)
47            end
48          EOC
49        end
50
51        [%w(about s)].each do |name, postfix|
52          var_name = "#{TRACKBACK_PREFIX}_#{name}"
53          klass_name = "TrackBack#{Utils.to_class_name(name)}"
54          klass.install_have_children_element(name, TRACKBACK_URI, "*",
55                                              var_name)
56          klass.module_eval(<<-EOC, __FILE__, __LINE__)
57            remove_method :#{var_name}
58            def #{var_name}(*args)
59              if args.empty?
60                @#{var_name}.first and @#{var_name}.first.value
61              else
62                ret = @#{var_name}.__send__("[]", *args)
63                if ret.is_a?(Array)
64                  ret.collect {|x| x.value}
65                else
66                  ret.value
67                end
68              end
69            end
70
71            remove_method :#{var_name}=
72            remove_method :set_#{var_name}
73            def #{var_name}=(*args)
74              if args.size == 1
75                item = Utils.new_with_value_if_need(#{klass_name}, args[0])
76                @#{var_name}.push(item)
77              else
78                new_val = args.last
79                if new_val.is_a?(Array)
80                  new_val = new_value.collect do |val|
81                    Utils.new_with_value_if_need(#{klass_name}, val)
82                  end
83                else
84                  new_val = Utils.new_with_value_if_need(#{klass_name}, new_val)
85                end
86                @#{var_name}.__send__("[]=", *(args[0..-2] + [new_val]))
87              end
88            end
89            alias set_#{var_name} #{var_name}=
90          EOC
91        end
92      end
93    end
94  end
95
96  module TrackBackModel10
97    extend BaseModel
98    extend BaseTrackBackModel
99
100    class TrackBackPing < Element
101      include RSS10
102
103      class << self
104
105        def required_prefix
106          TRACKBACK_PREFIX
107        end
108
109        def required_uri
110          TRACKBACK_URI
111        end
112
113      end
114
115      @tag_name = "ping"
116
117      [
118        ["resource", ::RSS::RDF::URI, true]
119      ].each do |name, uri, required|
120        install_get_attribute(name, uri, required, nil, nil,
121                              "#{::RSS::RDF::PREFIX}:#{name}")
122      end
123
124      alias_method(:value, :resource)
125      alias_method(:value=, :resource=)
126      def initialize(*args)
127        if Utils.element_initialize_arguments?(args)
128          super
129        else
130          super()
131          self.resource = args[0]
132        end
133      end
134
135      def full_name
136        tag_name_with_prefix(TRACKBACK_PREFIX)
137      end
138    end
139
140    class TrackBackAbout < Element
141      include RSS10
142
143      class << self
144
145        def required_prefix
146          TRACKBACK_PREFIX
147        end
148
149        def required_uri
150          TRACKBACK_URI
151        end
152
153      end
154
155      @tag_name = "about"
156
157      [
158        ["resource", ::RSS::RDF::URI, true]
159      ].each do |name, uri, required|
160        install_get_attribute(name, uri, required, nil, nil,
161                              "#{::RSS::RDF::PREFIX}:#{name}")
162      end
163
164      alias_method(:value, :resource)
165      alias_method(:value=, :resource=)
166
167      def initialize(*args)
168        if Utils.element_initialize_arguments?(args)
169          super
170        else
171          super()
172          self.resource = args[0]
173        end
174      end
175
176      def full_name
177        tag_name_with_prefix(TRACKBACK_PREFIX)
178      end
179
180      private
181      def maker_target(abouts)
182        abouts.new_about
183      end
184
185      def setup_maker_attributes(about)
186        about.resource = self.resource
187      end
188
189    end
190  end
191
192  module TrackBackModel20
193    extend BaseModel
194    extend BaseTrackBackModel
195
196    class TrackBackPing < Element
197      include RSS09
198
199      @tag_name = "ping"
200
201      content_setup
202
203      class << self
204
205        def required_prefix
206          TRACKBACK_PREFIX
207        end
208
209        def required_uri
210          TRACKBACK_URI
211        end
212
213      end
214
215      alias_method(:value, :content)
216      alias_method(:value=, :content=)
217
218      def initialize(*args)
219        if Utils.element_initialize_arguments?(args)
220          super
221        else
222          super()
223          self.content = args[0]
224        end
225      end
226
227      def full_name
228        tag_name_with_prefix(TRACKBACK_PREFIX)
229      end
230
231    end
232
233    class TrackBackAbout < Element
234      include RSS09
235
236      @tag_name = "about"
237
238      content_setup
239
240      class << self
241
242        def required_prefix
243          TRACKBACK_PREFIX
244        end
245
246        def required_uri
247          TRACKBACK_URI
248        end
249
250      end
251
252      alias_method(:value, :content)
253      alias_method(:value=, :content=)
254
255      def initialize(*args)
256        if Utils.element_initialize_arguments?(args)
257          super
258        else
259          super()
260          self.content = args[0]
261        end
262      end
263
264      def full_name
265        tag_name_with_prefix(TRACKBACK_PREFIX)
266      end
267
268    end
269  end
270
271  class RDF
272    class Item; include TrackBackModel10; end
273  end
274
275  class Rss
276    class Channel
277      class Item; include TrackBackModel20; end
278    end
279  end
280
281  BaseTrackBackModel::ELEMENTS.each do |name|
282    class_name = Utils.to_class_name(name)
283    BaseListener.install_class_name(TRACKBACK_URI, name,
284                                    "TrackBack#{class_name}")
285  end
286
287  BaseTrackBackModel::ELEMENTS.collect! {|name| "#{TRACKBACK_PREFIX}_#{name}"}
288end
289