[jsword-devel] BookDataListener: Question 1

Eric Galluzzo jsword-devel@crosswire.org
14 May 2003 21:58:05 -0400


On Tue, 2003-05-13 at 04:38, Joe Walker wrote:
> Hi,
> 
> Hmmm. Yes, I was worried this would be the response.
> 
> Options:
> 1. Split the class up into 2 or more Listeners, more tightly focused to 
> lessen then number of methods on the interface. (I think this simply 
> wallpapers over the cracks - having 2 interfaces doesn't make things 
> easier to use)
> 
> 2. Give up with the idea of using a SAX like interface and use a 
> generated data-bound style like JAXB (or Castor, ...). Directly using 
> JAXB does give us a strong dependency on it, which worries me, and I'm 
> sure anyone wanting to use JSword on a J2ME device would freak.
> 
> 3. Give up with the idea of using a SAX like interface and use our own 
> custom data-bound style. So we write our own W class with a setMorph() 
> method etc. This just seems like JAXB with more work, so I'm even less 
> keen on this.
> 
> 4. Use JDom (or DOM, DOM4J, XOM, etc). This again creates a big 
> dependency on an XML library that might not work on J2ME devices.
> 
> Any more?

How about this one.  We can make the existing interface even more
SAX-like by passing each method a map of attributes.  In general I
strongly dislike what I call "map-oriented programming" (i.e. no objects
but just maps of maps of maps -- generic but meaningless), but I think
that perhaps in this case the map is warranted.

This could be expressed in three ways:

5a.

public interface BookDataListener
{
    void startWord( Map attributes );
    void endWord();
    void startReference( Map attributes );
    void endReference();
}

Advantages:
    - very extensible
    - small API to maintain

Disadvantages:
    - hard to use (what goes in the map?)
    - tied tightly to XML


5b.

public interface BookDataListener
{
    void startWord( OSISAttributes attributes );
    void endWord();
    void startReference( OSISAttributes attributes );
    void endReference();
}

public class OSISAttributes
{
    Passage fPassage;
    String fMorph;

    public Passage getPassage()
    {
        return fPassage;
    }

    public void setPassage( Passage passage )
    {
        fPassage = passage;
    }

    public String getMorph()
    {
        return fMorph;
    }

    public void setMorph( String morph )
    {
        fMorph = morph;
    }

    // ...
}

Advantages:
    - still concise (only two classes)
    - fairly easy to use
    - not terribly tied to XML (e.g. uses real types, not just Strings;
      bean properties can span multiple OSIS attributes)

Disadvantages:
    - takes a little work to add new attributes
    - possibly difficult to map OSIS attributes into meaningful non-JAXB
      types
    - every startXXX() method gets this big bag of attributes, some of
      which are used, some of which are not


5c.

public interface BookDataListener
{
    void startWord( WordAttributes attributes );
    void endWord();
    void startReference( ReferenceAttributes attributes );
    void endReference();
}

public class CommonAttributes
{
    // common attributes here
}

public class WordAttributes extends CommonAttributes
{
    protected String fMorph;

    public String getMorph()
    {
        return fMorph;
    }

    public void setMorph( String morph )
    {
        fMorph = morph;
    }

    // ...
}

public class ReferenceAttributes extends CommonAttributes
{
    protected Passage fPassage;

    public Passage getPassage()
    {
        return fPassage;
    }

    public void setPassage( Passage passage )
    {
        fPassage = passage;
    }
}

Advantages:
    - easy to use
    - each startXXX() method gets only the attributes it needs

Disadvantages:
    - takes some work to add new attributes and elements
    - possibly difficult to map OSIS attributes into meaningful non-JAXB
      types
    - could require lots and lots of classes (although perhaps could use
      JDK 1.3 dynamic proxies to implement bean interfaces instead)


I'd probably favor 5b myself.  Failing that, I'd favor the original #2
(populating an XML-like tree ourselves).  The only problem with that, as
you said, is depending heavily on auto-generated classes, which means
that if JAXB suddenly changes, we're out of luck; and we can't add our
own "business methods."

> If we don't care about J2ME then option feels right to me. If we do care 
> about J2ME then option 1 with it's problems still feels right.
> 
> My gut feeling is that while thinking about J2ME we may well be 
> straining to meet a target that could better be met by using a separate 
> tree, and in doing so making the JSword harder to use.

I agree that the J2ME tree should probably just be a small, separate
tree.  Probably it could work simply by having a small MIDP client,
perhaps using kSOAP, and a proper server that uses the JSword APIs.

I would prefer not to depend on kXML and kSOAP in the core JSword tree,
simply because they're not standard APIs and would require a fair bit of
learning curve.  Also, if Enhydra suddenly pulls the carpet from under
their feet, we're kinda out of luck (although they are open-source, I
suppose).  On the other hand, SAX, DOM, JAXB, and so forth are probably
not going away any time soon, and developers are more likely to be
familiar with them.

> So there is an important question (1b!) How much do we care about J2ME?
> 
> Do we try to keep J2ME compatibility within the main tree or do we have 
> a spin off project - KSword?
> I don't know much about J2ME, or any of the profiles so I can't comment 
> on how different things are there. Are they so different that we need a 
> separate project?

Well, I'm certainly not an expert; however, that's never stopped me
before. ;)  As far as I have seen, there is a large difference between,
say, MIDP (built on CLDC) and Personal Profile (built on CDC).  MIDP is
extremely limited in application size (e.g. <50K for an application's
jar file), API richness, screen size, and language features (e.g. no
finalizers, no floating point, no native methods).  On the other hand,
the Personal Profile often uses a "real" JVM and has access to almost
all of the JDK 1.1.8 APIs.  So perhaps we need:

    - JSword
    - KSword
        - base library using kSOAP
        - MIDP UI (e.g. options, search screen, unformatted text
          display, book browser, and that's about it)
        - Personal Profile UI (e.g. rich-ish UI with formatted text
          display)

We'd have to design the KSword API so that it could return formatted or
unformatted text, I suppose.  Also, KSword may not be the best name,
since it wouldn't necessarily be limited to the KVM; and the KDE folks
might get upset. :)

What do folks think?

    - Eric