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.Date;
7   import java.util.HashMap;
8   import java.util.HashSet;
9   import java.util.List;
10  import java.util.Locale;
11  import java.util.Map;
12  import java.util.Set;
13  
14  import javax.xml.namespace.QName;
15  import javax.xml.parsers.ParserConfigurationException;
16  
17  import org.apache.commons.lang.ArrayUtils;
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  import org.w3c.dom.Element;
21  import org.xml.sax.SAXException;
22  
23  import yarfraw.utils.XMLUtils;
24  
25  /***
26   * 
27   * A channel may contain any number of {@link ItemEntry}s. 
28   * An item may represent a "story" -- much like a story in a newspaper or magazine; 
29   * if so its description is a synopsis of the story, and the link points to the full story. 
30   * An item may also be complete in itself, if so, the description contains the text 
31   * (entity-encoded HTML is allowed; see examples), 
32   * and the link and title may be omitted. 
33   * All elements of an item are optional, however at least one of title or description must be present.
34   * <p/>
35   * for Atom 1.0 format, the field also mapps to &lt;entry> element. 
36   * <br/>
37   * @author jliang
38   *
39   */
40  public class ItemEntry extends AbstractBaseObject{
41    private static final long serialVersionUID = 20070927L;
42    private static final Log LOG = LogFactory.getLog(ItemEntry.class);
43    private Text _title;
44    private List<Link> _links;
45    private Text _descriptionOrSummary;
46    private List<Person> _authorOrCreator;
47    private List<Person> _contributors;
48    private Set<CategorySubject> _categorySubjects;
49    private String _comments;
50    private Enclosure _enclosure;
51    private Id _uid;
52    private String _pubDate;
53    private String _updatedDate;
54    private Source _source;
55    private Text _rights;
56    private Content _content;
57    
58    public ItemEntry(){}
59    
60    /***
61     * <li>Rss 1.0 - The item's title.
62     * </li>
63     * <li>Rss 2.0 - The title of the item.
64     * </li>
65     * <li>Atom 1.0 -
66     * The "atom:title" element is a Text construct that conveys a human-readable title for an entry or feed.
67     * </li>
68     * @return
69     */
70    public Text getTitle() {
71      return _title;
72    }
73  
74    /***
75     * <li>Rss 1.0 - The item's title.
76     * </li>
77     * <li>Rss 2.0 - The title of the item.
78     * </li>
79     * <li>Atom 1.0 -
80     * The "atom:title" element is a Text construct that conveys a human-readable title for an entry or feed.
81     * </li>
82     * @param title
83     * @return
84     */
85    public ItemEntry setTitle(Text title) {
86      _title = title;
87      return this;
88    }
89    
90    /***
91     * <li>Rss 1.0 - The item's title.
92     * </li>
93     * <li>Rss 2.0 - The title of the item.
94     * </li>
95     * <li>Atom 1.0 -
96     * The "atom:title" element is a Text construct that conveys a human-readable title for an entry or feed.
97     * </li>
98     * <br/>
99     * This method creates a new {@link Text} object using the input string and sets title to this object. 
100    * @param title 
101    * @return
102    */
103   public ItemEntry setTitle(String title) {
104     return setTitle(new Text(title));
105   }
106 
107   /***
108    * <li>Rss 1.0 - The item's title.
109    * </li>
110    * <li>Rss 2.0 - The title of the item.
111    * </li>
112    * <li>Atom 1.0 -
113    * The "atom:title" element is a Text construct that conveys a human-readable title for an entry or feed.
114    * </li>
115    * <br/>
116    * Gets the text content of the title element.
117    * @return
118    */
119   public String getTitleText(){
120     return _title == null?null:_title.getText();
121   }
122   
123   /***
124    * <li>Rss 1.0 - The item's URL.
125    * </li>
126    * <li>Rss 2.0 - The URL of the item.
127    * </li>
128    * <li>Atom 1.0 - The "atom:link" element defines a reference from an entry or 
129    * feed to a Web resource. This specification assigns no meaning to the content (if any) of this element.
130    * </li>
131    * 
132    * <br/>
133    * <b>Only Atom 1.0 supports multiple link elements. Both Rss 1.0 and Rss 2.0 will only use the FIRST link in the list
134    * as the link element</b>
135    * @return
136    */
137   public List<Link> getLinks() {
138     return _links;
139   }
140   /***
141    * <li>Rss 1.0 - The item's URL.
142    * </li>
143    * <li>Rss 2.0 - The URL of the item.
144    * </li>
145    * <li>Atom 1.0 - The "atom:link" element defines a reference from an entry or 
146    * feed to a Web resource. This specification assigns no meaning to the content (if any) of this element.
147    * </li>
148    * 
149    * <br/>
150    * <b>Only Atom 1.0 supports multiple link elements. Both Rss 1.0 and Rss 2.0 will only use the FIRST link in the list
151    * as the link element</b>
152    * @param links
153    * @return
154    */
155   public ItemEntry setLinks(List<Link> links) {
156     _links = links;
157     return this;
158   }
159   
160   /***
161    * <li>Rss 1.0 - The item's URL.
162    * </li>
163    * <li>Rss 2.0 - The URL of the item.
164    * </li>
165    * <li>Atom 1.0 - The "atom:link" element defines a reference from an entry or 
166    * feed to a Web resource. This specification assigns no meaning to the content (if any) of this element.
167    * </li>
168    * 
169    * <br/>
170    * This method creates new {@link Link} objects and adds them to the END of the links list. 
171    * <br/>
172    * <b>Only Atom 1.0 supports multiple link elements. Both Rss 1.0 and Rss 2.0 will only use the FIRST link in the list
173    * as the link element</b>
174    * @param href
175    * @return
176    */
177   public ItemEntry addLink(String... href) {
178     if(ArrayUtils.isEmpty(href)){
179       LOG.warn("Empty href array is ignored");
180       return this;
181     }
182     if(_links == null){
183       _links = new ArrayList<Link>();
184     }
185     for (String s:href){
186       _links.add(new Link(s));
187     }
188     return this;
189   }
190 
191   /***
192    * <li>Rss 1.0 - The item's URL.
193    * </li>
194    * <li>Rss 2.0 - The URL of the item.
195    * </li>
196    * <li>Atom 1.0 - The "atom:link" element defines a reference from an entry or 
197    * feed to a Web resource. This specification assigns no meaning to the content (if any) of this element.
198    * </li>
199    * 
200    * <br/>
201    * This method adds input {@link Link} to the END of the links list. 
202    * <br/>
203    * <b>Only Atom 1.0 supports multiple link elements. Both Rss 1.0 and Rss 2.0 will only use the FIRST link in the list
204    * as the link element</b>
205    * @param link
206    * @return
207    */
208   public ItemEntry addLink(Link... link) {
209     if(ArrayUtils.isEmpty(link)){
210       LOG.warn("Empty link array is ignored");
211       return this;
212     }
213     if(_links == null){
214       _links = new ArrayList<Link>();
215     }
216     for(Link l : link){
217       _links.add(l);
218     }
219     return this;
220   }
221   /***
222    * <li>Rss 1.0 - A brief description/abstract of the item.
223    * </li>
224    * <li>Rss 2.0 -  The item synopsis.
225    * </li>
226    * <li>Atom 1.0 - The "atom:summary" element is a Text construct that conveys a short summary, abstract, or excerpt of an entry.
227    * </li>
228    * 
229    * <br/>
230    * Note: for Rss 1.0, this is mapped to the &lt;description> element, not the &lt;dc:description> element.
231    * @return
232    */
233   public Text getDescriptionOrSummary() {
234     return _descriptionOrSummary;
235   }
236 
237   /***
238    * <li>Rss 1.0 - A brief description/abstract of the item.
239    * </li>
240    * <li>Rss 2.0 -  The item synopsis.
241    * </li>
242    * <li>Atom 1.0 - The "atom:summary" element is a Text construct that conveys a short summary, abstract, or excerpt of an entry.
243    * </li>
244    * 
245    * @param descriptionOrSummary
246    * @return
247    */
248   public ItemEntry setDescriptionOrSummary(Text descriptionOrSummary) {
249     _descriptionOrSummary = descriptionOrSummary;
250     return this;
251   }
252   
253   /***
254    * <li>Rss 1.0 - A brief description/abstract of the item.
255    * </li>
256    * <li>Rss 2.0 -  The item synopsis.
257    * </li>
258    * <li>Atom 1.0 - The "atom:summary" element is a Text construct that conveys a short summary, abstract, or excerpt of an entry.
259    * </li>
260    * 
261    * <br/>
262    * This method creates a new {@link Text} object of type 'text' with the input string as its text content.
263    * @param descriptionOrSummary
264    * @return
265    */
266   public ItemEntry setDescriptionOrSummary(String descriptionOrSummary) {
267     if(descriptionOrSummary == null){
268       _descriptionOrSummary = null;
269       return this;
270     }
271     return setDescriptionOrSummary(new Text(descriptionOrSummary));
272   }
273   
274   /***
275    * <li>Rss 1.0 - A brief description/abstract of the item.
276    * </li>
277    * <li>Rss 2.0 -  The item synopsis.
278    * </li>
279    * <li>Atom 1.0 - The "atom:summary" element is a Text construct that conveys a short summary, abstract, or excerpt of an entry.
280    * </li>
281    * 
282    * <br/>
283    * This methods gets the text content of the <code>descriptionOrSummary</code> field on the current instance.
284    * @return
285    */
286   public String getDescriptionOrSummaryText() {
287     return _descriptionOrSummary == null?null:_descriptionOrSummary.getText();
288   }
289   
290   /***
291    * <li>Rss 1.0 - &lt;dc:creator> An entity primarily responsible for making the content of
292                the resource.
293    * </li>
294    * <li>Rss 2.0 - Email address of the author of the item.
295    * </li>
296    * <li>Atom 1.0 - The "atom:author" element is a Person construct that indicates the author of the entry or feed.
297    * </li>
298    * <br/>
299    * Note: only Rss 1.0 and Rss 2.0 only uses the email field of a {@link Person} object, all the other fields are ignored.
300    * 
301    * @return
302    */
303   public List<Person> getAuthorOrCreator() {
304     return _authorOrCreator;
305   }
306 
307   /***
308    * <li>Rss 1.0 - &lt;dc:creator> An entity primarily responsible for making the content of
309                the resource.
310    * </li>
311    * <li>Rss 2.0 - Email address of the author of the item.
312    * </li>
313    * <li>Atom 1.0 - The "atom:author" element is a Person construct that indicates the author of the entry or feed.
314    * </li>
315    * <br/>
316    * Note: only Rss 1.0 and Rss 2.0 only uses the email field of a {@link Person} object, all the other fields are ignored.
317    * @param author
318    * @return
319    */
320   public ItemEntry setAuthorOrCreator(List<Person> authorOrCreator) {
321     _authorOrCreator = authorOrCreator;
322     return this;
323   }
324 
325   /***
326    * <li>Rss 1.0 - &lt;dc:creator> An entity primarily responsible for making the content of
327                the resource.
328    * </li>
329    * <li>Rss 2.0 - Email address of the author of the item.
330    * </li>
331    * <li>Atom 1.0 - The "atom:author" element is a Person construct that indicates the author of the entry or feed.
332    * </li>
333    * <br/>
334    * This method constructs a new {@link Person} object using only the email address and 
335    * adds them to the END of the <code>authorOrCreator</code> list.
336    * <br/>
337    * Note: only Rss 1.0 and Rss 2.0 only uses the email field of a {@link Person} object, all the other fields are ignored.
338    * @param email
339    * @return
340    */
341   public ItemEntry addAuthorOrCreator(String... email) {
342     if(ArrayUtils.isEmpty(email)){
343       LOG.warn("Empty email array is ignored");
344       return this;
345     }
346     
347     if(_authorOrCreator == null){
348       _authorOrCreator = new ArrayList<Person>();
349     }
350     for(String e : email){
351       _authorOrCreator.add(new Person(e));      
352     }
353     return this;
354   }
355   /***
356    * <li>Rss 1.0 - &lt;dc:creator> An entity primarily responsible for making the content of
357                the resource.
358    * </li>
359    * <li>Rss 2.0 - Email address of the author of the item.
360    * </li>
361    * <li>Atom 1.0 - The "atom:author" element is a Person construct that indicates the author of the entry or feed.
362    * </li>
363    * <br/>
364    * This method constructs a new {@link Person} object using only the email address and 
365    * adds them to the END of the <code>authorOrCreator</code> list.
366    * <br/>
367    * Note: only Rss 1.0 and Rss 2.0 only uses the email field of a {@link Person} object, all the other fields are ignored.
368    * @param authorOrCreator
369    * @return
370    */
371   public ItemEntry addAuthorOrCreator(Person... authorOrCreator) {
372     if(ArrayUtils.isEmpty(authorOrCreator)){
373       LOG.warn("Empty author array is ignored");
374       return this;
375     }
376     
377     if(_authorOrCreator == null){
378       _authorOrCreator = new ArrayList<Person>();
379     }
380     for(Person p : authorOrCreator){
381       _authorOrCreator.add(p);
382     }
383     return this;
384   }
385   
386   
387   /***
388    * <li>Rss 1.0 - &lt;dc:contributor> An entity responsible for making contributions to the content of the resource.
389    * <br/><b>When this element is map to contributor in Rss 1.0, only the email address is used, other fields are ignored.</b>
390    * </li>
391    * <li>Rss 2.0 - Not supported, this list is ignored.
392    * </li>
393    * <li>Atom 1.0 - The "atom:contributor" element is a Person construct that indicates a person or other entity who contributed to the entry or feed.
394    * </li>
395    * @return
396    */
397   public List<Person> getContributors() {
398     return _contributors;
399   }
400 
401   /***
402    * <li>Rss 1.0 - &lt;dc:contributor> An entity responsible for making contributions to the content of the resource.
403    * <br/><b>When this element is map to contributor in Rss 1.0, only the email address is used, other fields are ignored.</b>
404    * </li>
405    * <li>Rss 2.0 - Not supported, this list is ignored.
406    * </li>
407    * <li>Atom 1.0 - The "atom:contributor" element is a Person construct that indicates a person or other entity who contributed to the entry or feed.
408    * </li>
409    * @param contributors
410    * @return
411    */
412   public ItemEntry setContributors(List<Person> contributors) {
413     _contributors = contributors;
414     return this;
415   }
416   
417   /***
418    * <li>Rss 1.0 - &lt;dc:contributor> An entity responsible for making contributions to the content of the resource.
419    * <br/><b>When this element is map to contributor in Rss 1.0, only the email address is used, other fields are ignored.</b>
420    * </li>
421    * <li>Rss 2.0 - Not supported, this list is ignored.
422    * </li>
423    * <li>Atom 1.0 - The "atom:contributor" element is a Person construct that indicates a person or other entity who contributed to the entry or feed.
424    * </li>
425    * 
426    * <br/>
427    * This method adds the input contributor to the END of the contributors list.
428    * @param contributor
429    * @return
430    */
431   public ItemEntry addContributor(Person... contributor){
432     if(ArrayUtils.isEmpty(contributor)){
433       LOG.warn("Empty contributor array is ignored");
434       return this;
435     }
436     
437     if(_contributors == null){
438       _contributors = new ArrayList<Person>();
439     }
440     for(Person p : contributor){
441       _contributors.add(p);
442     }
443     return this;
444   }
445 
446   /***
447    * <li>Rss 1.0 - &lt;dc:contributor> An entity responsible for making contributions to the content of the resource.
448    * <br/><b>When this element is map to contributor in Rss 1.0, only the email address is used, other fields are ignored.</b>
449    * </li>
450    * <li>Rss 2.0 - Not supported, this list is ignored.
451    * </li>
452    * <li>Atom 1.0 - The "atom:contributor" element is a Person construct that indicates a person or other entity who contributed to the entry or feed.
453    * </li>
454    * 
455    * <br/>
456    * This method adds the input contributor to the END of the contributors list.
457    * @param contributor
458    * @return
459    */
460   public ItemEntry addContributor(String... contributor){
461     if(ArrayUtils.isEmpty(contributor)){
462       LOG.warn("Empty contributor array is ignored");
463       return this;
464     }
465     
466     if(_contributors == null){
467       _contributors = new ArrayList<Person>();
468     }
469     for(String c : contributor){
470       _contributors.add(new Person(c));      
471     }
472     return this;
473   }
474   /***
475    * <li>Rss 1.0 - &lt;dc:subject> The topic of the content of the resource.
476    * </li>
477    * <li>Rss 2.0 - Includes the item in one or more categories.
478    * </li>
479    * <li>Atom 1.0 - The "atom:category" element conveys information about a category 
480    * associated with an entry or feed. This specification assigns no meaning to the content (if any) of this element.
481    * </li>
482    * @return
483    */
484   public Set<CategorySubject> getCategorySubjects() {
485     return _categorySubjects;
486   }
487 
488 
489   /***
490    * <li>Rss 1.0 - &lt;dc:subject> The topic of the content of the resource.
491    * </li>
492    * <li>Rss 2.0 - Includes the item in one or more categories.
493    * </li>
494    * <li>Atom 1.0 - The "atom:category" element conveys information about a category 
495    * associated with an entry or feed. This specification assigns no meaning to the content (if any) of this element.
496    * </li>
497    * @param categorySubjects
498    * @return
499    */
500   public ItemEntry setCategorySubjects(Set<CategorySubject> categorySubjects) {
501     _categorySubjects = categorySubjects;
502     return this;
503   }
504 
505   /***
506    * <li>Rss 1.0 - &lt;dc:subject> The topic of the content of the resource.
507    * </li>
508    * <li>Rss 2.0 - Includes the item in one or more categories.
509    * </li>
510    * <li>Atom 1.0 - The "atom:category" element conveys information about a category 
511    * associated with an entry or feed. This specification assigns no meaning to the content (if any) of this element.
512    * </li>
513    * 
514    * <br/>
515    * This method creates new {@link CategorySubject} objects using the input strings and add them to the category set.
516    * @param categorySubjectOrTerm
517    * @return
518    */
519   public ItemEntry addCategorySubject(String... categorySubjectOrTerm) {
520     if(ArrayUtils.isEmpty(categorySubjectOrTerm)){
521       LOG.warn("Empty category array is ignored");
522       return this;
523     }
524     if(_categorySubjects == null){
525       _categorySubjects = new HashSet<CategorySubject>();
526     }
527     for(String c : categorySubjectOrTerm){
528       _categorySubjects.add(new CategorySubject(c));
529     }
530     
531     return this;
532   }
533 
534   /***
535    * <li>Rss 1.0 - &lt;dc:subject> The topic of the content of the resource.
536    * </li>
537    * <li>Rss 2.0 - Includes the item in one or more categories.
538    * </li>
539    * <li>Atom 1.0 - The "atom:category" element conveys information about a category 
540    * associated with an entry or feed. This specification assigns no meaning to the content (if any) of this element.
541    * </li>
542    * 
543    * <br/>
544    * This method adds the input {@link CategorySubject} objects to the category set.
545    * @param categorySubject
546    * @return
547    */
548   public ItemEntry addCategorySubject(CategorySubject... categorySubject) {
549     if(ArrayUtils.isEmpty(categorySubject)){
550       LOG.warn("Empty category array is ignored");
551       return this;
552     }
553     
554     if(_categorySubjects == null){
555       _categorySubjects = new HashSet<CategorySubject>();
556     }
557     for(CategorySubject s : categorySubject){
558       _categorySubjects.add(s);
559     }
560     return this;
561   }
562   
563   /***
564    * <li>Rss 1.0 - Not supported, this field is ignored.
565    * </li>
566    * <li>Rss 2.0 - URL of a page for comments relating to the item.
567    * </li>
568    * <li>Atom 1.0 - Not supported, this is field is ignored.
569    * </li>
570    * @return
571    */
572   public String getComments() {
573     return _comments;
574   }
575 
576   /***
577    * <li>Rss 1.0 - Not supported, this field is ignored.
578    * </li>
579    * <li>Rss 2.0 - URL of a page for comments relating to the item.
580    * </li>
581    * <li>Atom 1.0 - Not supported, this is field is ignored.
582    * </li>
583    * @param comments
584    * @return
585    */
586   public ItemEntry setComments(String comments) {
587     _comments = comments;
588     return this;
589   }
590 
591   /***
592    * <li>Rss 1.0 - Not supported, this field is ignored.
593    * </li>
594    * <li>Rss 2.0 - Describes a media object that is attached to the item.
595    * </li>
596    * <li>Atom 1.0 - Not supported, this field is ignored.
597    * </li>
598    * @return
599    */
600   public Enclosure getEnclosure() {
601     return _enclosure;
602   }
603 
604   /***
605    * <li>Rss 1.0 - Not supported, this field is ignored.
606    * </li>
607    * <li>Rss 2.0 - Describes a media object that is attached to the item.
608    * </li>
609    * <li>Atom 1.0 - Not supported, this field is ignored.
610    * </li>
611    * @param enclosure
612    * @return
613    */
614   public ItemEntry setEnclosure(Enclosure enclosure) {
615     _enclosure = enclosure;
616     return this;
617   }
618 
619   /***
620    * <li>Rss 1.0 - Not supported, this field is ignored.
621    * </li>
622    * <li>Rss 2.0 - &lt;guid> A string that uniquely identifies the item.
623    * </li>
624    * <li>Atom 1.0 - The "atom:id" element conveys a permanent, universally unique identifier for an entry or feed.
625    * </li>
626    * @return
627    */
628   public Id getUid() {
629     return _uid;
630   }
631 
632   /***
633    * <li>Rss 1.0 - Not supported, this field is ignored.
634    * </li>
635    * <li>Rss 2.0 - &lt;guid> A string that uniquely identifies the item.
636    * </li>
637    * <li>Atom 1.0 - The "atom:id" element conveys a permanent, universally unique identifier for an entry or feed.
638    * </li>
639    * @param uid
640    * @return
641    */
642   public ItemEntry setUid(Id uid) {
643     _uid = uid;
644     return this;
645   }
646 
647   /***
648    * <li>Rss 1.0 - Not supported, this field is ignored.
649    * </li>
650    * <li>Rss 2.0 - &lt;guid> A string that uniquely identifies the item.
651    * </li>
652    * <li>Atom 1.0 - The "atom:id" element conveys a permanent, universally unique identifier for an entry or feed.
653    * </li>
654    * <br/>
655    * This method constructs a new {@link Id} object and sets the <code>uid</code> field to this object.
656    * @param uid
657    * @return
658    */
659   public ItemEntry setUid(String uid){
660     if(uid == null){
661       _uid = null;
662       return this;
663     }
664     return setUid(new Id(uid));
665   }
666 
667 
668   /***
669    * <li>Rss 1.0 - &lt;dc:date>  A date associated with an event in the life cycle of the resource.
670    * </li>
671    * <li>Rss 2.0 - &lt;pubDate> Indicates when the item was published. 
672    * </li>
673    * <li>Atom 1.0 - &lt;published> The "atom:published" element is a Date construct indicating an instant in time 
674    * associated with an event early in the life cycle of the entry.
675    * </li>
676    * @return
677    */
678   public String getPubDate() {
679     return _pubDate;
680   }
681 
682 
683   /***
684    * <li>Rss 1.0 - &lt;dc:date>  A date associated with an event in the life cycle of the resource.
685    * </li>
686    * <li>Rss 2.0 - &lt;pubDate> Indicates when the item was published. 
687    * </li>
688    * <li>Atom 1.0 - &lt;published> The "atom:published" element is a Date construct indicating an instant in time 
689    * associated with an event early in the life cycle of the entry.
690    * </li>
691    * @param pubDate
692    * @return
693    */
694   public ItemEntry setPubDate(String pubDate) {
695     _pubDate = pubDate;
696     return this;
697   }
698   
699   /***
700    * <li>Rss 1.0 - &lt;dc:date>  A date associated with an event in the life cycle of the resource.
701    * </li>
702    * <li>Rss 2.0 - &lt;pubDate> Indicates when the item was published. 
703    * </li>
704    * <li>Atom 1.0 - &lt;published> The "atom:published" element is a Date construct indicating an instant in time 
705    * associated with an event early in the life cycle of the entry.
706    * </li>
707    * 
708    * <br/>
709    * This method uses the input {@link SimpleDateFormat} object to format the date into a string.
710    * @param pubDate
711    * @param format
712    * @return
713    */
714   public ItemEntry setPubDate(Date pubDate, SimpleDateFormat format){
715     return setPubDate(format.format(pubDate));
716   }
717 
718   /***
719    * <li>Rss 1.0 - Not supported, this field is ignored.
720    * </li>
721    * <li>Rss 2.0 - Not supported, this field is ignored.
722    * </li>
723    * <li>Atom 1.0 - &lt;updated> The "atom:updated" element is a Date construct indicating the most recent 
724    * instant in time when an entry or feed was modified in a way the publisher considers significant. 
725    * Therefore, not all modifications necessarily result in a changed atom:updated value.
726    * </li>
727    * @return
728    */
729   public String getUpdatedDate() {
730     return _updatedDate;
731   }
732 
733   /***
734    * <li>Rss 1.0 - Not supported, this field is ignored.
735    * </li>
736    * <li>Rss 2.0 - Not supported, this field is ignored.
737    * </li>
738    * <li>Atom 1.0 - &lt;updated> The "atom:updated" element is a Date construct indicating the most recent 
739    * instant in time when an entry or feed was modified in a way the publisher considers significant. 
740    * Therefore, not all modifications necessarily result in a changed atom:updated value.
741    * </li>
742    * @param updatedDate
743    * @return
744    */
745   public ItemEntry setUpdatedDate(String updatedDate) {
746     _updatedDate = updatedDate;
747     return this;
748   }
749 
750 
751   /***
752    * <li>Rss 1.0 - Not supported, this field is ignored.
753    * </li>
754    * <li>Rss 2.0 - Not supported, this field is ignored.
755    * </li>
756    * <li>Atom 1.0 - &lt;updated> The "atom:updated" element is a Date construct indicating the most recent 
757    * instant in time when an entry or feed was modified in a way the publisher considers significant. 
758    * Therefore, not all modifications necessarily result in a changed atom:updated value.
759    * </li>
760    * 
761    * <br/>
762    * This method uses the input {@link SimpleDateFormat} object to format the date into a string.
763    * @param date
764    * @param format
765    * @return
766    */
767   public ItemEntry setUpdatedDate(Date date, SimpleDateFormat format) {
768     return setUpdatedDate(format.format(date));
769   }
770 
771 
772   /***
773    * <li>Rss 1.0 - Not supported, this field is ignored.
774    * </li>
775    * <li>Rss 2.0 - The RSS channel that the item came from.
776    * </li>
777    * <li>Atom 1.0 - Not supported, this field is ignored.
778    * </li>
779    * @return
780    */
781   public Source getSource() {
782     return _source;
783   }
784 
785   /***
786    * <li>Rss 1.0 - Not supported, this field is ignored.
787    * </li>
788    * <li>Rss 2.0 - &lt;source> The RSS channel that the item came from.
789    * </li>
790    * <li>Atom 1.0 - Not supported, this field is ignored.
791    * </li>
792    * @param source
793    * @return
794    */
795   public ItemEntry setSource(Source source) {
796     _source = source;
797     return this;
798   }
799 
800 
801   /***
802    * <li>Rss 1.0 - &lt;dc:rights> Information about rights held in and over the resource.
803    * </li>
804    * <li>Rss 2.0 - Not supported, this field is ignored.
805    * </li>
806    * <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.
807    * </li>
808    * @return
809    */
810   public Text getRights() {
811     return _rights;
812   }
813   /***
814    * <li>Rss 1.0 - &lt;dc:rights> Information about rights held in and over the resource.
815    * </li>
816    * <li>Rss 2.0 - Not supported, this field is ignored.
817    * </li>
818    * <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.
819    * </li>
820    * 
821    * @return the text content of the <code>rights</code> field.
822    */
823   public String getRightsText() {
824     return _rights == null ? null:_rights.getText();
825   }
826   
827   /***
828    * <li>Rss 1.0 - &lt;dc:rights> Information about rights held in and over the resource.
829    * </li>
830    * <li>Rss 2.0 - Not supported, this field is ignored.
831    * </li>
832    * <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.
833    * </li>
834    * @param rights
835    * @return
836    */
837   public ItemEntry setRights(Text rights) {
838     _rights = rights;
839     return this;
840   }
841 
842   /***
843    * <li>Rss 1.0 - &lt;dc:rights> Information about rights held in and over the resource.
844    * </li>
845    * <li>Rss 2.0 - Not supported, this field is ignored.
846    * </li>
847    * <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.
848    * </li>
849    * <br/>
850    * This method creates a new {@link Text} object using the input string as its content and sets <code>rights</code> field to this object.
851    * @param rights
852    * @return
853    */
854   public ItemEntry setRights(String rights) {
855     if(rights == null){
856       _rights = null;
857       return this;
858     }
859     return setRights(new Text(rights));
860   }
861   
862   /***
863    * <li>Rss 2.0 -
864    * This is not officially supported, but if there's a &lt;content:encoded /> element under &lt;Item>,
865    * the content of the encoded element will be mapped to this class. The type will always be 'text' in this case.
866    * </li>
867    * <li>Rss 1.0 -
868    * This is not officially supported, but if there's a &lt;content:encoded /> element under &lt;Item>,
869    * the content of the encoded element will be mapped to this class. The type will always be 'text' in this case.
870    * </li>
871    * <li>Atom 1.0 - &lt;content> 
872    * The "atom:content" element either contains or links to the content of the entry. The content of atom:content is Language-Sensitive.
873    * </li>
874    * @return
875    */
876   public Content getContent() {
877     return _content;
878   }
879 
880   /***
881    * <li>Rss 2.0 -
882    * This is not officially supported, but if there's a &lt;content:encoded /> element under &lt;Item>,
883    * the content of the encoded element will be mapped to this class. The type will always be 'text' in this case.
884    * </li>
885    * <li>Rss 1.0 -
886    * This is not officially supported, but if there's a &lt;content:encoded /> element under &lt;Item>,
887    * the content of the encoded element will be mapped to this class. The type will always be 'text' in this case.
888    * </li>
889    * <li>Atom 1.0 - &lt;content> 
890    * The "atom:content" element either contains or links to the content of the entry. The content of atom:content is Language-Sensitive.
891    * </li>
892    * @param content
893    * @return
894    */
895   public ItemEntry setContent(Content content) {
896     _content = content;
897     return this;
898   }
899 
900 
901   /***
902    * <li>Rss 2.0 -
903    * This is not officially supported, but if there's a &lt;content:encoded /> element under &lt;Item>,
904    * the content of the encoded element will be mapped to this class. The type will always be 'text' in this case.
905    * </li>
906    * <li>Rss 1.0 -
907    * This is not officially supported, but if there's a &lt;content:encoded /> element under &lt;Item>,
908    * the content of the encoded element will be mapped to this class. The type will always be 'text' in this case.
909    * </li>
910    * <li>Atom 1.0 - &lt;content> 
911    * The "atom:content" element either contains or links to the content of the entry. The content of atom:content is Language-Sensitive.
912    * </li>
913    * <br/>
914    * This method constructs a new {@link Content} object of type 'text' and uses the input string as its text content.
915    * @param contentText
916    * @return
917    */
918   public ItemEntry setContent(String contentText) {
919     if(_content == null){
920       _content = null;
921       return this;
922     }
923     setContent(new Content(contentText));
924     return this;
925   }
926 
927   ////////////////////////Common setters///////////////////////
928   /***
929    * Any other attribute that is not in the RSS 2.0 specs.
930    */
931   public ItemEntry setOtherAttributes(Map<QName, String> otherAttributes) {
932     _otherAttributes = otherAttributes;
933     return this;
934   }
935   /***
936    * Add an attribute that is not in the RSS 2.0 specs.
937    */
938   public ItemEntry addOtherAttributes(QName namespace, String attribute) {
939     if(_otherAttributes == null){
940       _otherAttributes = new HashMap<QName, String>();
941     }
942     _otherAttributes.put(namespace, attribute);
943     return this;
944   }
945   
946   /***
947    * Other additional elements that are not in the Rss specs.<br/>
948    * **Note** The element should not have an empty namespace to avoid collision with the specs elements.
949    */
950   public ItemEntry setOtherElements(List<Element> otherElements) {
951     _otherElements = otherElements;
952     return this;
953   }
954   /***
955    * Add an element that is not specified in the Rss specs.<br/>
956    * **Note** The element should not have an empty namespace to avoid collision with the specs elements.
957    * @param element - any element
958    */
959   public ItemEntry addOtherElement(Element element){
960     if(_otherElements == null){
961       _otherElements = new ArrayList<Element>();
962     }
963     _otherElements.add(element);
964     return this;
965   }
966   
967   /***
968    * Add an element that is not specified in the Rss specs.<br/>
969    * **Note** The element should not have an empty namespace to avoid collision with the specs elements.
970    * 
971    * @param xmlString - any element
972    * @throws ParserConfigurationException 
973    * @throws IOException 
974    * @throws SAXException 
975    */
976   public ItemEntry addOtherElement(String xmlString) throws SAXException, IOException, ParserConfigurationException{
977     return addOtherElement(XMLUtils.parseXml(xmlString, false, false).getDocumentElement());
978   }
979   
980 
981   /***
982    * <b>Atom 1.0 only</b><br/>
983    * Any element defined by this specification MAY have an xml:base attribute 
984    * [W3C.REC-xmlbase-20010627]. When xml:base is used in an Atom Document, 
985    * it serves the function described in section 5.1.1 of [RFC3986], establishing 
986    * the base URI (or IRI) for resolving any relative references found within the 
987    * effective scope of the xml:base attribute.
988    * @param base
989    * @return
990    */
991   public ItemEntry setBase(String base) {
992     _base = base;
993     return this;
994   }
995   /***
996    * <li>Rss 2.0 - &lt;language> element. 
997    * The language the channel is written in. This allows aggregators to group 
998    * all Italian language sites, for example, on a single page. A list of allowable 
999    * values for this element, as provided by Netscape, is here. You may also use values 
1000    * defined by the W3C.
1001    * Only &lt;channel> support this element.</li>
1002    * <li>Rss 1.0 - &lt;dc:language> element. A language of the intellectual content of the resource.
1003    * Only &lt;channel> and &lt;item> support this element. </li>
1004    * <li>Atom 1.0 - 'lang' attribute</li>
1005    * <br/>
1006    * Note: for Rss 2.0 and Rss 1.0, only &lt;channel> and &lt;item>
1007    * @param lang
1008    * @return
1009    */
1010   public ItemEntry setLang(String lang) {
1011     _lang = lang;
1012     return this;
1013   }
1014   /***
1015    * <li>Rss 2.0 - &lt;language> element. 
1016    * The language the channel is written in. This allows aggregators to group 
1017    * all Italian language sites, for example, on a single page. A list of allowable 
1018    * values for this element, as provided by Netscape, is here. You may also use values 
1019    * defined by the W3C.
1020    * Only &lt;channel> support this element.</li>
1021    * <li>Rss 1.0 - &lt;dc:language> element. A language of the intellectual content of the resource.
1022    * Only &lt;channel> and &lt;item> support this element. </li>
1023    * <li>Atom 1.0 - 'lang' attribute</li>
1024    * <br/>
1025    * Note: for Rss 2.0 and Rss 1.0, only &lt;channel> and &lt;item>
1026    * @param lang
1027    * @return
1028    */
1029   public ItemEntry setLang(Locale lang) {
1030     _lang = lang.getLanguage();
1031     return this;
1032   }
1033   /***
1034    * <b>Rss 1.0 only</b><br/>
1035    * @param resource
1036    * @return
1037    */
1038   public ItemEntry setResource(String resource) {
1039     _resource = resource;
1040     return this;
1041   }
1042   /***
1043    * <b>Rss 1.0 only</b><br/>
1044    * @param about
1045    * @return
1046    */
1047   public ItemEntry setAbout(String about) {
1048     _about = about;
1049     return this;
1050   }
1051   ////////////////////////Common setters///////////////////////
1052   
1053   @Override
1054   public void validate(FeedFormat format) throws ValidationException {
1055     
1056     if(_title == null && _descriptionOrSummary == null){
1057       throw new ValidationException("Item: At least one of title or description must be present.");
1058     }
1059     if(_categorySubjects != null){
1060       for(CategorySubject c: _categorySubjects){
1061         c.validate(format);
1062       }
1063     }
1064     if(_enclosure != null){
1065       _enclosure.validate(format);
1066     }
1067     if(_uid != null){
1068       _uid.validate(format);
1069     }
1070     if(_source != null){
1071       _source.validate(format);
1072     }
1073     
1074     if(_links != null){
1075       for(Link link : _links){
1076         if(link != null){
1077           link.validate(format);
1078         }
1079       }
1080     }
1081     
1082   }
1083 
1084 }