View Javadoc

1   /*
2    * Copyright 2004 Sun Microsystems, Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  package com.sun.syndication.feed.synd;
18  
19  import com.sun.syndication.feed.impl.ObjectBean;
20  import com.sun.syndication.feed.module.*;
21  import com.sun.syndication.feed.module.impl.ModuleUtils;
22  import com.sun.syndication.feed.synd.impl.URINormalizer;
23  import com.sun.syndication.feed.impl.CopyFromHelper;
24  
25  import java.util.*;
26  import java.io.Serializable; 
27  
28  /***
29   * Bean for entries of SyndFeedImpl feeds.
30   * <p>
31   * @author Alejandro Abdelnur
32   *
33   */
34  public class SyndEntryImpl implements Serializable,SyndEntry {
35      private ObjectBean _objBean;
36      private String _uri;
37      private String _link;
38      private Date _updatedDate;
39      private SyndContent _title;       
40      private SyndContent _description;
41      private List _links;
42      private List _contents; // deprecated by Atom 1.0
43      private List _modules;
44      private List _enclosures;
45      private List _authors;
46      private List _contributors;
47      private SyndFeed _source;
48      private List _foreignMarkup;
49      
50      // ISSUE: some converters assume this is never null
51      private List _categories = new ArrayList(); 
52  
53      private static final Set IGNORE_PROPERTIES = new HashSet();
54  
55      /***
56       * Unmodifiable Set containing the convenience properties of this class.
57       * <p>
58       * Convenience properties are mapped to Modules, for cloning the convenience properties
59       * can be ignored as the will be copied as part of the module cloning.
60       */
61      public static final Set CONVENIENCE_PROPERTIES = Collections.unmodifiableSet(IGNORE_PROPERTIES);
62  
63      static {
64          IGNORE_PROPERTIES.add("publishedDate");
65          IGNORE_PROPERTIES.add("author");
66      }
67  
68      /***
69       * For implementations extending SyndEntryImpl to be able to use the ObjectBean functionality
70       * with extended interfaces.
71       * <p>
72       * @param beanClass
73       * @param convenienceProperties set containing the convenience properties of the SyndEntryImpl
74       * (the are ignored during cloning, check CloneableBean for details).
75       *
76       */
77      protected SyndEntryImpl(Class beanClass,Set convenienceProperties) {
78          _objBean = new ObjectBean(beanClass,this,convenienceProperties);
79      }
80  
81      /***
82       * Default constructor. All properties are set to <b>null</b>.
83       * <p>
84       *
85       */
86      public SyndEntryImpl() {
87          this(SyndEntry.class,IGNORE_PROPERTIES);
88      }
89  
90      /***
91       * Creates a deep 'bean' clone of the object.
92       * <p>
93       * @return a clone of the object.
94       * @throws CloneNotSupportedException thrown if an element of the object cannot be cloned.
95       *
96       */
97      public Object clone() throws CloneNotSupportedException {
98          return _objBean.clone();
99      }
100 
101     /***
102      * Indicates whether some other object is "equal to" this one as defined by the Object equals() method.
103      * <p>
104      * @param other he reference object with which to compare.
105      * @return <b>true</b> if 'this' object is equal to the 'other' object.
106      *
107      */
108     public boolean equals(Object other) {
109         if (other == null) {
110             return false;
111         }
112         // while ObjectBean does this check this method does a cast to obtain the foreign markup
113         // so we need to check before doing so.
114         if (!(other instanceof SyndEntryImpl)) {
115             return false;
116         }
117         // can't use foreign markup in equals, due to JDOM equals impl
118         Object fm = getForeignMarkup();
119         setForeignMarkup(((SyndEntryImpl)other).getForeignMarkup());              
120         boolean ret = _objBean.equals(other);
121         // restore foreign markup
122         setForeignMarkup(fm);
123         return ret;
124     }
125 
126     /***
127      * Returns a hashcode value for the object.
128      * <p>
129      * It follows the contract defined by the Object hashCode() method.
130      * <p>
131      * @return the hashcode of the bean object.
132      *
133      */
134     public int hashCode() {
135         return _objBean.hashCode();
136     }
137 
138     /***
139      * Returns the String representation for the object.
140      * <p>
141      * @return String representation for the object.
142      *
143      */
144     public String toString() {
145         return _objBean.toString();
146     }
147 
148 
149     /***
150      * Returns the entry URI.
151      * <p>
152      * How the entry URI maps to a concrete feed type (RSS or Atom) depends on
153      * the concrete feed type. This is explained in detail in Rome documentation,
154      * <a href="http://wiki.java.net/bin/edit/Javawsxml/Rome04URIMapping">Feed and entry URI mapping</a>.
155      * <p>
156      * The returned URI is a normalized URI as specified in RFC 2396bis.
157      * <p>
158      * @return the entry URI, <b>null</b> if none.
159      *
160      */
161     public String getUri() {
162         return _uri;
163     }
164 
165     /***
166      * Sets the entry URI.
167      * <p>
168      * How the entry URI maps to a concrete feed type (RSS or Atom) depends on
169      * the concrete feed type. This is explained in detail in Rome documentation,
170      * <a href="http://wiki.java.net/bin/edit/Javawsxml/Rome04URIMapping">Feed and entry URI mapping</a>.
171      * <p>
172      * @param uri the entry URI to set, <b>null</b> if none.
173      *
174      */
175     public void setUri(String uri) {
176         _uri = URINormalizer.normalize(uri);
177     }
178 
179     /***
180      * Returns the entry title.
181      * <p>
182      * @return the entry title, <b>null</b> if none.
183      *
184      */
185     public String getTitle() {
186         if (_title != null) return _title.getValue();
187         return null;
188     }
189 
190     /***
191      * Sets the entry title.
192      * <p>
193      * @param title the entry title to set, <b>null</b> if none.
194      *
195      */
196     public void setTitle(String title) {
197         if (_title == null) _title = new SyndContentImpl();
198         _title.setValue(title);
199     }
200 
201     /***
202      * Returns the entry title as a text construct.
203      * <p>
204      * @return the entry title, <b>null</b> if none.
205      *
206      */
207     public SyndContent getTitleEx() {
208         return _title;
209     }
210 
211     /***
212      * Sets the entry title as a text construct.
213      * <p>
214      * @param title the entry title to set, <b>null</b> if none.
215      *
216      */
217     public void setTitleEx(SyndContent title) {
218         _title = title;
219     }
220 
221     /***
222      * Returns the entry link.
223      * <p>
224      * @return the entry link, <b>null</b> if none.
225      *
226      */
227     public String getLink() {
228         return _link;
229     }
230 
231     /***
232      * Sets the entry link.
233      * <p>
234      * @param link the entry link to set, <b>null</b> if none.
235      *
236      */
237     public void setLink(String link) {
238         _link = link;
239     }
240 
241     /***
242      * Returns the entry description.
243      * <p>
244      * @return the entry description, <b>null</b> if none.
245      *
246      */
247     public SyndContent getDescription() {
248         return _description;
249     }
250 
251     /***
252      * Sets the entry description.
253      * <p>
254      * @param description the entry description to set, <b>null</b> if none.
255      *
256      */
257     public void setDescription(SyndContent description) {
258         _description = description;
259     }
260 
261     /***
262      * Returns the entry contents.
263      * <p>
264      * @return a list of SyndContentImpl elements with the entry contents,
265      *         an empty list if none.
266      *
267      */
268     public List getContents() {
269         return (_contents==null) ? (_contents=new ArrayList()) : _contents;
270     }
271 
272     /***
273      * Sets the entry contents.
274      * <p>
275      * @param contents the list of SyndContentImpl elements with the entry contents to set,
276      *        an empty list or <b>null</b> if none.
277      *
278      */
279     public void setContents(List contents) {
280         _contents = contents;
281     }
282 
283     /***
284      * Returns the entry enclosures.
285      * <p>
286      * @return a list of SyndEnclosure elements with the entry enclosures,
287      *         an empty list if none.
288      *
289      */
290     public List getEnclosures() {
291         return (_enclosures==null) ? (_enclosures=new ArrayList()) : _enclosures;
292     }
293 
294     /***
295      * Sets the entry enclosures.
296      * <p>
297      * @param enclosures the list of SyndEnclosure elements with the entry enclosures to set,
298      *        an empty list or <b>null</b> if none.
299      *
300      */
301     public void setEnclosures(List enclosures) {
302         _enclosures = enclosures;
303     }
304 
305 
306     /***
307      * Returns the entry published date.
308      * <p>
309      * This method is a convenience method, it maps to the Dublin Core module date.
310      * <p>
311      * @return the entry published date, <b>null</b> if none.
312      *
313      */
314     public Date getPublishedDate() {
315         return getDCModule().getDate();
316     }
317 
318     /***
319      * Sets the entry published date.
320      * <p>
321      * This method is a convenience method, it maps to the Dublin Core module date.
322      * <p>
323      * @param publishedDate the entry published date to set, <b>null</b> if none.
324      *
325      */
326     public void setPublishedDate(Date publishedDate) {
327         getDCModule().setDate(publishedDate);
328     }
329 
330     /***
331      * Returns the entry categories.
332      * <p>
333      * @return a list of SyndCategoryImpl elements with the entry categories,
334      *         an empty list if none.
335      *
336      */
337     public List getCategories() {
338        return _categories;
339     }
340 
341     /***
342      * Sets the entry categories.
343      * <p>
344      * This method is a convenience method, it maps to the Dublin Core module subjects.
345      * <p>
346      * @param categories the list of SyndCategoryImpl elements with the entry categories to set,
347      *        an empty list or <b>null</b> if none.
348      *
349      */
350     public void setCategories(List categories) {
351         _categories = categories;
352     }
353 
354     /***
355      * Returns the entry modules.
356      * <p>
357      * @return a list of ModuleImpl elements with the entry modules,
358      *         an empty list if none.
359      *
360      */
361     public List getModules() {
362         if  (_modules==null) {
363             _modules=new ArrayList();
364         }
365         if (ModuleUtils.getModule(_modules,DCModule.URI)==null) {
366             _modules.add(new DCModuleImpl());
367         }
368         return _modules;
369     }
370 
371     /***
372      * Sets the entry modules.
373      * <p>
374      * @param modules the list of ModuleImpl elements with the entry modules to set,
375      *        an empty list or <b>null</b> if none.
376      *
377      */
378     public void setModules(List modules) {
379         _modules = modules;
380     }
381 
382     /***
383      * Returns the module identified by a given URI.
384      * <p>
385      * @param uri the URI of the ModuleImpl.
386      * @return The module with the given URI, <b>null</b> if none.
387      */
388     public Module getModule(String uri) {
389         return ModuleUtils.getModule(getModules(),uri);
390     }
391 
392     /***
393      * Returns the Dublin Core module of the feed.
394      * @return the DC module, it's never <b>null</b>
395      *
396      */
397     private DCModule getDCModule() {
398         return (DCModule) getModule(DCModule.URI);
399     }
400 
401     public Class getInterface() {
402         return SyndEntry.class;
403     }
404 
405     public void copyFrom(Object obj) {
406         COPY_FROM_HELPER.copy(this,obj);
407     }
408 
409     private static final CopyFromHelper COPY_FROM_HELPER;
410 
411     static {
412         Map basePropInterfaceMap = new HashMap();
413         basePropInterfaceMap.put("uri",String.class);
414         basePropInterfaceMap.put("title",String.class);
415         basePropInterfaceMap.put("link",String.class);
416         basePropInterfaceMap.put("uri",String.class);
417         basePropInterfaceMap.put("description",SyndContent.class);
418         basePropInterfaceMap.put("contents",SyndContent.class);
419         basePropInterfaceMap.put("enclosures",SyndEnclosure.class);
420         basePropInterfaceMap.put("modules",Module.class);
421 
422         Map basePropClassImplMap = new HashMap();
423         basePropClassImplMap.put(SyndContent.class,SyndContentImpl.class);
424         basePropClassImplMap.put(SyndEnclosure.class,SyndEnclosureImpl.class);
425         basePropClassImplMap.put(DCModule.class,DCModuleImpl.class);
426         basePropClassImplMap.put(SyModule.class,SyModuleImpl.class);
427 
428         COPY_FROM_HELPER = new CopyFromHelper(SyndEntry.class,basePropInterfaceMap,basePropClassImplMap);
429     }
430 
431     /***
432      * Returns the links
433      * <p>
434      * @return Returns the links.
435      */
436     public List getLinks() {
437         return (_links==null) ? (_links=new ArrayList()) : _links;
438     }
439     
440     /***
441      * Set the links
442      * <p>
443      * @param links The links to set.
444      */
445     public void setLinks(List links) {
446         _links = links;
447     }    
448     
449     /***
450      * Returns the updatedDate
451      * <p>
452      * @return Returns the updatedDate.
453      */
454     public Date getUpdatedDate() {
455         return _updatedDate;
456     }
457     
458     /***
459      * Set the updatedDate
460      * <p>
461      * @param updatedDate The updatedDate to set.
462      */
463     public void setUpdatedDate(Date updatedDate) {
464         _updatedDate = updatedDate;
465     }
466 
467     public List getAuthors() {
468         return _authors;
469     }
470 
471     /* (non-Javadoc)
472      * @see com.sun.syndication.feed.synd.SyndEntry#setAuthors(java.util.List)
473      */
474     public void setAuthors(List authors) {
475         _authors = authors;
476     }
477 
478     /***
479      * Returns the entry author.
480      * <p>
481      * This method is a convenience method, it maps to the Dublin Core module creator.
482      * <p>
483      * @return the entry author, <b>null</b> if none.
484      *
485      */
486     public String getAuthor() {
487         String author;
488         
489         // Start out looking for one or more authors in _authors. For non-Atom
490         // feeds, _authors may actually be null.
491         if ((_authors != null) && (_authors.size() > 0)) {
492             author = ((SyndPerson)_authors.get(0)).getName();
493         } else {
494             author = getDCModule().getCreator();
495         }
496         if (author == null) {
497             author = "";
498         }
499         
500         return author;
501     }
502 
503     /***
504      * Sets the entry author.
505      * <p>
506      * This method is a convenience method, it maps to the Dublin Core module creator.
507      * <p>
508      * @param author the entry author to set, <b>null</b> if none.
509      *
510      */
511     public void setAuthor(String author) {
512         // Get the DCModule so that we can check to see if "creator" is already
513         // set.
514         DCModule dcModule = getDCModule();
515         String currentValue = dcModule.getCreator();
516         
517         if ((currentValue == null) || (currentValue.length() == 0)) {
518             getDCModule().setCreator(author);
519         }
520     }
521     
522     public List getContributors() {
523         return _contributors;
524     }
525 
526     /* (non-Javadoc)
527      * @see com.sun.syndication.feed.synd.SyndEntry#setContributors(java.util.List)
528      */
529     public void setContributors(List contributors) {
530         _contributors = contributors;
531     }
532     
533     public SyndFeed getSource() {
534     	return _source;
535     }
536     
537     public void setSource(SyndFeed source) {
538     	_source = source;
539     }
540     
541     /***
542      * Returns foreign markup found at channel level.
543      * <p>
544      * @return list of JDOM nodes containing channel-level foreign markup,
545      *         an empty list if none.
546      *
547      */
548     public Object getForeignMarkup() {
549         return (_foreignMarkup==null) ? (_foreignMarkup=new ArrayList()) : _foreignMarkup;
550     }
551 
552     /***
553      * Sets foreign markup found at channel level.
554      * <p>
555      * @param foreignMarkup list of JDOM nodes containing channel-level foreign markup,
556      *         an empty list if none.
557      *
558      */
559     public void setForeignMarkup(Object foreignMarkup) {
560         _foreignMarkup = (List)foreignMarkup;
561     }    
562 }