1
20 package org.crosswire.jsword.book.sword;
21
22 import java.util.List;
23
24 import org.crosswire.jsword.JSOtherMsg;
25 import org.crosswire.jsword.book.BookException;
26 import org.crosswire.jsword.book.BookMetaData;
27 import org.crosswire.jsword.book.OSISUtil;
28 import org.crosswire.jsword.book.basic.AbstractPassageBook;
29 import org.crosswire.jsword.book.filter.SourceFilter;
30 import org.crosswire.jsword.book.sword.processing.RawTextToXmlProcessor;
31 import org.crosswire.jsword.passage.Key;
32 import org.crosswire.jsword.passage.KeyUtil;
33 import org.crosswire.jsword.passage.NoSuchKeyException;
34 import org.crosswire.jsword.passage.PassageKeyFactory;
35 import org.crosswire.jsword.passage.VerseKey;
36 import org.crosswire.jsword.versification.Versification;
37 import org.jdom2.Attribute;
38 import org.jdom2.Content;
39 import org.jdom2.Element;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43
49 public class SwordBook extends AbstractPassageBook {
50
56 public SwordBook(SwordBookMetaData sbmd, Backend<?> backend) {
57 super(sbmd, backend);
58
59 this.filter = sbmd.getFilter();
60
61 if (backend == null) {
62 throw new IllegalArgumentException("AbstractBackend must not be null.");
63 }
64 }
65
66
69 public final Key getGlobalKeyList() {
70 if (global == null) {
71 try {
72 global = getBackend().getGlobalKeyList();
73 return global;
74 } catch (UnsupportedOperationException ex) {
75 log.debug(ex.getMessage());
77 } catch (BookException ex) {
78 log.debug(ex.getMessage());
81 }
82
83 Versification v11n = super.getVersification();
84
85 global = super.createEmptyKeyList();
86 Key all = PassageKeyFactory.instance().getGlobalKeyList(v11n);
87
88 for (Key key : all) {
89 if (contains(key)) {
90 global.addAll(key);
91 }
92 }
93 }
94
95 return global;
96 }
97
98
101 @Override
102 public Key getScope() {
103 SwordBookMetaData sbmd = (SwordBookMetaData) getBookMetaData();
104 if (sbmd.getProperty(BookMetaData.KEY_VERSIFICATION) == null) {
106 return null;
108 }
109
110 Object keyString = sbmd.getProperty(BookMetaData.KEY_SCOPE);
111
112 if (keyString != null) {
113 try {
114 return getKey((String) keyString);
115 } catch (NoSuchKeyException ex) {
116 log.error("Unable to parse scope from book", ex);
118 return null;
119 }
120 }
121
122 Key bookKeys = getGlobalKeyList();
125
126 if (!(bookKeys instanceof VerseKey)) {
128 log.error("Global key list isn't a verse key. A very expensive no-op has just occurred.");
129 return null;
130 }
131
132 return bookKeys;
133 }
134
135
138 public boolean contains(Key key) {
139 return getBackend().contains(key);
140 }
141
142
145 public String getRawText(Key key) throws BookException {
146 return getBackend().getRawText(key);
147 }
148
149 @Override
150 protected List<Content> getOsis(Key key, RawTextToXmlProcessor processor) throws BookException {
151 List<Content> result = getBackend().readToOsis(key, processor);
152 assert result != null;
153 return result;
154 }
155
156 @Override
157 public void addOSIS(Key key, Element div, List<Content> osisContent) {
158 for (Content content : osisContent) {
161 if (content instanceof Element) {
162 Element ele = (Element) content;
163 if (ele.getName().equals(OSISUtil.OSIS_ELEMENT_VERSE)) {
164 super.addOSIS(key, div, osisContent);
165 return;
166 }
167 }
168 }
169
170 if (KeyUtil.getVerse(key).getVerse() == 0) {
173 super.addOSIS(key, div, osisContent);
174 } else {
175 Element everse = OSISUtil.factory().createVerse();
178 everse.setAttribute(OSISUtil.OSIS_ATTR_OSISID, key.getOsisID());
179 div.addContent(everse);
180 super.addOSIS(key, everse, osisContent);
181 }
182 }
183
184 @Override
185 public void addOSIS(Key key, List<Content> contentList, List<Content> osisContent) {
186 if (osisContent.size() == 0) {
188 return;
189 }
190
191 if (KeyUtil.getVerse(key).getVerse() == 0) {
194 Element div = OSISUtil.factory().createDiv();
195 div.setAttribute(OSISUtil.OSIS_ATTR_OSISID, key.getOsisID());
196 div.setAttribute(OSISUtil.OSIS_ATTR_TYPE, OSISUtil.GENERATED_CONTENT);
198 div.addContent(osisContent);
200 contentList.add(div);
202 return;
203 }
204
205
223 int start = 0;
226 int found = -1;
227 boolean wrapped = false;
228 Element preverse = null;
229 for (Content content : osisContent) {
230 if (content instanceof Element) {
231 Element ele = (Element) content;
232 String name = ele.getName();
233 if (OSISUtil.OSIS_ELEMENT_VERSE.equals(name)) {
234 wrapped = true;
235 continue;
236 }
237 Attribute typeAttr = ele.getAttribute(OSISUtil.OSIS_ATTR_TYPE);
238 Attribute subTypeAttr = ele.getAttribute(OSISUtil.OSIS_ATTR_SUBTYPE);
239 if (subTypeAttr != null && "x-preverse".equals(subTypeAttr.getValue())) {
240 if (OSISUtil.OSIS_ELEMENT_DIV.equals(name) || OSISUtil.OSIS_ELEMENT_TITLE.equals(name)) {
241 preverse = ele;
242 found = start;
243 }
244 } else if (typeAttr != null && "psalm".equals(typeAttr.getValue()) && OSISUtil.OSIS_ELEMENT_TITLE.equals(name)) {
245 Attribute canonicalAttr = ele.getAttribute(OSISUtil.OSIS_ATTR_CANONICAL);
248 if (canonicalAttr == null) {
249 ele.setAttribute(OSISUtil.OSIS_ATTR_CANONICAL, "true");
250 }
251 if (subTypeAttr == null) {
252 ele.setAttribute(OSISUtil.OSIS_ATTR_SUBTYPE, "x-preverse");
253 preverse = ele;
254 found = start;
255 }
256 }
257 }
258 start++;
259 }
260
261 if (wrapped) {
263 super.addOSIS(key, contentList, osisContent);
264 return;
265 }
266
267 Element everse = OSISUtil.factory().createVerse();
270 everse.setAttribute(OSISUtil.OSIS_ATTR_OSISID, key.getOsisID());
271 if (preverse == null) {
272 everse.addContent(osisContent);
273 } else {
274 List<Content> sublist = osisContent.subList(found + 1, osisContent.size());
275 everse.addContent(sublist);
276 sublist.clear();
279 super.addOSIS(key, contentList, osisContent);
281 }
282 contentList.add(everse);
284 }
285
286 @Override
287 public boolean isWritable() {
288 return getBackend().isWritable();
289 }
290
291
294 public void setRawText(Key key, String rawData) throws BookException {
295 throw new BookException(JSOtherMsg.lookupText("This Book is read-only."));
296 }
297
298
301 public void setAliasKey(Key alias, Key source) throws BookException {
302 getBackend().setAliasKey(alias, source);
303 }
304
305
308 @Override
309 protected SourceFilter getFilter() {
310 return filter;
311 }
312
313
316 private SourceFilter filter;
317
318
321 private Key global;
322
323
326 private static final Logger log = LoggerFactory.getLogger(SwordBook.class);
327 }
328