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.impl.CopyFromHelper;
21  import com.sun.syndication.feed.WireFeed;
22  import com.sun.syndication.feed.impl.ObjectBean;
23  import com.sun.syndication.feed.impl.CopyFromHelper;
24  import com.sun.syndication.feed.module.*;
25  import com.sun.syndication.feed.module.impl.ModuleUtils;
26  import com.sun.syndication.feed.synd.impl.Converters;
27  import com.sun.syndication.feed.synd.impl.URINormalizer;
28  
29  import java.util.*;
30  import java.io.Serializable;
31  
32  /***
33   * Bean for all types of feeds.
34   * <p>
35   * It handles all RSS versions and Atom 0.3, it normalizes all info, it may lose information.
36   * <p>
37   * @author Alejandro Abdelnur
38   *
39   */
40  public class SyndFeedImpl implements Serializable,SyndFeed {
41      private ObjectBean _objBean;
42      private String _encoding;
43      private String _uri;
44      private String _title;
45      private String _feedType;
46      private String _link;
47      private String _description;
48      private SyndImage _image;
49      private List _entries;
50      private List _modules;
51  
52      private static final Converters CONVERTERS = new Converters();
53  
54      private static final Set IGNORE_PROPERTIES = new HashSet();
55  
56      /***
57       * Unmodifiable Set containing the convenience properties of this class.
58       * <p>
59       * Convenience properties are mapped to Modules, for cloning the convenience properties
60       * can be ignored as the will be copied as part of the module cloning.
61       */
62  
63      public static final Set CONVENIENCE_PROPERTIES = Collections.unmodifiableSet(IGNORE_PROPERTIES);
64  
65      static {
66          IGNORE_PROPERTIES.add("publishedDate");
67          IGNORE_PROPERTIES.add("author");
68          IGNORE_PROPERTIES.add("copyright");
69          IGNORE_PROPERTIES.add("categories");
70          IGNORE_PROPERTIES.add("language");
71      }
72  
73      /***
74       * Returns the real feed types the SyndFeedImpl supports when converting from and to.
75       * <p>
76       * @return the real feed type supported.
77       */
78      public List getSupportedFeedTypes() {
79          return CONVERTERS.getSupportedFeedTypes();
80      }
81  
82      /***
83       * For implementations extending SyndFeedImpl to be able to use the ObjectBean functionality
84       * with extended interfaces.
85       * <p>
86       * @param beanClass
87       * @param convenienceProperties set containing the convenience properties of the SyndEntryImpl
88       * (the are ignored during cloning, check CloneableBean for details).
89       *
90       */
91      protected SyndFeedImpl(Class beanClass,Set convenienceProperties) {
92          _objBean = new ObjectBean(beanClass,this,convenienceProperties);
93      }
94  
95      /***
96       * Default constructor. All properties are set to <b>null</b>.
97       * <p>
98       *
99       */
100     public SyndFeedImpl() {
101         this(null);
102     }
103 
104     /***
105      * Creates a SyndFeedImpl and populates all its properties out of the
106      * given RSS Channel or Atom Feed properties.
107      * <p>
108      * @param feed the RSS Channel or the Atom Feed to populate the properties from.
109      *
110      */
111     public SyndFeedImpl(WireFeed feed) {
112         this(SyndFeed.class,IGNORE_PROPERTIES);
113         if (feed!=null) {
114             _feedType = feed.getFeedType();
115             Converter converter = CONVERTERS.getConverter(_feedType);
116             if (converter==null) {
117                 throw new IllegalArgumentException("Invalid feed type ["+_feedType+"]");
118             }
119             converter.copyInto(feed,this);
120         }
121     }
122 
123     /***
124      * Creates a deep 'bean' clone of the object.
125      * <p>
126      * @return a clone of the object.
127      * @throws CloneNotSupportedException thrown if an element of the object cannot be cloned.
128      *
129      */
130     public Object clone() throws CloneNotSupportedException {
131         return _objBean.clone();
132     }
133 
134     /***
135      * Indicates whether some other object is "equal to" this one as defined by the Object equals() method.
136      * <p>
137      * @param other he reference object with which to compare.
138      * @return <b>true</b> if 'this' object is equal to the 'other' object.
139      *
140      */
141     public boolean equals(Object other) {
142         return _objBean.equals(other);
143     }
144 
145     /***
146      * Returns a hashcode value for the object.
147      * <p>
148      * It follows the contract defined by the Object hashCode() method.
149      * <p>
150      * @return the hashcode of the bean object.
151      *
152      */
153     public int hashCode() {
154         return _objBean.hashCode();
155     }
156 
157     /***
158      * Returns the String representation for the object.
159      * <p>
160      * @return String representation for the object.
161      *
162      */
163     public String toString() {
164         return _objBean.toString();
165     }
166 
167     /***
168      * Creates a real feed containing the information of the SyndFeedImpl.
169      * <p>
170      * The feed type of the created WireFeed is taken from the SyndFeedImpl feedType property.
171      * <p>
172      * @return the real feed.
173      *
174      */
175     public WireFeed createWireFeed() {
176         return createWireFeed(_feedType);
177     }
178 
179     /***
180      * Creates a real feed containing the information of the SyndFeedImpl.
181      * <p>
182      * @param feedType the feed type for the WireFeed to be created.
183      * @return the real feed.
184      *
185      */
186     public WireFeed createWireFeed(String feedType) {
187         if (feedType==null) {
188             throw new IllegalArgumentException("Feed type cannot be null");
189         }
190         Converter converter = CONVERTERS.getConverter(feedType);
191         if (converter==null) {
192             throw new IllegalArgumentException("Invalid feed type ["+feedType+"]");
193         }
194         return converter.createRealFeed(this);
195     }
196 
197     /***
198      * Returns the wire feed type the feed had/will-have when coverted from/to a WireFeed.
199      * <p>
200      * @return the feed type, <b>null</b> if none.
201      *
202      */
203     public String getFeedType() {
204         return _feedType;
205     }
206 
207     /***
208      * Sets the wire feed type the feed will-have when coverted to a WireFeed.
209      * <p>
210      * @param feedType the feed type to set, <b>null</b> if none.
211      *
212      */
213     public void setFeedType(String feedType) {
214         _feedType = feedType;
215     }
216 
217     /***
218      * Returns the charset encoding of a the feed. This is not set by Rome parsers.
219      * <p>
220      * @return the charset encoding of the feed.
221      *
222      */
223     public String getEncoding() {
224         return _encoding;
225     }
226 
227     /***
228      * Sets the charset encoding of a the feed. This is not set by Rome parsers.
229      * <p>
230      * @param encoding the charset encoding of the feed.
231      *
232      */
233     public void setEncoding(String encoding) {
234         _encoding = encoding;
235     }
236 
237     /***
238      * Returns the feed URI.
239      * <p>
240      * How the feed URI maps to a concrete feed type (RSS or Atom) depends on
241      * the concrete feed type. This is explained in detail in Rome documentation,
242      * <a href="http://wiki.java.net/bin/edit/Javawsxml/Rome04URIMapping">Feed and entry URI mapping</a>.
243      * <p>
244      * The returned URI is a normalized URI as specified in RFC 2396bis.
245      * <p>
246      * @return the feed URI, <b>null</b> if none.
247      *
248      */
249     public String getUri() {
250         return _uri;
251     }
252 
253     /***
254      * Sets the feed URI.
255      * <p>
256      * How the feed URI maps to a concrete feed type (RSS or Atom) depends on
257      * the concrete feed type. This is explained in detail in Rome documentation,
258      * <a href="http://wiki.java.net/bin/edit/Javawsxml/Rome04URIMapping">Feed and entry URI mapping</a>.
259      * <p>
260      * @param uri the feed URI to set, <b>null</b> if none.
261      *
262      */
263     public void setUri(String uri) {
264         _uri = URINormalizer.normalize(uri);
265     }
266 
267     /***
268      * Returns the feed title.
269      * <p>
270      * @return the feed title, <b>null</b> if none.
271      *
272      */
273     public String getTitle() {
274         return _title;
275     }
276 
277     /***
278      * Sets the feed title.
279      * <p>
280      * @param title the feed title to set, <b>null</b> if none.
281      *
282      */
283     public void setTitle(String title) {
284         _title = title;
285     }
286 
287     /***
288      * Returns the feed link.
289      * <p>
290      * @return the feed link, <b>null</b> if none.
291      *
292      */
293     public String getLink() {
294         return _link;
295     }
296 
297     /***
298      * Sets the feed link.
299      * <p>
300      * @param link the feed link to set, <b>null</b> if none.
301      *
302      */
303     public void setLink(String link) {
304         _link = link;
305     }
306 
307     /***
308      * Returns the feed description.
309      * <p>
310      * @return the feed description, <b>null</b> if none.
311      *
312      */
313     public String getDescription() {
314         return _description;
315     }
316 
317     /***
318      * Sets the feed description.
319      * <p>
320      * @param description the feed description to set, <b>null</b> if none.
321      *
322      */
323     public void setDescription(String description) {
324         _description = description;
325     }
326 
327     /***
328      * Returns the feed published date.
329      * <p>
330      * This method is a convenience method, it maps to the Dublin Core module date.
331      * <p>
332      * @return the feed published date, <b>null</b> if none.
333      *
334      */
335     public Date getPublishedDate() {
336         return getDCModule().getDate();
337     }
338 
339     /***
340      * Sets the feed published date.
341      * <p>
342      * This method is a convenience method, it maps to the Dublin Core module date.
343      * <p>
344      * @param publishedDate the feed published date to set, <b>null</b> if none.
345      *
346      */
347     public void setPublishedDate(Date publishedDate) {
348         getDCModule().setDate(publishedDate);
349     }
350 
351     /***
352      * Returns the feed author.
353      * <p>
354      * This method is a convenience method, it maps to the Dublin Core module creator.
355      * <p>
356      * @return the feed author, <b>null</b> if none.
357      *
358      */
359     public String getAuthor() {
360         return getDCModule().getCreator();
361     }
362 
363     /***
364      * Sets the feed author.
365      * <p>
366      * This method is a convenience method, it maps to the Dublin Core module creator.
367      * <p>
368      * @param author the feed author to set, <b>null</b> if none.
369      *
370      */
371     public void setAuthor(String author) {
372         getDCModule().setCreator(author);
373     }
374 
375     /***
376      * Returns the feed copyright.
377      * <p>
378      * This method is a convenience method, it maps to the Dublin Core module rights.
379      * <p>
380      * @return the feed copyright, <b>null</b> if none.
381      *
382      */
383     public String getCopyright() {
384         return getDCModule().getRights();
385     }
386 
387     /***
388      * Sets the feed copyright.
389      * <p>
390      * This method is a convenience method, it maps to the Dublin Core module rights.
391      * <p>
392      * @param copyright the feed copyright to set, <b>null</b> if none.
393      *
394      */
395     public void setCopyright(String copyright) {
396         getDCModule().setRights(copyright);
397     }
398 
399     /***
400      * Returns the feed image.
401      * <p>
402      * @return the feed image, <b>null</b> if none.
403      *
404      */
405     public SyndImage getImage() {
406         return _image;
407     }
408 
409     /***
410      * Sets the feed image.
411      * <p>
412      * @param image the feed image to set, <b>null</b> if none.
413      *
414      */
415     public void setImage(SyndImage image) {
416         _image = image;
417     }
418 
419     /***
420      * Returns the feed categories.
421      * <p>
422      * This method is a convenience method, it maps to the Dublin Core module subjects.
423      * <p>
424      * @return a list of SyndCategoryImpl elements with the feed categories,
425      *         an empty list if none.
426      *
427      */
428     public List getCategories() {
429         return new SyndCategoryListFacade(getDCModule().getSubjects());
430     }
431 
432     /***
433      * Sets the feed categories.
434      * <p>
435      * This method is a convenience method, it maps to the Dublin Core module subjects.
436      * <p>
437      * @param categories the list of SyndCategoryImpl elements with the feed categories to set,
438      *        an empty list or <b>null</b> if none.
439      *
440      */
441     public void setCategories(List categories) {
442         getDCModule().setSubjects(SyndCategoryListFacade.convertElementsSyndCategoryToSubject(categories));
443     }
444 
445     /***
446      * Returns the feed entries.
447      * <p>
448      * @return a list of SyndEntryImpl elements with the feed entries,
449      *         an empty list if none.
450      *
451      */
452     public List getEntries() {
453         return (_entries==null) ? (_entries=new ArrayList()) : _entries;
454     }
455 
456     /***
457      * Sets the feed entries.
458      * <p>
459      * @param entries the list of SyndEntryImpl elements with the feed entries to set,
460      *        an empty list or <b>null</b> if none.
461      *
462      */
463     public void setEntries(List entries) {
464         _entries = entries;
465     }
466 
467     /***
468      * Returns the feed language.
469      * <p>
470      * This method is a convenience method, it maps to the Dublin Core module language.
471      * <p>
472      * @return the feed language, <b>null</b> if none.
473      *
474      */
475     public String getLanguage() {
476         return getDCModule().getLanguage();
477     }
478 
479     /***
480      * Sets the feed language.
481      * <p>
482      * This method is a convenience method, it maps to the Dublin Core module language.
483      * <p>
484      * @param language the feed language to set, <b>null</b> if none.
485      *
486      */
487     public void setLanguage(String language) {
488         getDCModule().setLanguage(language);
489     }
490 
491     /***
492      * Returns the feed modules.
493      * <p>
494      * @return a list of ModuleImpl elements with the feed modules,
495      *         an empty list if none.
496      *
497      */
498     public List getModules() {
499         if  (_modules==null) {
500             _modules=new ArrayList();
501         }
502         if (ModuleUtils.getModule(_modules,DCModule.URI)==null) {
503             _modules.add(new DCModuleImpl());
504         }
505         return _modules;
506     }
507 
508 
509     /***
510      * Sets the feed modules.
511      * <p>
512      * @param modules the list of ModuleImpl elements with the feed modules to set,
513      *        an empty list or <b>null</b> if none.
514      *
515      */
516     public void setModules(List modules) {
517         _modules = modules;
518     }
519 
520     /***
521      * Returns the module identified by a given URI.
522      * <p>
523      * @param uri the URI of the ModuleImpl.
524      * @return The module with the given URI, <b>null</b> if none.
525      */
526     public Module getModule(String uri) {
527         return ModuleUtils.getModule(getModules(),uri);
528     }
529 
530     /***
531      * Returns the Dublin Core module of the feed.
532      * @return the DC module, it's never <b>null</b>
533      *
534      */
535     private DCModule getDCModule() {
536         return (DCModule) getModule(DCModule.URI);
537     }
538 
539     public Class getInterface() {
540         return SyndFeed.class;
541     }
542 
543     public void copyFrom(Object obj) {
544         COPY_FROM_HELPER.copy(this,obj);
545     }
546 
547 
548     // TODO We need to find out how to refactor this one in a nice reusable way.
549 
550     private static final CopyFromHelper COPY_FROM_HELPER;
551 
552     static {
553         Map basePropInterfaceMap = new HashMap();
554         basePropInterfaceMap.put("feedType",String.class);
555         basePropInterfaceMap.put("encoding",String.class);
556         basePropInterfaceMap.put("uri",String.class);
557         basePropInterfaceMap.put("title",String.class);
558         basePropInterfaceMap.put("link",String.class);
559         basePropInterfaceMap.put("description",String.class);
560         basePropInterfaceMap.put("image",SyndImage.class);
561         basePropInterfaceMap.put("entries",SyndEntry.class);
562         basePropInterfaceMap.put("modules",Module.class);
563 
564         Map basePropClassImplMap = new HashMap();
565         basePropClassImplMap.put(SyndEntry.class,SyndEntryImpl.class);
566         basePropClassImplMap.put(SyndImage.class,SyndImageImpl.class);
567         basePropClassImplMap.put(DCModule.class,DCModuleImpl.class);
568         basePropClassImplMap.put(SyModule.class,SyModuleImpl.class);
569 
570         COPY_FROM_HELPER = new CopyFromHelper(SyndFeed.class,basePropInterfaceMap,basePropClassImplMap);
571     }
572 
573 }