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