Source code: docs/DesignIntro.java
1 package docs;
2
3 /**
4 *
5 * This is overview documentation that explains how the Book and Bible
6 * interfaces are arranged and justifies the design decisions. Note that most
7 * of what is documented here is current for ProjectB - there are a few
8 * sections that reflect where we will be given a bit more re-factoring.
9 *
10 * <p>The most important thing any Bible program does is to access Bible data, and
11 * in more general terms, book data. There may be many different sources of
12 * data - Bibles stored in different formats, or even on remote systems,
13 * dictionaries, lexicons and so on. It would be good (where appropriate) to be
14 * able to treat them all similarly without needing to reinvent the wheel too
15 * often. Clearly we should be able to use inheritance to specialize where
16 * needed.
17 * So we start by creating an interface that is common to all 'Books' but that
18 * allows is to do as much as possible.
19 * The first goal is to read data and to be able to direct where to read from
20 * with some sort of pointer system. So we start with an interface that looks
21 * like this:
22 *
23 * <pre>interface Book
24 * {
25 * Data getData(Pointers ptr);
26 * }</pre>
27 *
28 * Before we look at what Data and Pointers look like, a Book will need to be
29 * able to do 2 other things:<br>
30 * Firstly tell us about itself: what it is called, where it comes from and so
31 * on - MetaData about the Book itself.
32 * Secondly help us to find stuff by searching. Now searching can be complex
33 * and we should not aim to implement a full search system in every Book,
34 * however I think we can build a couple of simple methods that will allow us
35 * to construct a powerful generalized search system separately. All we need
36 * is to find any given word and to be able to find words that match a given
37 * specification.
38 *
39 * So we can develop our interface like this:
40 *
41 * <pre>interface Book
42 * {
43 * BookMetaData getMetaData();
44 * Data getData(Pointers ptr);
45 * Pointers search(String word);
46 * String[] matchingWords(String spec);
47 * }</pre>
48 *
49 * The definition of the matchingWord spec needs attention - in ProjectB the
50 * method is called getStartsWith(String base) which allows stemming (the most
51 * commmon search word manipulation) but does not allow more complex wildcard
52 * cases. I want to avoid adding too much complexity that will be hard to
53 * implement and rarely used. Certainly any solution that involves regular
54 * expression is going to be 1. very hard to implement and 2. not actually
55 * useful for 99% of users. So I propose a simplifiaction:
56 *
57 * <pre>interface Book
58 * {
59 * ...
60 * String[] startsWith(String spec);
61 * }</pre>
62 *
63 * This interface can be implemented several times, once by something that
64 * reads Sword format data, once by something that reads ProjectB format data,
65 * and so on.
66 * The users, and indeed the developers of the front ends do not want to know
67 * about the various different implementors and what implementations need to be
68 * looked at. So we can use a couple of classes to fix this. If you like GoF
69 * patterns, an AbstractFactory:
70 *
71 * <pre>interface Books
72 * {
73 * Iterator listBooks();
74 * void registerDriver(BookDriver driver);
75 * }
76 *
77 * interface BookDriver
78 * {
79 * Iterator listBooks();
80 * }</pre>
81 *
82 * Both listBooks() methods allow you to iterate over the Books known to the
83 * whole system (Books) or the particular BookDriver. The question is what sort
84 * of Object should these iterators iterate over?<br>
85 * The Books themselves would be a bad idea because creating a Book may be a
86 * time and memory consuming process (indexes to be loaded etc) so we need some
87 * sort of a key to refer to Books by.
88 * A simple string is OK, but better (and more unique) would be the MetaData
89 * objects previously noted. So these MetaData objects need to be able to give
90 * access to the Book they represent.
91 *
92 * <pre>interface Books
93 * {
94 * Iterator listBooks();
95 * void registerDriver(BookDriver driver);
96 * Book getBook(BookMetaData id);
97 * }</pre>
98 *
99 * The BookMetaData itself looks something like this:
100 *
101 * <pre>interface BookMetaData
102 * {
103 * String getName();
104 * }</pre>
105 *
106 * Before we move on to what BookData and Pointers look like, I have
107 * intentionally ignored 2 issues:
108 * Encrypted works - some works will need to be encrypted - however the finding
109 * of keys or deobfustication will be done within the Driver so we don't need
110 * to worry about it too much.
111 * Configuration - some Books will need configuring before they will work,
112 * maybe with encryption keys, maybe with directories under which to find
113 * information. Each BookDriver will need to take care of configuring the Books
114 * that it creates we don't attempt to do anything more fancy even though there
115 * are parts of ProjectB that have implemented a generic configuration system.
116 *
117 * <p>BookData and Pointers are related. BookData describes the actual Book
118 * text (for example "In the beginning God created ...") and Pointers describe
119 * where that text comes from (for example "Gen 1:1")
120 *
121 * <p>BookData first. We do not want to force users of this code to use it in
122 * any specific way, so BookData should describe the text in as much detail as
123 * possible without forcing how that text is used. The final display could be a
124 * PDA, a web browser, a matching verse list or a full-blow GUI display. This
125 * to me rules out RTF, HTML and plain text, as they are all either display
126 * specific (RTF/HTML) or low detail (text), and makes me think that XML along
127 * with some standard converters to turn XML into RTF/HTML/PDF/text/blah is the
128 * best choice.<br>
129 * This has the added benefit that it allows us to specify not just what output
130 * format is required, but also how that transformation is done, the fonts and
131 * layout details of the produced RTF/HTML are all very configurable.<br>
132 * It also turn out to be very easy in Java simply by using the XSL libraries
133 * produced by Sun and Apache. XSL libraries are freely available in all good
134 * languages. :-)<br>
135 * However there is still the question of how to marshal the XML into objects
136 * for manipulation. In Java there are many options - SAX/DOM/JDOM/JAXB -
137 * ordered in my opinion from worst for this job (SAX) to best for the job
138 * (JAXB) however JAXB is still very alpha so I am currently using JDOM and
139 * I've implemented some classes to hide the marshalling method for all but the
140 * most fancy of Books.
141 *
142 * <p>Pointers are used to request BookData from a Book and are also used as a
143 * reply from a search - so we have Pointers that tell us where the word
144 * "aaron" exists in a particular Book. For the case of a Bible a pointer could
145 * look like this: "Gen 1:1, Isa 45:2, Rev 20:4", for the case of a dictionary
146 * a pointer would be like this: "aaron", or for a BookDriver that contained
147 * sermons: "page 153, para 4-5".<br>
148 * I have not placed a requirement on Pointers for them to apply only to single
149 * results, or even for the results to be contiguous (Pointers would be of
150 * little use as search answers if this was to be the case).<br>
151 * The only common feature of Pointers that I can think of is that they ought
152 * to be convertible to and from strings.<br>
153 *
154 * <p>For the Bible case a Pointers is a collection of verses, and ProjectB has
155 * a set of classes called Verse, VerseRange and Passage which are a
156 * fundamental building block. Passage is a specialization of Pointers where
157 * the Book in question is a Pointer. The Passage package has classes to do all
158 * sorts of useful manipulations to lists of verses.
159 */
160 public class DesignIntro
161 {
162 }
163