As we were designing and implementing Rome we had discusssions, brainstorming and code reviews on the API. We've captured them in this document.
Yes, using what we call Modules. Currently we support the 2 modules defined in RSS 1.0, Dublin Core and Syndication. They are wired when converting from SyndFeed beans to RSS/Atom feeds beans and vice versa. We use the RSS 1.0 terminology of Modules because RSS 1.0 is the specification that defined and used extensibility the most. RSS 2.0 and Atom use XML namespaces to extend the feed.
However we will develop, and encourage developers to develop Rome specific Modules to handle future RSS 2.0 and Atom extensions.
If additional modules are defined to express metadata the converters should be modified to handle them. And the same goes for the parsers and generators or RSS/Atom feeds.
We've struggled (and still are struggling) with names. We renamed and moved things around until we got dizzy. If you have suggestions please let us know.
They are in hidden (not javadoc-ed) packages within the Rome jar file. Their classes are loaded using declarations in a properties file. It is possible for developers to add or replace implementations of these components without modifying Rome source code, just by indicating an addition properties file to look for extra implementation classes.
At first we got tired of modifying the toString() methods every time we were adding/removing a property. As we were strictly following the Bean patterns we wrote a toString() method that would traverse the properties and print them. Then we went recursively. Then we refactor that into an interface and provided an adapter.
Later we did the same to handle equals/hashcode, which is very useful when using Maps.
To complete the task we did the same for cloning, providing deep cloning support.
The ObjectBean is a base class that implements all these features. All Rome beans extend ObjectBean getting a toString, equals, hashcode and clone support for free.
For Boolean is false. For numbers is 1. For String is null. For collections is an empty collection (even if you set it to null you get an empty collection). For all other objects is null.
All properties as always handled by reference (except primitive types). If they are not immutable and you modify them you are affecting the bean/s that reference them too.
Interfaces have the following naming pattern: <NAME>I. Default implementations provided with Rome are named just <NAME>. For example, SyndFeedI is the interface and SyndFeed is the default implementation.
We decided to use <NAME> for the default implementation classes as we think they'll be the implementation of choice most of the time.
We added interfaces only for the higher abstraction layer of Rome, SyndFeed (and Modules as they are used to express extensible metadata for SyndFeed instances). The reasoning behind such decoupling was to allow facading existing classes as SyndFeed beans. For example some persistent classes. This would allow to process them through components that work with SyndFeedI.
We thought about this, we dismissed the idea. The reasoning was that we expect to work with the SyndFeed and Module beans all the time and the convenience of using interface should be at that level only. We have RSS and Atom only because we have folks going and making up things without talking to each other. In short, we expect all our application processing to be done in a feed agnostic way in Java using SyndFeed and Module beans.
Item description MIME type, depending on the RSS version is text/plain (0.91), text/html (0.92, 0.93, 2.0) or configurable (0.94). The thing is that when you get the value out of JDOM Element it's always XML unescaped. When putting data into a JDOM Element the data is XML escaped. This is not 100% correct but it will work in most of the cases.
Note that type in feed beans indicate what was the escaping type of the underlying feed, but if you get the value is already unescaped.
The mode in feed in content indicates what was the encoding of the element in the feed, but when you get the value is already unencoded.
Rome implementation currently uses JDOM for parsing and generating syndication feeds. As people tend to use the XML libraries they feel more comfortable with we have built in support for SAX, DOM, JDOM, byte streams, character streams and strings.
This method was originally a static method in the SyndFeed class. We've moved ot the SyndFeedI interface as we thought it would be useful to be able to ask a SyndFeedI instance the feed converters it handles.
Yes, the default bean implementations of SyndFeedI provided with Rome are Serializable.
However, the *I interfaces are not. We made that decision consciously and the reason behind it is closely related to the reason we introduced the *I interfaces. You may want to extend some existing classes to implement SyndFeedI, and these classes you are extending may not be Serializable and cannot be (for example, they are tied to a live InputStream).