More notes on Rome 2

View: New views
1 Messages — Rating Filter:   Alert me  

More notes on Rome 2

by Robert (kebernet) Cooper :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Having spent a little more time with Alejandro's code, I just have a
few things that I would like to add on styles and implementation.
Also, the Google Code project now has Alejandro's source and my source
checked in. They are in no way set up to integrate with each other,
just there and compilable on their own.

Parse detection:

While I agree that the Synd* structure is generally more trouble than
it is worth, I think we still need some support for basic parse
detection and conversion. The use case I am imagining looks something
like this:


RomeService rome = new DefaultRomeService(); // creation with auto
discovery (see the DefaultParserContext)

AtomFeed feed = (AtomFeed) rome.readAs( AtomFeed.class, new
URL("http://some.com/something.rss"));

This is a little different from where Alejandro's proposal was. While
we could still support the direct method calls, I think you need
something that supports a feed type discovery and auto-conversion. A
big part of the current Rome utility is that you can jut point it at a
URL and have it parse it into something usable. While the Synd*
structure seems to cause more problems than it solves, I think we
would maintain that use case.

After parsing with the native feed parser, this would use a default
set of converters that would be registered as the DefaultRomeService
is created, or could be set on an empty RomeService by DI. Conversion
Registry would look like:

public RSS2toAtomConvert implements Converter<AtomFeed, RSS2Channel> {

   public void init(ConverterContext context){
        boolean clobbered = context.registerConverter(this,
AtomFeed.class, RSS2Channel.class);
        if(clobbered) System.err.println("WARNING, Clobbered a converter!");
   }

  public AtomFeed convert(ConverterContext context, RSS2Channel channel){
   ...

  }
}

The ConverterContext should also support participation by the Modules
system in the process. After the conversion of one type to another,
the converter should cycle through first the new feed element, then
each of its "Entry" equivalents, and match the supported module class
to a converter:

public interface ModuleConverter<F extends FeedType, E extends EntryType> {

     void init(ConverterContext context);
     F translate(ConverterContext context, F destinationFeed);
     E translate(ConverterContext context, E destinationEntry);

}

Here an implementation might be:

public DublinCoreRSSToAtomConverter
implementsModuleConverter<AtomFeed, AtomEntry> {

    public void init(ConverterContext context){
         context.registerModuleConverter(this, RSS2Channel.class,
AtomFeed.class);

    }
    //...
}

Saying that "Use this converter when moving from RSS2 to Atom. Since
the AtomFeed should contain all the Extensions for DC from the source
feed provided by the basic conversion, the purpose here would be to
simply remove DC elements that are duplicated by Atom element. This
takes away the "special cases" and allows any module that wants to the
ability to participate first class in the conversion process.
Moreover, if a new FeedType is supported in the future, say KML is
kind of on my wish list, the GeoRSS module could supply the direct
conversion of GeoRSS information to the proper KML elements.

There are also a few more things I would change in Alejandro's current
system: The individual feed parsers should get a Types factory
injected into them. This would be something that would either be
auto-registered, or injectable/resettable on the top level RomeService
object. It would be a marker interface that each feed type would be
required to provide a definition for. This would change something
like:

@SuppressWarnings({"unchecked"})
   private AtomCategory parseCategory(AtomParserContext context,
Element jCategory) throws AtomException {
       AtomCategory aCategory = new AtomCategory();

       commonParsing(context, jCategory, aCategory, true);

       for (Attribute jAttr : getAttributes(jCategory,
context.getAtomNamespace(), true)) {
           if (jAttr.getName().equals("term")) {
               aCategory.setTerm(jAttr.getValue());
           }
           else if (jAttr.getName().equals("scheme")) {
               aCategory.setScheme(jAttr.getValue());
           }
           else if (jAttr.getName().equals("label")) {
               aCategory.setLabel(jAttr.getValue());
           }
           else {
               context.getReporter().report("WARN - unknown Atom
category attribute: " + jAttr.getName());
           }
       }

       return aCategory;
   }

to

@SuppressWarnings({"unchecked"})
   private AtomCategory parseCategory(AtomParserContext context,
Element jCategory) throws AtomException {
       AtomTypesFactory factory = (AtomTypesFactory) context.getTypesFactory();
       AtomCategory aCategory = factory.newCategory();

       commonParsing(context, jCategory, aCategory, true);

      //.. snip

       return aCategory;
   }


Allowing the insertion of, for instance, JPA classes in as a wholesale
implementation of AtomTypesFactory.

I'll have a few more notes tomorrow.

--
:Robert "kebernet" Cooper
::kebernet@...
Alice's cleartext
Charlie is the attacker
Bob signs and encrypts
http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x9E8759F8

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...