[jsword-devel] Valid module keys

Greg Hellings greg.hellings at gmail.com
Sat Jan 11 19:48:29 MST 2014


DM,

Thanks for that thorough explanation. I was trying to figure out if I was
simply missing a call like book.getBooks() or book.getRootKeys() or similar
or if I needed to construct it more deeply.


On Sat, Jan 11, 2014 at 7:21 AM, DM Smith <dmsmith at crosswire.org> wrote:

>
> On Jan 11, 2014, at 1:15 AM, Greg Hellings <greg.hellings at gmail.com>
> wrote:
>
> > I'm trying to decipher the API so I can fetch a list of the top-level
> keys in a module. e.g. for a Bible a list of all the Bible books that are
> valid for a given Book or such. What is the preferred way?
>
> It depends. Typically on use case.
>
> Are you asking specifically about Bibles or modules in general?
>

I was asking in general.


>
> Not sure what top-level means to you. It probably differs between
> different module types. For a dictionary, do you mean all the terms that
> don't link to others? For a Gen Book do you mean all the first nodes in the
> tree? For a Bible do you mean all the books of the Bible? What about Bible
> introductions (e.g. module and testament level)?
>

For a Bible I was meaning all the books in the particular module/Book that
contain content. For Gen Book I was meaning all the top-level sections.


>
> And I'm not sure what you mean by valid. There are several levels of valid?
>
> Given a key is it allowable for the module.
> Is Genesis allowable for a Bible? How about 1 Hesitations?
> Is Fred allowable for a dictionary? How about xyz?
> Is Fred allowable for a Daily Devotion? How about March 3?
>
> Does the key have content in the module?
> Is Gen 1:1 in the Bible? Is Genesis in the Bible?
> Is xyz in the Dictionary?
> Is March 3 in the Daily Devotion?
>
> Is the key defined for the versification?
> Is Bel and the Dragon defined for the KJV v11n?
>
> Answering for Bibles:
> A Bible module (in JSword, we call a module a Book and a Bible module is
> an AbstractPassageBook) always has a Versification. A Key can only be
> understood in the context of a Bible's Versification.
> Given a Bible Book (aka module), b, you ask it for the Versification:
> b.getVersification();
> The Versification object has all kinds of methods to query what's
> allowable. Internally, it has a BibleBookList, which is an ordered list of
> BibleBook. This can be queried in a variety of ways:
>
> There are two kinds of BibleBook existence questions for a Versification:
> 1) Given a String, can it be understood as a BibleBook, using getBook(s)
> or isBook(s). E.g. Ge for Genesis.
> 2) Is a BibleBook in the Versification using containsBook(bb)
>
> There are 3 different ways to iterate over the list:
> 1) Iterate using getBookIterator
> 2) Numerically using getBookCount() and getBook(n)
> 3) Adjacency using getFirstBook(), getLastBook(), getNextBook(bb),
> getPreviousBook(bb)
>
>
> If you are wanting to know whether a particular Bible has a BibleBook, you
> might be asking whether there is any content for the BibleBook in the
> module. This can either be determined exactly (is there at least one key in
> the BibleBook that would return content) or heuristically (Is chapter 1,
> verse 1 have content for the BibleBook). The decision is one of performance.
>
> Aside, the SWORD module building programs append verse content to the dat
> file in the order it occurs in the source file. Then they write the start
> and length to the idx file for that verse. If the verses are in the
> canonical, versification order then the question can be answered with great
> performance as a Bible book will have a start and a length in the dat file.
> If the source is not in canonical, versification order or if the append
> mode of the module builder is used then this is not true. So, JSword cannot
> make assumptions about the order of verses in the dat files.
>
> To do the heuristic check:
> Build the key for the first chapter and verse of the book, using a verse
> constructor v = new Verse(v11n, bb, 1, 1).
> Then check for existence with b.contains(v)
>
> To do the full check, it really depends upon whether you are wanting to
> check just one BibleBook or every BibleBook. Assuming the latter case,
> which needs to check every last verse in the module for existence:
> b.getGlobalKeyList() will return the list of all keys that are actually in
> the Book. Chris B has optimized this to be very fast.
> Then create a VerseRange for each BibleBook and test to see if that verse
> range intersects with the global key list.
> To create a VerseRange you supply the first and last verse of the range:
> new VerseRange(v11n, new Verse(v11n, bb, 0, 0), new Verse(v11n, bb,
> v11n.getLastChapter(bb), v11n.getLastVerse(bb, v11n.getLastChapter())
> (Note use 1, 1 if you are not interested in the Book Intro or the first
> chapter intro. The range will include other chapter's intros.)
> Then test the global key list to see if it contains any of the keys in the
> VerseRange. (Note, the contains method on a global key list tests contains
> all).
> JSword does not have a "contain any", which is needed here. (BTW, we can
> add such if needed)
> It'd be something like:
> for each verse in the verse range
>   if is in the global key list
>     then return true as we are done
> end for
> return false
>

What I ended up doing, though I wasn't sure this would be the best way from
just glancing at the API, though it appears to be, is taking the list from
getGlobalKeyList(), splitting on the '.' character, and creating a Set out
of that. Then using those results to output. It does result in my ordering
being according to the module rather than the versification, but that is
sufficient for my purposes. But I'm running into a problem with Gen Books
with my final output algorithm. I'm using code like this to output the
requested sub-section of a module:

for (Key key : book.getKey(requestedReference)) {
    BookData data = new BookData(book, key);

    System.out.println(OSISUtil.getCanonicalText(data.getOSISFragment()));
}

This works fine for Bibles. I can iterate a single chapter, verse range,
book, etc in a Bible. I can get out any entry in a Dictionary. I can even
get the contents of a Gen Book if that sub-tree is only one level deep.
E.g. I can get out Pilgrim's Progress 'SOURCE' section or 'TITLE' section.
But I can't get out 'THE_AUTHOR'S_APOLOGY_FOR_HIS_BOOK' or 'PART_I'. Both
of them throw a NoSuchKeyException, although getGlobalKeyList() returned a
key whose OSIS ID claims to be equal to that string. Am I doing something
wrong here, or breaking some sort of assumption about module types?



>
> In Bible Desktop, we want something like this to help build the Book,
> chapter, verse navigator based on content of the Bible rather than on its
> Versification. E.g. No sense showing OT book names when the OT is not part
> of the module. Or showing all the Books when the module only contains John.
>
>
Exactly, I'm trying to generate a list like this for any type of module
that is passed in.

--Greg


> It may be that Chris B has implemented something like this for STEP.
>
> If this doesn't answer your question or point you in a useful direction,
> please ask.
>
> In Him,
>         DM
>
>
> _______________________________________________
> jsword-devel mailing list
> jsword-devel at crosswire.org
> http://www.crosswire.org/mailman/listinfo/jsword-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.crosswire.org/pipermail/jsword-devel/attachments/20140111/d74aee59/attachment.html>


More information about the jsword-devel mailing list