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