View Javadoc

1   package yarfraw.core.datamodel;
2   
3   import java.io.IOException;
4   import java.text.SimpleDateFormat;
5   import java.util.ArrayList;
6   import java.util.Arrays;
7   import java.util.Date;
8   import java.util.HashMap;
9   import java.util.HashSet;
10  import java.util.List;
11  import java.util.Locale;
12  import java.util.Map;
13  import java.util.Set;
14  
15  import javax.xml.namespace.QName;
16  import javax.xml.parsers.ParserConfigurationException;
17  
18  import org.apache.commons.collections.CollectionUtils;
19  import org.apache.commons.lang.ArrayUtils;
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.w3c.dom.Element;
23  import org.xml.sax.SAXException;
24  
25  import yarfraw.utils.ValidationUtils;
26  import yarfraw.utils.XMLUtils;
27  /***
28   * 
29   * The name of the channel. It's how people refer to your service. 
30   * If you have an HTML website that contains the same information as your RSS file, 
31   * the title of your channel should be the same as the title of your website.
32   * <p/>
33   * for Atom 1.0 format, the field also maps to &lt;feed> element. 
34   * <br/>
35   * 
36   * <li>Rss 1.0 - &lt;channel> and second level elements  such as &lt;item> elements under &lt;rdf:RDF>
37   * </li>
38   * <li>Rss 2.0 - &lt;channel>
39   * </li>
40   * <li>Atom 1.0 - &lt;feed> The "atom:feed" element is the document (i.e., top-level) element of an Atom Feed Document, 
41   * acting as a container for metadata and data associated with the feed. Its element children consist of metadata 
42   * elements followed by zero or more atom:entry child elements.
43   * </li>
44   * @author jliang
45   *
46   */
47  public class ChannelFeed extends AbstractBaseObject{
48    /***
49     * 
50     */
51    private static final long serialVersionUID = 20070927L;
52    private static final Log LOG = LogFactory.getLog(ChannelFeed.class);
53    private List<ItemEntry> _items;
54    private Text _title;
55    private List<Link> _links;
56    private Text _descriptionOrSubtitle;
57    private Text _rights;
58    private List<Person> _managingEditorOrAuthorOrPublisher;
59    private List<Person> _webMasterOrCreator;
60    private List<Person> _contributors;
61    private Set<CategorySubject> _categorySubjects;
62    private String _pubDate;
63    private String _lastBuildOrUpdatedDate;
64    private Id _uid;
65    private Generator _generator;
66    private String _docs;
67    private Integer _ttl;
68    private Cloud _cloud;
69    private Image _imageOrIcon;
70    private Image _logo;
71    private TextInput _texInput;
72    private Set<Integer> _skipHours;
73    private Set<Day> _skipDays;
74    
75    /***
76     * <li>Rss 1.0 - &lt;item> 
77     * While commonly a news headline, with RSS 1.0's modular extensibility, 
78     * this can be just about anything: discussion posting, job listing, software 
79     * patch -- any object with a URI. There may be a minimum of one item per RSS 
80     * document. While RSS 1.0 does not enforce an upper limit, 
81     * for backward compatibility with RSS 0.9 and 0.91, a maximum of fifteen items is recommended.
82     * </li>
83     * <li>Rss 2.0 - &lt;item> 
84     * A channel may contain any number of <item>s. An item may represent a "story" 
85     * -- much like a story in a newspaper or magazine; if so its description is a 
86     * synopsis of the story, and the link points to the full story. An item may also 
87     * be complete in itself, if so, the description contains the text 
88     * (entity-encoded HTML is allowed; see examples), and the link and title 
89     * may be omitted. All elements of an item are optional, however at least one 
90     * of title or description must be present.
91     * </li>
92     * <li>Atom 1.0 - &lt;entry>
93     * The "atom:entry" element represents an individual entry, acting as a 
94     * container for metadata and data associated with the entry. This element 
95     * can appear as a child of the atom:feed element, or it can appear as the 
96     * document (i.e., top-level) element of a standalone Atom Entry Document.
97     * </li>
98     * @return
99     */
100   public List<ItemEntry> getItems() {
101     return _items;
102   }
103 
104   /***
105    * <li>Rss 1.0 - &lt;item> 
106    * While commonly a news headline, with RSS 1.0's modular extensibility, 
107    * this can be just about anything: discussion posting, job listing, software 
108    * patch -- any object with a URI. There may be a minimum of one item per RSS 
109    * document. While RSS 1.0 does not enforce an upper limit, 
110    * for backward compatibility with RSS 0.9 and 0.91, a maximum of fifteen items is recommended.
111    * </li>
112    * <li>Rss 2.0 - &lt;item> 
113    * A channel may contain any number of <item>s. An item may represent a "story" 
114    * -- much like a story in a newspaper or magazine; if so its description is a 
115    * synopsis of the story, and the link points to the full story. An item may also 
116    * be complete in itself, if so, the description contains the text 
117    * (entity-encoded HTML is allowed; see examples), and the link and title 
118    * may be omitted. All elements of an item are optional, however at least one 
119    * of title or description must be present.
120    * </li>
121    * <li>Atom 1.0 - &lt;entry>
122    * The "atom:entry" element represents an individual entry, acting as a 
123    * container for metadata and data associated with the entry. This element 
124    * can appear as a child of the atom:feed element, or it can appear as the 
125    * document (i.e., top-level) element of a standalone Atom Entry Document.
126    * </li>
127    * @param items
128    * @return
129    */
130   public ChannelFeed setItems(List<ItemEntry> items) {
131     _items = items;
132     return this;
133   }
134 
135   /***
136    * <li>Rss 1.0 - &lt;item> 
137    * While commonly a news headline, with RSS 1.0's modular extensibility, 
138    * this can be just about anything: discussion posting, job listing, software 
139    * patch -- any object with a URI. There may be a minimum of one item per RSS 
140    * document. While RSS 1.0 does not enforce an upper limit, 
141    * for backward compatibility with RSS 0.9 and 0.91, a maximum of fifteen items is recommended.
142    * </li>
143    * <li>Rss 2.0 - &lt;item> 
144    * A channel may contain any number of <item>s. An item may represent a "story" 
145    * -- much like a story in a newspaper or magazine; if so its description is a 
146    * synopsis of the story, and the link points to the full story. An item may also 
147    * be complete in itself, if so, the description contains the text 
148    * (entity-encoded HTML is allowed; see examples), and the link and title 
149    * may be omitted. All elements of an item are optional, however at least one 
150    * of title or description must be present.
151    * </li>
152    * <li>Atom 1.0 - &lt;entry>
153    * The "atom:entry" element represents an individual entry, acting as a 
154    * container for metadata and data associated with the entry. This element 
155    * can appear as a child of the atom:feed element, or it can appear as the 
156    * document (i.e., top-level) element of a standalone Atom Entry Document.
157    * </li>
158    * <br/>
159    * This method adds all the input {@link ItemEntry} to the end of the items list.
160    * @param items
161    * @return
162    */
163   public ChannelFeed addItem(ItemEntry...items){
164     if(ArrayUtils.isEmpty(items)){
165       LOG.warn("Empty items array is ignored");
166       return this;
167     }
168     if(_items == null){
169       _items = new ArrayList<ItemEntry>();
170     }
171     for(ItemEntry item : items){
172       _items.add(item);
173     }
174     return this;
175   }
176 
177   /***
178    * <li>Rss 1.0 - The channel's title.
179    * </li>
180    * <li>Rss 2.0 - The title of the channel.
181    * </li>
182    * <li>Atom 1.0 - 
183    * The "atom:title" element is a Text construct that conveys a 
184    * human-readable title for an entry or feed.
185    * </li>
186    * <br/>
187    * Note: Rss 1.0 and Rss 2.0 only use the text content of the title field, 
188    * the other fields in the {@link Text} object are ignored.
189    * @return
190    */
191   public Text getTitle() {
192     return _title;
193   }
194   
195   /***
196    * <li>Rss 1.0 - The channel's title.
197    * </li>
198    * <li>Rss 2.0 - The title of the channel.
199    * </li>
200    * <li>Atom 1.0 - 
201    * The "atom:title" element is a Text construct that conveys a 
202    * human-readable title for an entry or feed.
203    * </li>
204    * <br/>
205    * This method returns the text content of the <code>title</code> field.
206    * @return
207    */
208   public String getTitleText() {
209     return _title == null ? null :_title.getText();
210   }
211 
212   /***
213    * <li>Rss 1.0 - The channel's title.
214    * </li>
215    * <li>Rss 2.0 - The title of the channel.
216    * </li>
217    * <li>Atom 1.0 - 
218    * The "atom:title" element is a Text construct that conveys a 
219    * human-readable title for an entry or feed.
220    * </li>
221    * <br/>
222    * Note: Rss 1.0 and Rss 2.0 only use the text content of the title field, 
223    * the other fields in the {@link Text} object are ignored.
224    * @param title
225    * @return
226    */
227   public ChannelFeed setTitle(Text title) {
228     _title = title;
229     return this;
230   }
231 
232   /***
233    * <li>Rss 1.0 - The channel's title.
234    * </li>
235    * <li>Rss 2.0 - The title of the channel.
236    * </li>
237    * <li>Atom 1.0 - 
238    * The "atom:title" element is a Text construct that conveys a 
239    * human-readable title for an entry or feed.
240    * </li>
241    * <br/>
242    * This method constructs a new {@link Text} object with the input string as its text
243    * content.
244    * <br/>
245    * Note: Rss 1.0 and Rss 2.0 only use the text content of the title field, 
246    * the other fields in the {@link Text} object are ignored.
247    * @param title
248    * @return
249    */
250   public ChannelFeed setTitle(String title){
251     if(title == null){
252       _title = null;
253       return this;
254     }
255     return setTitle(new Text(title));
256   }
257 
258   /***
259    * <li>Rss 1.0 - The URL to which an HTML rendering of the channel title will link, 
260    * commonly the parent site's home or news page.
261    * </li>
262    * <li>Rss 2.0 - The URL to the HTML website corresponding to the channel.
263    * </li>
264    * <li>Atom 1.0 - 
265    * The "atom:link" element defines a reference from an entry or feed to a Web 
266    * resource. This specification assigns no meaning to the content (if any) of this element.
267    * </li>
268    * 
269    * <br/>
270    * Note: According to the specs, only Atom 1.0 allows multiple links under the {@link ChannelFeed}.
271    * Therefore, for Rss 1.0 and Rss 2.0, only the first link will be interpreted, the rest will be 
272    * ignored.
273    * @return
274    */
275   public List<Link> getLinks() {
276     return _links;
277   }
278 
279 
280   /***
281    * <li>Rss 1.0 - The URL to which an HTML rendering of the channel title will link, 
282    * commonly the parent site's home or news page.
283    * </li>
284    * <li>Rss 2.0 - The URL to the HTML website corresponding to the channel.
285    * </li>
286    * <li>Atom 1.0 - 
287    * The "atom:link" element defines a reference from an entry or feed to a Web 
288    * resource. This specification assigns no meaning to the content (if any) of this element.
289    * </li>
290    * 
291    * <br/>
292    * Note: According to the specs, only Atom 1.0 allows multiple links under the {@link ChannelFeed}.
293    * Therefore, for Rss 1.0 and Rss 2.0, only the first link will be interpreted, the rest will be 
294    * ignored.
295    * @param links
296    * @return
297    */
298   public ChannelFeed setLinks(List<Link> links) {
299     _links = links;
300     return this;
301   }
302 
303 
304   /***
305    * <li>Rss 1.0 - The URL to which an HTML rendering of the channel title will link, 
306    * commonly the parent site's home or news page.
307    * </li>
308    * <li>Rss 2.0 - The URL to the HTML website corresponding to the channel.
309    * </li>
310    * <li>Atom 1.0 - 
311    * The "atom:link" element defines a reference from an entry or feed to a Web 
312    * resource. This specification assigns no meaning to the content (if any) of this element.
313    * </li>
314    * 
315    * <br/>
316    * Note: According to the specs, only Atom 1.0 allows multiple links under the {@link ChannelFeed}.
317    * Therefore, for Rss 1.0 and Rss 2.0, only the first link will be interpreted, the rest will be 
318    * ignored.
319    * <br/>
320    * This method creates new {@link Link} objects and adds them to the END of the links list. 
321    * 
322    * @param href
323    * @return
324    */
325   public ChannelFeed addLink(String... href) {
326     if(ArrayUtils.isEmpty(href)){
327       LOG.warn("Empty href array is ignored");
328       return this;
329     }
330     if(_links == null){
331       _links = new ArrayList<Link>();
332     }
333     for (String s:href){
334       _links.add(new Link(s));
335     }
336     return this;
337   }
338 
339   /***
340    * <li>Rss 1.0 - The URL to which an HTML rendering of the channel title will link, 
341    * commonly the parent site's home or news page.
342    * </li>
343    * <li>Rss 2.0 - The URL to the HTML website corresponding to the channel.
344    * </li>
345    * <li>Atom 1.0 - 
346    * The "atom:link" element defines a reference from an entry or feed to a Web 
347    * resource. This specification assigns no meaning to the content (if any) of this element.
348    * </li>
349    * 
350    * <br/>
351    * Note: According to the specs, only Atom 1.0 allows multiple links under the {@link ChannelFeed}.
352    * Therefore, for Rss 1.0 and Rss 2.0, only the first link will be interpreted, the rest will be 
353    * ignored.
354    * <br/>
355    * 
356    * <br/>
357    * This method adds input {@link Link} to the END of the links list. 
358    * 
359    * @param link
360    * @return
361    */
362   public ChannelFeed addLink(Link... link) {
363     if(ArrayUtils.isEmpty(link)){
364       LOG.warn("Empty link array is ignored");
365       return this;
366     }
367     if(_links == null){
368       _links = new ArrayList<Link>();
369     }
370     for(Link l : link){
371       _links.add(l);
372     }
373     return this;
374   }
375   
376   /***
377    * <li>Rss 1.0 - &lt;description> 
378    * A brief description of the channel's content, function, source, etc.
379    * </li>
380    * <li>Rss 2.0 - &lt;description> Phrase or sentence describing the channel.
381    * </li>
382    * <li>Atom 1.0 - 
383    * This maps to &lt;subtitle>. 
384    * The "atom:subtitle" element is a Text construct that conveys a human-readable description or subtitle for a feed.
385    * </li>
386    * @return
387    */
388   public Text getDescriptionOrSubtitle() {
389     return _descriptionOrSubtitle;
390   }
391   
392   /***
393    * <li>Rss 1.0 - &lt;description> 
394    * A brief description of the channel's content, function, source, etc.
395    * </li>
396    * <li>Rss 2.0 - &lt;description> Phrase or sentence describing the channel.
397    * </li>
398    * <li>Atom 1.0 - 
399    * This maps to &lt;subtitle>. 
400    * The "atom:subtitle" element is a Text construct that conveys a human-readable description or subtitle for a feed.
401    * </li>
402    * <br/>
403    * This method returns the text content of the <code>descriptionOrSubtitle</code> field.
404    * @return
405    */
406   public String getDescriptionOrSubtitleText() {
407     return _descriptionOrSubtitle == null ? null : _descriptionOrSubtitle.getText();
408   }
409 
410   /***
411    * <li>Rss 1.0 - &lt;description> 
412    * A brief description of the channel's content, function, source, etc.
413    * </li>
414    * <li>Rss 2.0 - &lt;description> Phrase or sentence describing the channel.
415    * </li>
416    * <li>Atom 1.0 - 
417    * This maps to &lt;subtitle>. 
418    * The "atom:subtitle" element is a Text construct that conveys a human-readable description or subtitle for a feed.
419    * </li>
420    * @param descriptionOrSubtitle
421    * @return
422    */
423   public ChannelFeed setDescriptionOrSubtitle(Text descriptionOrSubtitle) {
424     _descriptionOrSubtitle = descriptionOrSubtitle;
425     return this;
426   }
427 
428   /***
429    * <li>Rss 1.0 - &lt;description> 
430    * A brief description of the channel's content, function, source, etc.
431    * </li>
432    * <li>Rss 2.0 - &lt;description> Phrase or sentence describing the channel.
433    * </li>
434    * <li>Atom 1.0 - 
435    * This maps to &lt;subtitle>. 
436    * The "atom:subtitle" element is a Text construct that conveys a human-readable description or subtitle for a feed.
437    * </li>
438    * 
439    * <br/>
440    * This method constructs a new {@link Text} object with the input string as its text content.
441    * @param descriptionOrSubtitle
442    * @return
443    */
444   public ChannelFeed setDescriptionOrSubtitle(String descriptionOrSubtitle) {
445     _descriptionOrSubtitle = descriptionOrSubtitle == null? null: new Text(descriptionOrSubtitle);
446     return this;
447   }
448   
449   /***
450    * <li>Rss 1.0 - &lt;dc:rights> Information about rights held in and over the resource.
451    * </li>
452    * <li>Rss 2.0 - &lt;copyright> Copyright notice for content in the channel.
453    * </li>
454    * <li>Atom 1.0 - &lt;rights> The "atom:rights" element is a Text construct that conveys information about rights held in and over an entry or feed.
455    * </li>
456    * @return
457    */
458   public Text getRights() {
459     return _rights;
460   }
461   
462 
463   /***
464    * <li>Rss 1.0 - &lt;dc:rights> Information about rights held in and over the resource.
465    * </li>
466    * <li>Rss 2.0 - &lt;copyright> Copyright notice for content in the channel.
467    * </li>
468    * <li>Atom 1.0 - &lt;rights> The "atom:rights" element is a Text construct that conveys information about rights held in and over an entry or feed.
469    * </li>
470    * 
471    * @return the text content of the <code>rights</code> field.
472    */
473   public String getRightsText() {
474     return _rights == null ? null:_rights.getText();
475   }
476   
477   /***
478    * <li>Rss 1.0 - &lt;dc:rights> Information about rights held in and over the resource.
479    * </li>
480    * <li>Rss 2.0 - &lt;copyright> Copyright notice for content in the channel.
481    * </li>
482    * <li>Atom 1.0 - &lt;rights> The "atom:rights" element is a Text construct that conveys information about rights held in and over an entry or feed.
483    * </li>
484    * @param rights
485    * @return
486    */
487   public ChannelFeed setRights(Text rights) {
488     _rights = rights;
489     return this;
490   }
491 
492   /***
493    * <li>Rss 1.0 - &lt;dc:rights> Information about rights held in and over the resource.
494    * </li>
495    * <li>Rss 2.0 - &lt;copyright> Copyright notice for content in the channel.
496    * </li>
497    * <li>Atom 1.0 - &lt;rights> The "atom:rights" element is a Text construct that conveys information about rights held in and over an entry or feed.
498    * </li>
499    * <br/>
500    * This method creates a new {@link Text} object using the input string as its content and sets <code>rights</code> field to this object.
501    * @param rights
502    * @return
503    */
504   public ChannelFeed setRights(String rights) {
505     if(rights == null){
506       _rights = null;
507       return this;
508     }
509     return setRights(new Text(rights));
510   }
511 
512   /***
513    * <li>Rss 1.0 - &lt;dc:publisher> An entity responsible for making the resource available
514    * </li>
515    * <li>Rss 2.0 - &lt;managingEditor> Email address for person responsible for editorial content.
516    * </li>
517    * <li>Atom 1.0 - &lt;author> 
518    * The "atom:author" element is a Person construct that indicates the author of the entry or feed.
519    * </li>
520    * <br/>
521    * Note: This is a list because Atom 1.0 allows multiple &lt;author>. For Rss 1.0 and Rss 2.0,
522    * only the first {@link Person} is interpreted, the rest are ignored.
523    * @return
524    */
525   public List<Person> getManagingEditorOrAuthorOrPublisher() {
526     return _managingEditorOrAuthorOrPublisher;
527   }
528 
529   /***
530    * <li>Rss 1.0 - &lt;dc:publisher> An entity responsible for making the resource available
531    * </li>
532    * <li>Rss 2.0 - &lt;managingEditor> Email address for person responsible for editorial content.
533    * </li>
534    * <li>Atom 1.0 - &lt;author> 
535    * The "atom:author" element is a Person construct that indicates the author of the entry or feed.
536    * </li>
537    * <br/>
538    * Note: This is a list because Atom 1.0 allows multiple &lt;author>. For Rss 1.0 and Rss 2.0,
539    * only the first {@link Person} is interpreted, the rest are ignored.
540    * @param managingEditorOrAuthorOrPublisher
541    * @return
542    */
543   public ChannelFeed setManagingEditorOrAuthorOrPublisher(
544       List<Person> managingEditorOrAuthorOrPublisher) {
545     _managingEditorOrAuthorOrPublisher = managingEditorOrAuthorOrPublisher;
546     return this;
547   }
548 
549   /***
550    * <li>Rss 1.0 - &lt;dc:publisher> An entity responsible for making the resource available
551    * </li>
552    * <li>Rss 2.0 - &lt;managingEditor> Email address for person responsible for editorial content.
553    * </li>
554    * <li>Atom 1.0 - &lt;author> 
555    * The "atom:author" element is a Person construct that indicates the author of the entry or feed.
556    * </li>
557    * <br/>
558    * Note: This is a list because Atom 1.0 allows multiple &lt;author>. For Rss 1.0 and Rss 2.0,
559    * only the first {@link Person} is interpreted, the rest are ignored.
560    * <br/>
561    * This method constructs a new {@link Person} object with input email as its email and adds it to the end
562    * of the list.
563    * @param managingEditorOrAuthorOrPublisher
564    * @return
565    */
566   public ChannelFeed addManagingEditorOrAuthorOrPublisher(
567       String... emails) {
568     if(ArrayUtils.isEmpty(emails)){
569       LOG.warn("Empty email array is ignored");
570       return this;
571     }
572     if(_managingEditorOrAuthorOrPublisher == null){
573       _managingEditorOrAuthorOrPublisher = new ArrayList<Person>();
574     }
575     for(String s :emails){
576       _managingEditorOrAuthorOrPublisher.add(new Person(s));
577     }
578     return this;
579   }
580   
581   /***
582    * <li>Rss 1.0 - &lt;dc:publisher> An entity responsible for making the resource available
583    * </li>
584    * <li>Rss 2.0 - &lt;managingEditor> Email address for person responsible for editorial content.
585    * </li>
586    * <li>Atom 1.0 - &lt;author> 
587    * The "atom:author" element is a Person construct that indicates the author of the entry or feed.
588    * </li>
589    * <br/>
590    * Note: This is a list because Atom 1.0 allows multiple &lt;author>. For Rss 1.0 and Rss 2.0,
591    * only the first {@link Person} is interpreted, the rest are ignored.
592    * <br/>
593    * This method adds all input {@link Person} to the END of the list.
594    * @param managingEditorOrAuthorOrPublisher
595    * @return
596    */
597   public ChannelFeed addManagingEditorOrAuthorOrPublisher(
598       Person... persons) {
599     if(ArrayUtils.isEmpty(persons)){
600       LOG.warn("Empty email array is ignored");
601       return this;
602     }
603     if(_managingEditorOrAuthorOrPublisher == null){
604       _managingEditorOrAuthorOrPublisher = new ArrayList<Person>();
605     }
606     for(Person p : persons){
607       _managingEditorOrAuthorOrPublisher.add(p);
608     }
609     return this;
610   }
611   
612   /***
613    * <li>Rss 1.0 - &lt;dc:creator> An entity primarily responsible for making the content of
614    * the resource.
615    * </li>
616    * <li>Rss 2.0 - &lt;webMaster> Email address for person responsible for technical issues relating to channel.
617    * </li>
618    * <li>Atom 1.0 - Not supported, this field is ignored.
619    * </li>
620    * 
621    * <br/>
622    * Notes: according to Rss 2.0 specs, there can be only 1 &lt;webMaster> element under &lt;channel>,
623    * therefore, only the first {@link Person} is interpreted, the rest are ignored.  
624    * @return
625    */
626   public List<Person> getWebMasterOrCreator() {
627     return _webMasterOrCreator;
628   }
629 
630   /***
631    * <li>Rss 1.0 - &lt;dc:creator> An entity primarily responsible for making the content of
632    * the resource.
633    * </li>
634    * <li>Rss 2.0 - &lt;webMaster> Email address for person responsible for technical issues relating to channel.
635    * </li>
636    * <li>Atom 1.0 - Not supported, this field is ignored.
637    * </li>
638    * 
639    * <br/>
640    * Notes: according to Rss 2.0 specs, there can be only 1 &lt;webMaster> element under &lt;channel>,
641    * therefore, only the first {@link Person} is interpreted, the rest are ignored.
642    * @param webMasterOrCreator
643    * @return
644    */
645   public ChannelFeed setWebMasterOrCreator(List<Person> webMasterOrCreator) {
646     _webMasterOrCreator = webMasterOrCreator;
647     return this;
648   }
649 
650 
651   /***
652    * <li>Rss 1.0 - &lt;dc:creator> An entity primarily responsible for making the content of
653    * the resource.
654    * </li>
655    * <li>Rss 2.0 - &lt;webMaster> Email address for person responsible for technical issues relating to channel.
656    * </li>
657    * <li>Atom 1.0 - Not supported, this field is ignored.
658    * </li>
659    * <br/>
660    * This method adds all the input {@link Person} to the END of the list.
661    * <br/>
662    * Notes: according to Rss 2.0 specs, there can be only 1 &lt;webMaster> element under &lt;channel>,
663    * therefore, only the first {@link Person} is interpreted, the rest are ignored.
664    * @param webMasterOrCreator
665    * @return
666    */
667   public ChannelFeed addWebMasterOrCreator(Person... webMasterOrCreator) {
668     if(ArrayUtils.isEmpty(webMasterOrCreator)){
669       LOG.warn("empty person array is ignored");
670       return this;
671     }
672     if(_webMasterOrCreator == null){
673       _webMasterOrCreator = new ArrayList<Person>();
674     }
675     for(Person p : webMasterOrCreator){
676       _webMasterOrCreator.add(p);
677     }
678     return this;
679   }
680   
681   /***
682    * <li>Rss 1.0 - &lt;dc:creator> An entity primarily responsible for making the content of
683    * the resource.
684    * </li>
685    * <li>Rss 2.0 - &lt;webMaster> Email address for person responsible for technical issues relating to channel.
686    * </li>
687    * <li>Atom 1.0 - Not supported, this field is ignored.
688    * </li>
689    * <br/>
690    * This method constructs new {@link Person} object and adds them all to the END of the list.
691    * <br/>
692    * Notes: according to Rss 2.0 specs, there can be only 1 &lt;webMaster> element under &lt;channel>,
693    * therefore, only the first {@link Person} is interpreted, the rest are ignored.
694    * @param emailOrText
695    * @return
696    */
697   public ChannelFeed addWebMasterOrCreator(String... emailOrText) {
698     if(ArrayUtils.isEmpty(emailOrText)){
699       LOG.warn("empty array is ignored");
700       return this;
701     }
702     if(_webMasterOrCreator == null){
703       _webMasterOrCreator = new ArrayList<Person>();
704     }
705     for(String e : emailOrText){
706       _webMasterOrCreator.add(new Person(e));
707     }
708     return this;
709   }
710   
711   /***
712    * <li>Rss 1.0 - &lt;dc:creator> An entity responsible for making contributions to the content of the resource.
713    * </li>
714    * <li>Rss 2.0 - Not supported, this field is ignored.
715    * </li>
716    * <li>Atom 1.0 - &lt;contributor> 
717    * The "atom:contributor" element is a Person construct that indicates a person or other entity who contributed to the entry or feed.
718    * </li>
719    * 
720    * @return
721    */
722   public List<Person> getContributors() {
723     return _contributors;
724   }
725 
726 
727   /***
728    * <li>Rss 1.0 - &lt;dc:creator> An entity responsible for making contributions to the content of the resource.
729    * </li>
730    * <li>Rss 2.0 - Not supported, this field is ignored.
731    * </li>
732    * <li>Atom 1.0 - &lt;contributor> 
733    * The "atom:contributor" element is a Person construct that indicates a person or other entity who contributed to the entry or feed.
734    * </li>
735    * @param contributors
736    * @return
737    */
738   public ChannelFeed setContributors(List<Person> contributors) {
739     _contributors = contributors;
740     return this;
741   }
742 
743   /***
744    * <li>Rss 1.0 - &lt;dc:creator> An entity responsible for making contributions to the content of the resource.
745    * </li>
746    * <li>Rss 2.0 - Not supported, this field is ignored.
747    * </li>
748    * <li>Atom 1.0 - &lt;contributor> 
749    * The "atom:contributor" element is a Person construct that indicates a person or other entity who contributed to the entry or feed.
750    * </li>
751    * <br/>
752    * This method adds all the input {@link Person} to the END of the list.
753    * 
754    * @param contributor
755    * @return
756    */
757   public ChannelFeed addContributor(Person... contributor) {
758     if(ArrayUtils.isEmpty(contributor)){
759       LOG.warn("empty person array is ignored");
760       return this;
761     }
762     if(_contributors == null){
763       _contributors = new ArrayList<Person>();
764     }
765     for(Person p : contributor){
766       _contributors.add(p);
767     }
768     return this;
769   }
770   
771   /***
772    * <li>Rss 1.0 - &lt;dc:creator> An entity responsible for making contributions to the content of the resource.
773    * </li>
774    * <li>Rss 2.0 - Not supported, this field is ignored.
775    * </li>
776    * <li>Atom 1.0 - &lt;contributor> 
777    * The "atom:contributor" element is a Person construct that indicates a person or other entity who contributed to the entry or feed.
778    * </li>
779    * <br/>
780    * This method constructs new {@link Person} object and adds them all to the END of the list.
781    * @return
782    */
783   public ChannelFeed addContributor(String... emailOrText) {
784     if(ArrayUtils.isEmpty(emailOrText)){
785       LOG.warn("empty array is ignored");
786       return this;
787     }
788     if(_contributors == null){
789       _contributors = new ArrayList<Person>();
790     }
791     for(String e : emailOrText){
792       _contributors.add(new Person(e));
793     }
794     return this;
795   }
796   
797   /***
798    * <li>Rss 1.0 - &lt;dc:subject> The topic of the content of the resource.
799    * </li>
800    * <li>Rss 2.0 - Includes the item in one or more categories.
801    * </li>
802    * <li>Atom 1.0 - The "atom:category" element conveys information about a category 
803    * associated with an entry or feed. This specification assigns no meaning to the content (if any) of this element.
804    * </li>
805    * @return
806    */
807   public Set<CategorySubject> getCategorySubjects() {
808     return _categorySubjects;
809   }
810 
811 
812   /***
813    * <li>Rss 1.0 - &lt;dc:subject> The topic of the content of the resource.
814    * </li>
815    * <li>Rss 2.0 - Includes the item in one or more categories.
816    * </li>
817    * <li>Atom 1.0 - The "atom:category" element conveys information about a category 
818    * associated with an entry or feed. This specification assigns no meaning to the content (if any) of this element.
819    * </li>
820    * @param categorySubjects
821    * @return
822    */
823   public ChannelFeed setCategorySubjects(Set<CategorySubject> categorySubjects) {
824     _categorySubjects = categorySubjects;
825     return this;
826   }
827 
828   /***
829    * <li>Rss 1.0 - &lt;dc:subject> The topic of the content of the resource.
830    * </li>
831    * <li>Rss 2.0 - Includes the item in one or more categories.
832    * </li>
833    * <li>Atom 1.0 - The "atom:category" element conveys information about a category 
834    * associated with an entry or feed. This specification assigns no meaning to the content (if any) of this element.
835    * </li>
836    * 
837    * <br/>
838    * This method creates new {@link CategorySubject} objects using the input strings and add them to the category set.
839    * @param categorySubjectOrTerm
840    * @return
841    */
842   public ChannelFeed addCategorySubject(String... categorySubjectOrTerm) {
843     if(ArrayUtils.isEmpty(categorySubjectOrTerm)){
844       LOG.warn("Empty category array is ignored");
845       return this;
846     }
847     if(_categorySubjects == null){
848       _categorySubjects = new HashSet<CategorySubject>();
849     }
850     for(String c : categorySubjectOrTerm){
851       _categorySubjects.add(new CategorySubject(c));
852     }
853     
854     return this;
855   }
856 
857   /***
858    * <li>Rss 1.0 - &lt;dc:subject> The topic of the content of the resource.
859    * </li>
860    * <li>Rss 2.0 - Includes the item in one or more categories.
861    * </li>
862    * <li>Atom 1.0 - The "atom:category" element conveys information about a category 
863    * associated with an entry or feed. This specification assigns no meaning to the content (if any) of this element.
864    * </li>
865    * 
866    * <br/>
867    * This method adds the input {@link CategorySubject} objects to the category set.
868    * @param categorySubject
869    * @return
870    */
871   public ChannelFeed addCategorySubject(CategorySubject... categorySubject) {
872     if(ArrayUtils.isEmpty(categorySubject)){
873       LOG.warn("Empty category array is ignored");
874       return this;
875     }
876     
877     if(_categorySubjects == null){
878       _categorySubjects = new HashSet<CategorySubject>();
879     }
880     for(CategorySubject s : categorySubject){
881       _categorySubjects.add(s);
882     }
883     return this;
884   }
885 
886 
887   /***
888    * <li>Rss 1.0 - &lt;dc:date>  A date associated with an event in the life cycle of the resource.
889    * </li>
890    * <li>Rss 2.0 - &lt;pubDate> Indicates when the item was published. 
891    * </li>
892    * <li>Atom 1.0 - Not supported, this field is ignored.
893    * </li>
894    * @return
895    */
896   public String getPubDate() {
897     return _pubDate;
898   }
899 
900 
901   /***
902    * <li>Rss 1.0 - &lt;dc:date>  A date associated with an event in the life cycle of the resource.
903    * </li>
904    * <li>Rss 2.0 - &lt;pubDate> Indicates when the item was published. 
905    * </li>
906    * <li>Atom 1.0 - Not supported, this field is ignored.
907    * </li>
908    * @param pubDate
909    * @return
910    */
911   public ChannelFeed setPubDate(String pubDate) {
912     _pubDate = pubDate;
913     return this;
914   }
915   
916   /***
917    * <li>Rss 1.0 - &lt;dc:date>  A date associated with an event in the life cycle of the resource.
918    * </li>
919    * <li>Rss 2.0 - &lt;pubDate> Indicates when the item was published. 
920    * </li>
921    * <li>Atom 1.0 - Not supported, this field is ignored.
922    * </li>
923    * 
924    * <br/>
925    * This method uses the input {@link SimpleDateFormat} object to format the date into a string.
926    * @param pubDate
927    * @param format
928    * @return
929    */
930   public ChannelFeed setPubDate(Date pubDate, SimpleDateFormat format){
931     _pubDate = format.format(pubDate);
932     return this;
933   }
934 
935 
936   /***
937    * <li>Rss 1.0 - Not supported, this field is ignored.
938    * </li>
939    * <li>Rss 2.0 - &lt;lastBuildDate> The last time the content of the channel changed. 
940    * </li>
941    * <li>Atom 1.0 - &lt;updated> The "atom:updated" element is a Date construct indicating the most recent 
942    * instant in time when an entry or feed was modified in a way the publisher considers significant. 
943    * Therefore, not all modifications necessarily result in a changed atom:updated value.
944    * </li>
945    * 
946    * @return
947    */
948   public String getLastBuildOrUpdatedDate() {
949     return _lastBuildOrUpdatedDate;
950   }
951 
952 
953   /***
954    * <li>Rss 1.0 - Not supported, this field is ignored.
955    * </li>
956    * <li>Rss 2.0 - &lt;lastBuildDate> The last time the content of the channel changed. 
957    * </li>
958    * <li>Atom 1.0 - &lt;updated> The "atom:updated" element is a Date construct indicating the most recent 
959    * instant in time when an entry or feed was modified in a way the publisher considers significant. 
960    * Therefore, not all modifications necessarily result in a changed atom:updated value.
961    * </li>
962    * 
963    * @param lastBuildOrUpdatedDate
964    * @return
965    */
966   public ChannelFeed setLastBuildOrUpdatedDate(String lastBuildOrUpdatedDate) {
967     _lastBuildOrUpdatedDate = lastBuildOrUpdatedDate;
968     return this;
969   }
970 
971   /***
972    * <li>Rss 1.0 - Not supported, this field is ignored.
973    * </li>
974    * <li>Rss 2.0 - &lt;lastBuildDate> The last time the content of the channel changed. 
975    * </li>
976    * <li>Atom 1.0 - &lt;updated> The "atom:updated" element is a Date construct indicating the most recent 
977    * instant in time when an entry or feed was modified in a way the publisher considers significant. 
978    * Therefore, not all modifications necessarily result in a changed atom:updated value.
979    * </li>
980    * <br/>
981    * This method uses the input {@link SimpleDateFormat} object to format the date into a string.
982    * @param lastBuildOrUpdatedDate
983    * @return
984    */
985   public ChannelFeed setLastBuildOrUpdatedDate(Date lastBuildOrUpdatedDate, SimpleDateFormat format) {
986     return setLastBuildOrUpdatedDate(format.format(lastBuildOrUpdatedDate));
987   }
988   
989   
990   /***
991    * <li>Rss 1.0 - Not supported, this field is ignored.
992    * </li>
993    * <li>Rss 2.0 - Not supported, this field is ignored.
994    * </li>
995    * <li>Atom 1.0 - The "atom:id" element conveys a permanent, universally unique identifier for an entry or feed.
996    * </li>
997    * @return
998    */
999   public Id getUid() {
1000     return _uid;
1001   }
1002 
1003   /***
1004    * <li>Rss 1.0 - Not supported, this field is ignored.
1005    * </li>
1006    * <li>Rss 2.0 - Not supported, this field is ignored.
1007    * </li>
1008    * <li>Atom 1.0 - The "atom:id" element conveys a permanent, universally unique identifier for an entry or feed.
1009    * </li>
1010    * @param uid
1011    * @return
1012    */
1013   public ChannelFeed setUid(Id uid) {
1014     _uid = uid;
1015     return this;
1016   }
1017 
1018   /***
1019    * <li>Rss 1.0 - Not supported, this field is ignored.
1020    * </li>
1021    * <li>Rss 2.0 - Not supported, this field is ignored.
1022    * </li>
1023    * <li>Atom 1.0 - The "atom:id" element conveys a permanent, universally unique identifier for an entry or feed.
1024    * </li>
1025    * <br/>
1026    * This method constructs a new {@link Id} object and sets the <code>uid</code> field to this object.
1027    * @param uid
1028    * @return
1029    */
1030   public ChannelFeed setUid(String uid){
1031     if(_uid == null){
1032       _uid = null;
1033       return this;
1034     }
1035     _uid = new Id(uid);
1036     return this;
1037   }
1038 
1039 
1040   /***
1041    * <li>Rss 1.0 - Not supported, this is ignored.</li>
1042    * <li>Rss 2.0 - &lt;generator> A string indicating the program used to generate the channel.  
1043    * </li>
1044    * <li>Atom 1.0 - &lt;generator> 
1045    * The "atom:generator" element's content identifies the agent used to generate a feed, for debugging and other purposes.
1046    * </li>
1047    * @return
1048    */
1049   public Generator getGenerator() {
1050     return _generator;
1051   }
1052 
1053   /***
1054    * <li>Rss 1.0 - Not supported, this is ignored.</li>
1055    * <li>Rss 2.0 - &lt;generator> A string indicating the program used to generate the channel.  
1056    * </li>
1057    * <li>Atom 1.0 - &lt;generator> 
1058    * The "atom:generator" element's content identifies the agent used to generate a feed, for debugging and other purposes.
1059    * </li>
1060    * @param generator
1061    * @return
1062    */
1063   public ChannelFeed setGenerator(Generator generator) {
1064     _generator = generator;
1065     return this;
1066   }
1067 
1068   /***
1069    * <li>Rss 1.0 - Not supported, this is ignored.</li>
1070    * <li>Rss 2.0 - &lt;generator> A string indicating the program used to generate the channel.  
1071    * </li>
1072    * <li>Atom 1.0 - &lt;generator> 
1073    * The "atom:generator" element's content identifies the agent used to generate a feed, for debugging and other purposes.
1074    * </li>
1075    * <br/>
1076    * This method constructs a new {@link Generator} object.
1077    * @param generatorValue
1078    * @return
1079    */
1080   public ChannelFeed setGenerator(String generatorValue) {
1081     _generator = generatorValue == null?null: new Generator(generatorValue);
1082     return this;
1083   }
1084   
1085   /***
1086    * <b>Rss 2.0 only</b><br/>
1087    * A URL that points to the documentation for the format used in the RSS file. 
1088    * It's probably a pointer to this page. It's for people who might stumble 
1089    * across an RSS file on a Web server 25 years from now and wonder what it is.
1090    * @return
1091    */
1092   public String getDocs() {
1093     return _docs;
1094   }
1095 
1096 
1097   /***
1098    * <b>Rss 2.0 only</b><br/>
1099    * A URL that points to the documentation for the format used in the RSS file. 
1100    * It's probably a pointer to this page. It's for people who might stumble 
1101    * across an RSS file on a Web server 25 years from now and wonder what it is.
1102    * @param docs
1103    * @return
1104    */
1105   public ChannelFeed setDocs(String docs) {
1106     _docs = docs;
1107     return this;
1108   }
1109 
1110   /***
1111    * <li>Rss 1.0 - This value is parsed from both the 
1112    * &lt;sy:updatePeriod> and  &lt;sy:updateFrequency> <br/>
1113    * for example: updatePeriod:hourly and updateFrequency:2 = ttl: 30 minutes
1114    * </li>
1115    * <li>Rss 2.0 - ttl stands for time to live. It's a number of minutes that 
1116    * indicates how long a channel can be cached before refreshing from the source.
1117    * </li>
1118    * <li>Atom 1.0 - Not supported, this field is ignored.</li>
1119    * @return
1120    */
1121   public Integer getTtl() {
1122     return _ttl;
1123   }
1124 
1125   /***
1126    * <li>Rss 1.0 - This value is parsed from both the 
1127    * &lt;sy:updatePeriod> and  &lt;sy:updateFrequency> <br/>
1128    * for example: updatePeriod:hourly and updateFrequency:2 = ttl: 30 minutes
1129    * </li>
1130    * <li>Rss 2.0 - ttl stands for time to live. It's a number of minutes that 
1131    * indicates how long a channel can be cached before refreshing from the source.
1132    * </li>
1133    * <li>Atom 1.0 - Not supported, this field is ignored.</li>
1134    * @param ttl
1135    * @return
1136    */
1137   public ChannelFeed setTtl(Integer ttl) {
1138     _ttl = ttl;
1139     return this;
1140   }
1141 
1142 
1143   /***
1144    * <b>Rss 2.0 only</b><br/>
1145    * Allows processes to register with a cloud to be notified of updates to the 
1146    * channel, implementing a lightweight publish-subscribe protocol for RSS feeds.
1147    * @return
1148    */
1149   public Cloud getCloud() {
1150     return _cloud;
1151   }
1152 
1153 
1154   /***
1155    * <b>Rss 2.0 only</b><br/>
1156    * Allows processes to register with a cloud to be notified of updates to the 
1157    * channel, implementing a lightweight publish-subscribe protocol for RSS feeds.
1158    * @param cloud
1159    * @return
1160    */
1161   public ChannelFeed setCloud(Cloud cloud) {
1162     _cloud = cloud;
1163     return this;
1164   }
1165 
1166   /***
1167    * <li>Rss 1.0 - &lt;image> 
1168    * Establishes an RDF association between the optional image element [5.4] and this particular RSS channel. The rdf:resource's {image_uri} must be the same as the image element's rdf:about {image_uri}.
1169    * </li>
1170    * <li> Rss 2.0 - &lt;image>
1171    * Specifies a GIF, JPEG or PNG image that can be displayed with the channel. </li>
1172    * <li>Atom 1.0 - &lt;icon>
1173    * The "atom:icon" element's content is an IRI reference [RFC3987] which identifies 
1174    * an image which provides iconic visual identification for a feed.
1175    * </li>
1176    * @return
1177    */
1178   public Image getImageOrIcon() {
1179     return _imageOrIcon;
1180   }
1181 
1182   /***
1183    * <li>Rss 1.0 - &lt;image> 
1184    * Establishes an RDF association between the optional image element [5.4] and this particular RSS channel. The rdf:resource's {image_uri} must be the same as the image element's rdf:about {image_uri}.
1185    * </li>
1186    * <li> Rss 2.0 - &lt;image>
1187    * Specifies a GIF, JPEG or PNG image that can be displayed with the channel. </li>
1188    * <li>Atom 1.0 - &lt;icon>
1189    * The "atom:icon" element's content is an IRI reference [RFC3987] which identifies 
1190    * an image which provides iconic visual identification for a feed.
1191    * </li>
1192    * @param imageOrIcon
1193    * @return
1194    */
1195   public ChannelFeed setImageOrIcon(Image imageOrIcon) {
1196     _imageOrIcon = imageOrIcon;
1197     return this;
1198   }
1199 
1200 
1201   /***
1202    * <b>Atom 1.0 only </b><br/>
1203    * The "atom:logo" element's content is an IRI reference [RFC3987] which identifies an image which provides visual identification for a feed.
1204    * @return
1205    */
1206   public Image getLogo() {
1207     return _logo;
1208   }
1209 
1210 
1211   /***
1212    * <b>Atom 1.0 only </b><br/>
1213    * The "atom:logo" element's content is an IRI reference [RFC3987] which identifies an image which provides visual identification for a feed.
1214    * @param logo
1215    * @return
1216    */
1217   public ChannelFeed setLogo(Image logo) {
1218     _logo = logo;
1219     return this;
1220   }
1221 
1222 
1223   /***
1224    * <b>Rss 1.0 and Rss 2.0 only </b><br/>
1225    * <li>Rss 1.0 - Establishes an RDF association between the optional textinput element [5.6] and this particular RSS channel. The {textinput_uri} rdf:resource must be the same as the textinput element's rdf:about {textinput_uri}.
1226    * </li>
1227    * <li>Rss 2.0 - Specifies a text input box that can be displayed with the channel. </li>
1228    * @return
1229    */
1230   public TextInput getTexInput() {
1231     return _texInput;
1232   }
1233 
1234 
1235   /***
1236    * <b>Rss 1.0 and Rss 2.0 only </b><br/>
1237    * <li>Rss 1.0 - Establishes an RDF association between the optional textinput element [5.6] and this particular RSS channel. The {textinput_uri} rdf:resource must be the same as the textinput element's rdf:about {textinput_uri}.
1238    * </li>
1239    * <li>Rss 2.0 - Specifies a text input box that can be displayed with the channel. </li>
1240    * @param texInput
1241    * @return
1242    */
1243   public ChannelFeed setTexInput(TextInput texInput) {
1244     _texInput = texInput;
1245     return this;
1246   }
1247 
1248    /***
1249     * <b>Rss 2.0 only</b><br/>
1250     * An XML element that contains up to 24 <hour> sub-elements whose value is a number between 0 and 23, representing a time in GMT, when aggregators, if they support the feature, may not read the channel on hours listed in the skipHours element.
1251     * <br/>
1252     * The hour beginning at midnight is hour zero.
1253     */
1254    public Set<Integer> getSkipHours() {
1255      return _skipHours;
1256    }
1257    /***
1258     * <b>Rss 2.0 only</b><br/>
1259     * An XML element that contains up to 24 <hour> sub-elements whose value is a number between 0 and 23, representing a time in GMT, when aggregators, if they support the feature, may not read the channel on hours listed in the skipHours element.
1260     * <br/>
1261     * The hour beginning at midnight is hour zero.
1262     */
1263    public ChannelFeed setSkipHours(Set<Integer> skipHours) {
1264      for(Integer i : skipHours){
1265        if(i == null || i <0 || i >23){
1266          throw new IllegalArgumentException("all skip hour must be a value that is a number between 0 and 23");
1267        }
1268      }
1269      _skipHours = skipHours;
1270      return this;
1271    }
1272  
1273    /***
1274     * <b>Rss 2.0 only</b><br/>
1275     * Add a skip hour to the feed;
1276     * @param hour value is a number between 0 and 23, representing a time in GMT, when aggregators, if they support the feature, may not read the channel on hours listed in the skipHours element.
1277     * <br/>
1278     * The hour beginning at midnight is hour zero.
1279     */
1280    public ChannelFeed addSkipHour(int... hour){
1281      if(!ArrayUtils.isEmpty(hour)){
1282        for(int h : hour){
1283          if(h <0 || h >23){
1284            throw new IllegalArgumentException("all skip hour must be a value that is a number between 0 and 23");
1285          }
1286          if(_skipHours == null){
1287            _skipHours = new HashSet<Integer>();
1288          }
1289          _skipHours.add(h);
1290        }
1291      }
1292      return this;
1293    }
1294  
1295    /***
1296     * <b>Rss 2.0 only</b><br/>
1297     * value is Monday, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday. Aggregators may not read the channel during days listed in the skipDays element.
1298     */
1299    public Set<Day> getSkipDays() {
1300      return _skipDays;
1301    }
1302    /***
1303     * <b>Rss 2.0 only</b><br/>
1304     * value is Monday, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday. Aggregators may not read the channel during days listed in the skipDays element.
1305     */
1306    public ChannelFeed setSkipDays(Set<Day> skipDays) {
1307      _skipDays = skipDays;
1308      return this;
1309    }
1310  
1311    /***
1312     * <b>Rss 2.0 only</b><br/>
1313     * Add a skip day.
1314     */
1315    public ChannelFeed addSkipDay(Day... day){
1316      if(!ArrayUtils.isEmpty(day)){
1317        if(_skipDays == null){
1318          _skipDays = new HashSet<Day>();
1319        }
1320        _skipDays.addAll(Arrays.asList(day));
1321      }
1322  
1323      return this;
1324    }
1325 
1326 
1327   ////////////////////////Common setters///////////////////////
1328    /***
1329     * Any other attribute that is not in the RSS 2.0 specs.
1330     */
1331    public ChannelFeed setOtherAttributes(Map<QName, String> otherAttributes) {
1332      _otherAttributes = otherAttributes;
1333      return this;
1334    }
1335    /***
1336     * Add an attribute that is not in the RSS 2.0 specs.
1337     */
1338    public ChannelFeed addOtherAttributes(QName namespace, String attribute) {
1339      if(_otherAttributes == null){
1340        _otherAttributes = new HashMap<QName, String>();
1341      }
1342      _otherAttributes.put(namespace, attribute);
1343      return this;
1344    }
1345    
1346    /***
1347     * Other additional elements that are not in the Rss specs.<br/>
1348     * **Note** The element should not have an empty namespace to avoid collision with the specs elements.
1349     */
1350    public ChannelFeed setOtherElements(List<Element> otherElements) {
1351      _otherElements = otherElements;
1352      return this;
1353    }
1354    /***
1355     * Add an element that is not specified in the Rss specs.<br/>
1356     * **Note** The element should not have an empty namespace to avoid collision with the specs elements.
1357     * @param element - any element
1358     */
1359    public ChannelFeed addOtherElement(Element element){
1360      if(_otherElements == null){
1361        _otherElements = new ArrayList<Element>();
1362      }
1363      _otherElements.add(element);
1364      return this;
1365    }
1366    
1367    /***
1368     * Add an element that is not specified in the Rss specs.<br/>
1369     * **Note** The element should not have an empty namespace to avoid collision with the specs elements.
1370     * 
1371     * @param xmlString - any element
1372     * @throws ParserConfigurationException 
1373     * @throws IOException 
1374     * @throws SAXException 
1375     */
1376    public ChannelFeed addOtherElement(String xmlString) throws SAXException, IOException, ParserConfigurationException{
1377      return addOtherElement(XMLUtils.parseXml(xmlString, false, false).getDocumentElement());
1378    }
1379    
1380 
1381    /***
1382     * <b>Atom 1.0 only</b><br/>
1383     * Any element defined by this specification MAY have an xml:base attribute 
1384     * [W3C.REC-xmlbase-20010627]. When xml:base is used in an Atom Document, 
1385     * it serves the function described in section 5.1.1 of [RFC3986], establishing 
1386     * the base URI (or IRI) for resolving any relative references found within the 
1387     * effective scope of the xml:base attribute.
1388     * @param base
1389     * @return
1390     */
1391    public ChannelFeed setBase(String base) {
1392      _base = base;
1393      return this;
1394    }
1395    /***
1396     * <li>Rss 2.0 - &lt;language> element. 
1397     * The language the channel is written in. This allows aggregators to group 
1398     * all Italian language sites, for example, on a single page. A list of allowable 
1399     * values for this element, as provided by Netscape, is here. You may also use values 
1400     * defined by the W3C.
1401     * Only &lt;channel> support this element.</li>
1402     * <li>Rss 1.0 - &lt;dc:language> element. A language of the intellectual content of the resource.
1403     * Only &lt;channel> and &lt;item> support this element. </li>
1404     * <li>Atom 1.0 - 'lang' attribute</li>
1405     * <br/>
1406     * Note: for Rss 2.0 and Rss 1.0, only &lt;channel> and &lt;item>
1407     * @param lang
1408     * @return
1409     */
1410    public ChannelFeed setLang(String lang) {
1411      _lang = lang;
1412      return this;
1413    }
1414    
1415    /***
1416     * <li>Rss 2.0 - &lt;language> element. 
1417     * The language the channel is written in. This allows aggregators to group 
1418     * all Italian language sites, for example, on a single page. A list of allowable 
1419     * values for this element, as provided by Netscape, is here. You may also use values 
1420     * defined by the W3C.
1421     * Only &lt;channel> support this element.</li>
1422     * <li>Rss 1.0 - &lt;dc:language> element. A language of the intellectual content of the resource.
1423     * Only &lt;channel> and &lt;item> support this element. </li>
1424     * <li>Atom 1.0 - 'lang' attribute</li>
1425     * <br/>
1426     * Note: for Rss 2.0 and Rss 1.0, only &lt;channel> and &lt;item>
1427     * @param lang
1428     * @return
1429     */
1430    public ChannelFeed setLang(Locale lang) {
1431      _lang = lang.getLanguage();
1432      return this;
1433    }
1434    /***
1435     * <b>Rss 1.0 only</b><br/>
1436     * @param resource
1437     * @return
1438     */
1439    public ChannelFeed setResource(String resource) {
1440      _resource = resource;
1441      return this;
1442    }
1443    /***
1444     * <b>Rss 1.0 only</b><br/>
1445     * @param about
1446     * @return
1447     */
1448    public ChannelFeed setAbout(String about) {
1449      _about = about;
1450      return this;
1451    }
1452    ////////////////////////Common setters///////////////////////
1453    
1454   @Override
1455   public void validate(FeedFormat format) throws ValidationException {
1456     if(CollectionUtils.isEmpty(_items)){
1457       throw new ValidationException("Channel: You should have at least 1 item");
1458     }
1459     
1460     for(ItemEntry item : _items){
1461       ValidationUtils.validateNotNull("Channel: All item should not be null", item);
1462       item.validate(format);
1463     }
1464     
1465     ValidationUtils.validateNotNull("Channel: Title, Link and Description should not be null", _title, _links, _descriptionOrSubtitle);
1466   
1467     _title.validate(format);
1468     _descriptionOrSubtitle.validate(format);
1469     
1470     for(Link l : _links){
1471       l.validate(format);
1472     }
1473     
1474     if(_categorySubjects != null){
1475       for(CategorySubject c: _categorySubjects){
1476         c.validate(format);
1477       }
1478     }
1479     if(_cloud != null){
1480       _cloud.validate(format);
1481     }
1482     if(_imageOrIcon != null){
1483       _imageOrIcon.validate(format);
1484     }
1485     if(_logo != null){
1486       _logo.validate(format);
1487     }
1488     if(_texInput != null){
1489       _texInput.validate(format);
1490     }    
1491     
1492     if(_uid != null){
1493       _uid.validate(format);
1494     }
1495     
1496     if(_generator != null){
1497       _generator.validate(format);
1498     }
1499     
1500     if(_contributors != null){
1501       for(Person p : _contributors){
1502         p.validate(format);
1503       }
1504     }
1505     
1506     if(_managingEditorOrAuthorOrPublisher != null){
1507       for(Person p : _managingEditorOrAuthorOrPublisher){
1508         p.validate(format);
1509       }
1510     }
1511     
1512     if(_webMasterOrCreator != null){
1513       for(Person p : _webMasterOrCreator){
1514         p.validate(format);
1515       }
1516     }
1517     
1518     if(_rights != null){
1519       _rights.validate(format);
1520     }
1521     
1522   }
1523   
1524 }