1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
package org.crosswire.jsword.book.sword; |
21 | |
|
22 | |
import java.io.File; |
23 | |
import java.io.IOException; |
24 | |
import java.io.PrintWriter; |
25 | |
import java.io.Writer; |
26 | |
import java.net.URI; |
27 | |
import java.util.ArrayList; |
28 | |
import java.util.Arrays; |
29 | |
import java.util.Collection; |
30 | |
import java.util.Collections; |
31 | |
import java.util.HashMap; |
32 | |
import java.util.HashSet; |
33 | |
import java.util.Iterator; |
34 | |
import java.util.List; |
35 | |
import java.util.Map; |
36 | |
import java.util.Set; |
37 | |
import java.util.regex.Pattern; |
38 | |
|
39 | |
import org.crosswire.common.util.Filter; |
40 | |
import org.crosswire.common.util.IOUtil; |
41 | |
import org.crosswire.common.util.IniSection; |
42 | |
import org.crosswire.common.util.Language; |
43 | |
import org.crosswire.common.util.NetUtil; |
44 | |
import org.crosswire.common.util.PropertyMap; |
45 | |
import org.crosswire.common.xml.XMLUtil; |
46 | |
import org.crosswire.jsword.JSMsg; |
47 | |
import org.crosswire.jsword.book.BookCategory; |
48 | |
import org.crosswire.jsword.book.BookException; |
49 | |
import org.crosswire.jsword.book.FeatureType; |
50 | |
import org.crosswire.jsword.book.KeyType; |
51 | |
import org.crosswire.jsword.book.MetaDataLocator; |
52 | |
import org.crosswire.jsword.book.OSISUtil; |
53 | |
import org.crosswire.jsword.book.basic.AbstractBookMetaData; |
54 | |
import org.crosswire.jsword.book.filter.SourceFilter; |
55 | |
import org.crosswire.jsword.book.filter.SourceFilterFactory; |
56 | |
import org.crosswire.jsword.versification.system.Versifications; |
57 | |
import org.jdom2.Document; |
58 | |
import org.jdom2.Element; |
59 | |
import org.slf4j.Logger; |
60 | |
import org.slf4j.LoggerFactory; |
61 | |
|
62 | |
|
63 | |
|
64 | |
|
65 | |
|
66 | |
|
67 | |
|
68 | |
|
69 | |
|
70 | |
|
71 | |
|
72 | |
|
73 | |
|
74 | |
|
75 | |
|
76 | |
|
77 | |
|
78 | |
|
79 | |
|
80 | |
|
81 | |
|
82 | |
|
83 | |
|
84 | |
|
85 | |
|
86 | |
|
87 | |
|
88 | |
|
89 | |
|
90 | |
|
91 | |
|
92 | |
|
93 | |
|
94 | |
|
95 | |
|
96 | |
|
97 | |
public final class SwordBookMetaData extends AbstractBookMetaData { |
98 | |
|
99 | |
|
100 | |
|
101 | |
|
102 | |
|
103 | |
|
104 | |
|
105 | |
|
106 | |
|
107 | |
public static final String KEY_ABBREVIATION = "Abbreviation"; |
108 | |
public static final String KEY_ABOUT = "About"; |
109 | |
public static final String KEY_BLOCK_COUNT = "BlockCount"; |
110 | |
public static final String KEY_BLOCK_TYPE = "BlockType"; |
111 | |
public static final String KEY_CASE_SENSITIVE_KEYS = "CaseSensitiveKeys"; |
112 | |
public static final String KEY_CIPHER_KEY = "CipherKey"; |
113 | |
public static final String KEY_COMPRESS_TYPE = "CompressType"; |
114 | |
public static final String KEY_COPYRIGHT = "Copyright"; |
115 | |
public static final String KEY_COPYRIGHT_CONTACT_ADDRESS = "CopyrightContactAddress"; |
116 | |
public static final String KEY_COPYRIGHT_CONTACT_EMAIL = "CopyrightContactEmail"; |
117 | |
public static final String KEY_COPYRIGHT_CONTACT_NAME = "CopyrightContactName"; |
118 | |
public static final String KEY_COPYRIGHT_CONTACT_NOTES = "CopyrightContactNotes"; |
119 | |
public static final String KEY_COPYRIGHT_DATE = "CopyrightDate"; |
120 | |
public static final String KEY_COPYRIGHT_HOLDER = "CopyrightHolder"; |
121 | |
public static final String KEY_COPYRIGHT_NOTES = "CopyrightNotes"; |
122 | |
public static final String KEY_DATA_PATH = "DataPath"; |
123 | |
public static final String KEY_DESCRIPTION = "Description"; |
124 | |
public static final String KEY_DIRECTION = "Direction"; |
125 | |
public static final String KEY_DISPLAY_LEVEL = "DisplayLevel"; |
126 | |
public static final String KEY_DISTRIBUTION_LICENSE = "DistributionLicense"; |
127 | |
public static final String KEY_DISTRIBUTION_NOTES = "DistributionNotes"; |
128 | |
public static final String KEY_DISTRIBUTION_SOURCE = "DistributionSource"; |
129 | |
public static final String KEY_ENCODING = "Encoding"; |
130 | |
public static final String KEY_FEATURE = "Feature"; |
131 | |
public static final String KEY_GLOBAL_OPTION_FILTER = "GlobalOptionFilter"; |
132 | |
public static final String KEY_SIGLUM1 = "Siglum1"; |
133 | |
public static final String KEY_SIGLUM2 = "Siglum2"; |
134 | |
public static final String KEY_SIGLUM3 = "Siglum3"; |
135 | |
public static final String KEY_SIGLUM4 = "Siglum4"; |
136 | |
public static final String KEY_SIGLUM5 = "Siglum5"; |
137 | |
public static final String KEY_GLOSSARY_FROM = "GlossaryFrom"; |
138 | |
public static final String KEY_GLOSSARY_TO = "GlossaryTo"; |
139 | |
public static final String KEY_HISTORY = "History"; |
140 | |
public static final String KEY_INSTALL_SIZE = "InstallSize"; |
141 | |
public static final String KEY_KEY_TYPE = "KeyType"; |
142 | |
public static final String KEY_LCSH = "LCSH"; |
143 | |
public static final String KEY_LOCAL_STRIP_FILTER = "LocalStripFilter"; |
144 | |
public static final String KEY_MINIMUM_VERSION = "MinimumVersion"; |
145 | |
public static final String KEY_MOD_DRV = "ModDrv"; |
146 | |
public static final String KEY_OBSOLETES = "Obsoletes"; |
147 | |
public static final String KEY_OSIS_Q_TO_TICK = "OSISqToTick"; |
148 | |
public static final String KEY_OSIS_VERSION = "OSISVersion"; |
149 | |
public static final String KEY_PREFERRED_CSS_XHTML = "PreferredCSSXHTML"; |
150 | |
public static final String KEY_SEARCH_OPTION = "SearchOption"; |
151 | |
public static final String KEY_SHORT_COPYRIGHT = "ShortCopyright"; |
152 | |
public static final String KEY_SHORT_PROMO = "ShortPromo"; |
153 | |
public static final String KEY_SOURCE_TYPE = "SourceType"; |
154 | |
public static final String KEY_STRONGS_PADDING = "StrongsPadding"; |
155 | |
public static final String KEY_SWORD_VERSION_DATE = "SwordVersionDate"; |
156 | |
public static final String KEY_TEXT_SOURCE = "TextSource"; |
157 | |
public static final String KEY_UNLOCK_URL = "UnlockURL"; |
158 | |
public static final String KEY_VERSION = "Version"; |
159 | |
|
160 | |
|
161 | |
public static final Map<String, String> DEFAULTS; |
162 | |
static { |
163 | 0 | Map<String, String> tempMap = new HashMap<String, String>(); |
164 | 0 | tempMap.put(KEY_COMPRESS_TYPE, "LZSS"); |
165 | 0 | tempMap.put(KEY_BLOCK_TYPE, "CHAPTER"); |
166 | 0 | tempMap.put(KEY_BLOCK_COUNT, "200"); |
167 | 0 | tempMap.put(KEY_KEY_TYPE, "TreeKey"); |
168 | 0 | tempMap.put(KEY_VERSIFICATION, "KJV"); |
169 | 0 | tempMap.put(KEY_DIRECTION, "LtoR"); |
170 | 0 | tempMap.put(KEY_SOURCE_TYPE, "Plaintext"); |
171 | 0 | tempMap.put(KEY_ENCODING, "Latin-1"); |
172 | 0 | tempMap.put(KEY_DISPLAY_LEVEL, "1"); |
173 | 0 | tempMap.put(KEY_OSIS_Q_TO_TICK, "true"); |
174 | 0 | tempMap.put(KEY_VERSION, "1.0"); |
175 | 0 | tempMap.put(KEY_MINIMUM_VERSION, "1.5.1a"); |
176 | 0 | tempMap.put(KEY_CATEGORY, "Other"); |
177 | 0 | tempMap.put(KEY_LANG, "en"); |
178 | 0 | tempMap.put(KEY_DISTRIBUTION_LICENSE, "Public Domain"); |
179 | 0 | tempMap.put(KEY_CASE_SENSITIVE_KEYS, "false"); |
180 | 0 | tempMap.put(KEY_STRONGS_PADDING, "true"); |
181 | 0 | DEFAULTS = Collections.unmodifiableMap(tempMap); |
182 | |
} |
183 | |
|
184 | |
|
185 | |
|
186 | |
|
187 | |
|
188 | |
|
189 | |
|
190 | |
|
191 | |
|
192 | |
|
193 | |
|
194 | |
|
195 | 0 | public SwordBookMetaData(File file, URI bookRootPath) throws IOException, BookException { |
196 | 0 | this.installed = true; |
197 | 0 | this.configFile = file; |
198 | 0 | this.bookConf = file.getName(); |
199 | 0 | setLibrary(bookRootPath); |
200 | |
|
201 | 0 | this.configAll = new IniSection(); |
202 | 0 | this.filtered = true; |
203 | 0 | reload(keyKeepers); |
204 | 0 | } |
205 | |
|
206 | |
|
207 | |
|
208 | |
|
209 | |
|
210 | |
|
211 | |
|
212 | |
|
213 | |
|
214 | 0 | public SwordBookMetaData(byte[] buffer, String bookConf) throws IOException, BookException { |
215 | 0 | this.installed = false; |
216 | 0 | this.bookConf = bookConf; |
217 | 0 | this.supported = true; |
218 | 0 | this.configAll = new IniSection(); |
219 | 0 | this.filtered = true; |
220 | 0 | loadBuffer(buffer, keyKeepers); |
221 | 0 | adjustConfig(); |
222 | 0 | report(configAll); |
223 | 0 | } |
224 | |
|
225 | |
|
226 | |
|
227 | |
|
228 | |
@Override |
229 | |
public void reload() throws BookException { |
230 | 0 | reload(null); |
231 | 0 | } |
232 | |
|
233 | |
public void reload(Filter<String> keepers) throws BookException { |
234 | |
|
235 | |
|
236 | |
|
237 | 0 | if (!filtered && keepers == null) { |
238 | 0 | return; |
239 | |
} |
240 | 0 | this.supported = true; |
241 | 0 | if (configJSword != null) { |
242 | 0 | configJSword.clear(); |
243 | |
} |
244 | 0 | if (configFrontend != null) { |
245 | 0 | configFrontend.clear(); |
246 | |
} |
247 | |
try { |
248 | 0 | if (installed) { |
249 | 0 | loadFile(keepers); |
250 | |
} else { |
251 | 0 | byte[] buffer = IOUtil.getZipEntry(bookConf); |
252 | 0 | loadBuffer(buffer, keepers); |
253 | |
} |
254 | 0 | adjustConfig(); |
255 | 0 | report(configAll); |
256 | |
|
257 | 0 | this.configJSword = addConfig(MetaDataLocator.JSWORD); |
258 | 0 | this.configFrontend = addConfig(MetaDataLocator.FRONTEND); |
259 | 0 | } catch (IOException ex) { |
260 | 0 | throw new BookException("unable to load conf", ex); |
261 | 0 | } |
262 | 0 | } |
263 | |
|
264 | |
|
265 | |
|
266 | |
|
267 | |
@Override |
268 | |
public boolean isQuestionable() { |
269 | |
|
270 | 0 | return questionable; |
271 | |
} |
272 | |
|
273 | |
|
274 | |
|
275 | |
|
276 | |
@Override |
277 | |
public boolean isSupported() { |
278 | |
|
279 | 0 | return supported; |
280 | |
} |
281 | |
|
282 | |
|
283 | |
|
284 | |
|
285 | |
@Override |
286 | |
public boolean isEnciphered() { |
287 | 0 | String cipher = getProperty(KEY_CIPHER_KEY); |
288 | 0 | return cipher != null; |
289 | |
} |
290 | |
|
291 | |
|
292 | |
|
293 | |
|
294 | |
@Override |
295 | |
public boolean isLocked() { |
296 | |
|
297 | 0 | String cipher = getProperty(KEY_CIPHER_KEY); |
298 | 0 | return cipher != null && cipher.length() == 0; |
299 | |
} |
300 | |
|
301 | |
|
302 | |
|
303 | |
|
304 | |
@Override |
305 | |
public boolean unlock(String unlockKey) { |
306 | |
|
307 | 0 | putProperty(KEY_CIPHER_KEY, unlockKey, false); |
308 | 0 | return true; |
309 | |
} |
310 | |
|
311 | |
|
312 | |
|
313 | |
|
314 | |
|
315 | |
|
316 | |
@Override |
317 | |
public String getUnlockKey() { |
318 | 0 | return getProperty(KEY_CIPHER_KEY); |
319 | |
} |
320 | |
|
321 | |
|
322 | |
|
323 | |
|
324 | |
|
325 | |
|
326 | |
public String getName() { |
327 | 0 | return getProperty(KEY_DESCRIPTION); |
328 | |
} |
329 | |
|
330 | |
|
331 | |
|
332 | |
|
333 | |
public String getBookCharset() { |
334 | 0 | return ENCODING_JAVA.get(getProperty(KEY_ENCODING)); |
335 | |
} |
336 | |
|
337 | |
|
338 | |
|
339 | |
|
340 | |
|
341 | |
@Override |
342 | |
public KeyType getKeyType() { |
343 | 0 | BookType bt = getBookType(); |
344 | 0 | if (bt == null) { |
345 | 0 | return null; |
346 | |
} |
347 | 0 | return bt.getKeyType(); |
348 | |
} |
349 | |
|
350 | |
|
351 | |
|
352 | |
|
353 | |
public BookType getBookType() { |
354 | 0 | return bookType; |
355 | |
} |
356 | |
|
357 | |
|
358 | |
|
359 | |
|
360 | |
public SourceFilter getFilter() { |
361 | 0 | String sourcetype = getProperty(KEY_SOURCE_TYPE); |
362 | 0 | return SourceFilterFactory.getFilter(sourcetype); |
363 | |
} |
364 | |
|
365 | |
|
366 | |
|
367 | |
|
368 | |
|
369 | |
|
370 | |
|
371 | |
public File getConfigFile() { |
372 | 0 | return configFile; |
373 | |
} |
374 | |
|
375 | |
|
376 | |
|
377 | |
|
378 | |
|
379 | |
public BookCategory getBookCategory() { |
380 | 0 | if (bookCat == null) { |
381 | 0 | bookCat = (BookCategory) getValue(KEY_CATEGORY); |
382 | 0 | if (bookCat == BookCategory.OTHER) { |
383 | 0 | BookType bt = getBookType(); |
384 | 0 | if (bt == null) { |
385 | 0 | return bookCat; |
386 | |
} |
387 | 0 | bookCat = bt.getBookCategory(); |
388 | |
} |
389 | |
} |
390 | 0 | return bookCat; |
391 | |
} |
392 | |
|
393 | |
|
394 | |
|
395 | |
|
396 | |
|
397 | |
@Override |
398 | |
public Document toOSIS() { |
399 | 0 | List<String> knownKeys = new ArrayList(configAll.getKeys()); |
400 | 0 | OSISUtil.OSISFactory factory = OSISUtil.factory(); |
401 | 0 | Element table = factory.createTable(); |
402 | 0 | Element row = toRow(factory, "Initials", getInitials()); |
403 | 0 | table.addContent(row); |
404 | |
|
405 | 0 | for (String key : OSIS_INFO) { |
406 | 0 | knownKeys.remove(key); |
407 | 0 | row = toRow(factory, key); |
408 | 0 | if (row != null) { |
409 | 0 | table.addContent(row); |
410 | |
} |
411 | |
} |
412 | |
|
413 | |
|
414 | 0 | List<String> hide = Arrays.asList(HIDDEN); |
415 | 0 | for (String key : knownKeys) { |
416 | 0 | if (hide.contains(key)) { |
417 | 0 | continue; |
418 | |
} |
419 | 0 | row = toRow(factory, key); |
420 | 0 | if (row != null) { |
421 | 0 | table.addContent(row); |
422 | |
} |
423 | |
} |
424 | 0 | return new Document(table); |
425 | |
} |
426 | |
|
427 | |
public static void normalize(Writer out, final IniSection config, final String[] order) { |
428 | 0 | PrintWriter writer = null; |
429 | 0 | if (out instanceof PrintWriter) { |
430 | 0 | writer = (PrintWriter) out; |
431 | |
} else { |
432 | 0 | writer = new PrintWriter(out); |
433 | |
} |
434 | 0 | IniSection copy = new IniSection(config); |
435 | |
|
436 | 0 | adjustHistory(copy); |
437 | |
|
438 | 0 | List<String> knownKeys = new ArrayList(copy.getKeys()); |
439 | 0 | writer.print("["); |
440 | 0 | writer.print(copy.getName()); |
441 | 0 | writer.print("]"); |
442 | 0 | writer.println(); |
443 | |
|
444 | |
|
445 | 0 | for (String key : order) { |
446 | 0 | knownKeys.remove(key); |
447 | 0 | if (!copy.containsKey(key)) { |
448 | 0 | continue; |
449 | |
} |
450 | 0 | Collection<String> values = copy.getValues(key); |
451 | 0 | Iterator<String> iter = values.iterator(); |
452 | |
String value; |
453 | 0 | while (iter.hasNext()) { |
454 | 0 | value = iter.next(); |
455 | 0 | String newKey = key; |
456 | |
|
457 | 0 | if (KEY_HISTORY.equalsIgnoreCase(key)) { |
458 | 0 | int pos = value.indexOf(' '); |
459 | 0 | newKey += '_' + value.substring(0, pos); |
460 | 0 | value = value.substring(pos + 1); |
461 | |
} |
462 | 0 | writer.print(newKey); |
463 | 0 | writer.print("="); |
464 | 0 | writer.print(value.replaceAll("\n", " \\\\\n")); |
465 | 0 | writer.println(); |
466 | 0 | } |
467 | |
} |
468 | |
|
469 | 0 | Iterator<String> keys = knownKeys.iterator(); |
470 | 0 | while (keys.hasNext()) { |
471 | 0 | String key = keys.next(); |
472 | 0 | Collection<String> values = copy.getValues(key); |
473 | 0 | Iterator<String> iter = values.iterator(); |
474 | |
String value; |
475 | 0 | while (iter.hasNext()) { |
476 | 0 | value = iter.next(); |
477 | 0 | writer.print(key); |
478 | 0 | writer.print("="); |
479 | 0 | writer.print(value.replaceAll("\n", " \\\\\n")); |
480 | 0 | writer.println(); |
481 | |
} |
482 | 0 | } |
483 | |
|
484 | 0 | writer.flush(); |
485 | 0 | } |
486 | |
|
487 | |
|
488 | |
|
489 | |
|
490 | |
public String getInitials() { |
491 | 0 | return configAll.getName(); |
492 | |
} |
493 | |
|
494 | |
|
495 | |
|
496 | |
|
497 | |
|
498 | |
String getInternalName() { |
499 | 0 | return configAll.getName(); |
500 | |
} |
501 | |
|
502 | |
|
503 | |
|
504 | |
|
505 | |
public String getAbbreviation() { |
506 | 0 | String abbreviation = getProperty(KEY_ABBREVIATION); |
507 | 0 | if (abbreviation != null && abbreviation.length() > 0) { |
508 | 0 | return abbreviation; |
509 | |
} |
510 | 0 | return getInitials(); |
511 | |
} |
512 | |
|
513 | |
|
514 | |
|
515 | |
|
516 | |
public boolean isLeftToRight() { |
517 | |
|
518 | |
|
519 | 0 | String dir = getProperty(KEY_DIRECTION); |
520 | 0 | if (ConfigEntryType.DIRECTION_BIDI.equalsIgnoreCase(dir)) { |
521 | |
|
522 | |
|
523 | 0 | Language lang = getLanguage(); |
524 | 0 | return lang.isLeftToRight(); |
525 | |
} |
526 | |
|
527 | 0 | return ConfigEntryType.DIRECTION_LTOR.equalsIgnoreCase(dir); |
528 | |
} |
529 | |
|
530 | |
|
531 | |
|
532 | |
|
533 | |
@Override |
534 | |
public boolean hasFeature(FeatureType feature) { |
535 | 0 | String name = feature.toString(); |
536 | |
|
537 | |
|
538 | 0 | if (configAll.containsValue(KEY_FEATURE, name)) { |
539 | 0 | return true; |
540 | |
} |
541 | |
|
542 | |
|
543 | |
|
544 | 0 | StringBuilder buffer = new StringBuilder(getProperty(KEY_SOURCE_TYPE)); |
545 | 0 | buffer.append(name); |
546 | 0 | if (configAll.containsValue(KEY_GLOBAL_OPTION_FILTER, buffer.toString())) { |
547 | 0 | return true; |
548 | |
} |
549 | |
|
550 | |
|
551 | 0 | String alias = feature.getAlias(); |
552 | 0 | buffer.setLength(0); |
553 | 0 | buffer.append(getProperty(KEY_SOURCE_TYPE)); |
554 | 0 | buffer.append(alias); |
555 | |
|
556 | |
|
557 | 0 | return configAll.containsValue(KEY_GLOBAL_OPTION_FILTER, name) || configAll.containsValue(KEY_GLOBAL_OPTION_FILTER, buffer.toString()); |
558 | |
|
559 | |
} |
560 | |
|
561 | |
|
562 | |
|
563 | |
|
564 | |
public Set<String> getPropertyKeys() { |
565 | 0 | return null; |
566 | |
} |
567 | |
|
568 | |
|
569 | |
|
570 | |
|
571 | |
public String getProperty(String key) { |
572 | 0 | if (KEY_LANGUAGE.equals(key)) { |
573 | 0 | return getLanguage().getName(); |
574 | |
} |
575 | 0 | return configAll.get(key, DEFAULTS.get(key)); |
576 | |
} |
577 | |
|
578 | |
|
579 | |
|
580 | |
|
581 | |
public void setProperty(String key, String value) { |
582 | 0 | configAll.replace(key, value); |
583 | 0 | } |
584 | |
|
585 | |
|
586 | |
|
587 | |
|
588 | |
public void putProperty(String key, String value, boolean forFrontend) { |
589 | 0 | MetaDataLocator mdl = forFrontend ? MetaDataLocator.FRONTEND : MetaDataLocator.JSWORD; |
590 | 0 | putProperty(key, value, mdl); |
591 | 0 | } |
592 | |
|
593 | |
|
594 | |
|
595 | |
|
596 | |
|
597 | |
|
598 | |
|
599 | |
|
600 | |
public void putProperty(String key, String value, MetaDataLocator metaDataLocator) { |
601 | |
|
602 | 0 | setProperty(key, value); |
603 | |
|
604 | |
|
605 | 0 | if (!installed) { |
606 | 0 | return; |
607 | |
} |
608 | |
|
609 | 0 | File writeLocation = metaDataLocator.getWriteLocation(); |
610 | |
|
611 | 0 | if (writeLocation == null) { |
612 | 0 | return; |
613 | |
} |
614 | |
|
615 | |
|
616 | 0 | IniSection config = null; |
617 | 0 | switch (metaDataLocator) { |
618 | |
case FRONTEND: |
619 | 0 | if (this.configFrontend == null) { |
620 | 0 | this.configFrontend = new IniSection(configAll.getName()); |
621 | |
} |
622 | 0 | config = this.configFrontend; |
623 | 0 | break; |
624 | |
case JSWORD: |
625 | 0 | if (this.configJSword == null) { |
626 | 0 | this.configJSword = new IniSection(configAll.getName()); |
627 | |
} |
628 | 0 | config = this.configJSword; |
629 | 0 | break; |
630 | |
case TRANSIENT: |
631 | |
default: |
632 | |
break; |
633 | |
} |
634 | |
|
635 | 0 | if (config != null) { |
636 | 0 | config.replace(key, value); |
637 | |
try { |
638 | 0 | config.save(new File(writeLocation, bookConf), getBookCharset()); |
639 | 0 | } catch (IOException ex) { |
640 | 0 | LOGGER.error("Unable to save {}={}: conf file for [{}]; error={}", key, value, configAll.getName(), ex); |
641 | 0 | } |
642 | |
} |
643 | 0 | } |
644 | |
|
645 | |
|
646 | |
|
647 | |
|
648 | |
|
649 | |
|
650 | |
|
651 | |
public static void setPartialLoading(boolean partial) { |
652 | |
|
653 | 0 | if (partial != partialLoading) { |
654 | 0 | if (partial) { |
655 | 0 | keyKeepers = new KeyFilter(REQUIRED); |
656 | |
} else { |
657 | 0 | keyKeepers = null; |
658 | |
} |
659 | |
} |
660 | 0 | partialLoading = partial; |
661 | 0 | } |
662 | |
|
663 | |
|
664 | |
|
665 | |
|
666 | |
|
667 | |
|
668 | |
|
669 | |
|
670 | |
private void loadFile(Filter<String> keepers) throws IOException { |
671 | 0 | filtered = keepers != null; |
672 | |
|
673 | 0 | configAll.clear(); |
674 | 0 | configAll.load(configFile, ENCODING_UTF8, keepers); |
675 | 0 | String encoding = configAll.get(KEY_ENCODING); |
676 | 0 | if (!ENCODING_UTF8.equalsIgnoreCase(encoding)) { |
677 | 0 | configAll.clear(); |
678 | 0 | configAll.load(configFile, ENCODING_LATIN1, keepers); |
679 | |
} |
680 | 0 | } |
681 | |
|
682 | |
|
683 | |
|
684 | |
|
685 | |
|
686 | |
|
687 | |
|
688 | |
|
689 | |
private void loadBuffer(byte[] buffer, Filter<String> keepers) throws IOException { |
690 | 0 | filtered = keepers != null; |
691 | |
|
692 | 0 | configAll.clear(); |
693 | 0 | configAll.load(buffer, ENCODING_UTF8, keepers); |
694 | 0 | String encoding = configAll.get(KEY_ENCODING); |
695 | 0 | if (!ENCODING_UTF8.equalsIgnoreCase(encoding)) { |
696 | 0 | configAll.clear(); |
697 | 0 | configAll.load(buffer, ENCODING_LATIN1, keepers); |
698 | |
} |
699 | 0 | } |
700 | |
|
701 | |
private IniSection addConfig(MetaDataLocator locator) { |
702 | |
|
703 | 0 | File conf = new File(locator.getWriteLocation(), bookConf); |
704 | 0 | if (!conf.exists()) { |
705 | 0 | conf = new File(locator.getReadLocation(), bookConf); |
706 | |
} |
707 | |
|
708 | 0 | if (conf.exists()) { |
709 | |
|
710 | 0 | String encoding = getProperty(KEY_ENCODING); |
711 | |
try { |
712 | 0 | IniSection config = new IniSection(); |
713 | 0 | config.load(conf, encoding); |
714 | 0 | mergeConfig(config); |
715 | 0 | return config; |
716 | 0 | } catch (IOException e) { |
717 | 0 | LOGGER.error("Unable to load conf {}:{}", conf, e); |
718 | |
} |
719 | |
} |
720 | |
|
721 | 0 | return null; |
722 | |
} |
723 | |
|
724 | |
private void mergeConfig(IniSection config) { |
725 | 0 | for (String key : config.getKeys()) { |
726 | 0 | ConfigEntryType type = ConfigEntryType.fromString(key); |
727 | 0 | for (String value : config.getValues(key)) { |
728 | 0 | if (type != null && type.mayRepeat()) { |
729 | 0 | if (!configAll.containsValue(key, value)) { |
730 | 0 | configAll.add(key, value); |
731 | |
} |
732 | |
} else { |
733 | 0 | setProperty(key, value); |
734 | |
} |
735 | |
} |
736 | 0 | } |
737 | 0 | } |
738 | |
|
739 | |
|
740 | |
|
741 | |
|
742 | |
|
743 | |
|
744 | |
|
745 | |
|
746 | |
private Object getValue(String key) { |
747 | 0 | ConfigEntryType type = ConfigEntryType.fromString(key); |
748 | 0 | String ce = getProperty(key); |
749 | 0 | if (type == null) { |
750 | 0 | return ce; |
751 | |
} |
752 | |
|
753 | 0 | return ce == null ? null : type.convert(ce); |
754 | |
} |
755 | |
|
756 | |
private Element toRow(OSISUtil.OSISFactory factory, String key, String value) { |
757 | 0 | Element nameEle = toKeyCell(factory, key); |
758 | |
|
759 | 0 | Element valueElement = factory.createCell(); |
760 | 0 | valueElement.addContent(value); |
761 | |
|
762 | |
|
763 | 0 | Element rowEle = factory.createRow(); |
764 | 0 | rowEle.addContent(nameEle); |
765 | 0 | rowEle.addContent(valueElement); |
766 | 0 | return rowEle; |
767 | |
} |
768 | |
|
769 | |
private Element toRow(OSISUtil.OSISFactory factory, String key) { |
770 | 0 | int size = configAll.size(key); |
771 | 0 | if (size == 0) { |
772 | 0 | return null; |
773 | |
} |
774 | |
|
775 | |
|
776 | 0 | ConfigEntryType type = ConfigEntryType.fromString(key); |
777 | 0 | Element nameEle = toKeyCell(factory, key); |
778 | |
|
779 | 0 | Element valueElement = factory.createCell(); |
780 | 0 | for (int j = 0; j < size; j++) { |
781 | 0 | if (j > 0) { |
782 | 0 | valueElement.addContent(factory.createLB()); |
783 | |
} |
784 | |
|
785 | 0 | String text = configAll.get(key, j); |
786 | 0 | if (type != null && !type.isText() && type.isAllowed(text)) { |
787 | 0 | text = type.convert(text).toString(); |
788 | |
} |
789 | 0 | text = XMLUtil.escape(text); |
790 | 0 | if (type != null && type.allowsRTF()) { |
791 | 0 | valueElement.addContent(OSISUtil.rtfToOsis(text)); |
792 | |
} else { |
793 | 0 | valueElement.addContent(text); |
794 | |
} |
795 | |
} |
796 | |
|
797 | |
|
798 | 0 | Element rowEle = factory.createRow(); |
799 | 0 | rowEle.addContent(nameEle); |
800 | 0 | rowEle.addContent(valueElement); |
801 | |
|
802 | 0 | return rowEle; |
803 | |
} |
804 | |
|
805 | |
private Element toKeyCell(OSISUtil.OSISFactory factory, String key) { |
806 | 0 | Element nameEle = factory.createCell(); |
807 | 0 | Element hiEle = factory.createHI(); |
808 | 0 | hiEle.setAttribute(OSISUtil.OSIS_ATTR_TYPE, OSISUtil.HI_BOLD); |
809 | 0 | nameEle.addContent(hiEle); |
810 | |
|
811 | 0 | hiEle.addContent(key); |
812 | 0 | return nameEle; |
813 | |
} |
814 | |
|
815 | |
private void adjustConfig() throws BookException { |
816 | 0 | adjustLocation(); |
817 | 0 | adjustLanguage(); |
818 | 0 | adjustBookType(); |
819 | 0 | adjustName(); |
820 | 0 | adjustHistory(configAll); |
821 | 0 | } |
822 | |
|
823 | |
private void adjustLanguage() { |
824 | 0 | String lang = getProperty(KEY_LANG); |
825 | 0 | testLanguage(KEY_LANG, lang); |
826 | |
|
827 | 0 | String langFrom = configAll.get(KEY_GLOSSARY_FROM); |
828 | 0 | String langTo = configAll.get(KEY_GLOSSARY_TO); |
829 | |
|
830 | |
|
831 | 0 | if (langFrom != null || langTo != null) { |
832 | 0 | if (langFrom == null) { |
833 | 0 | langFrom = lang; |
834 | 0 | setProperty(KEY_GLOSSARY_FROM, langFrom); |
835 | 0 | LOGGER.warn("Missing data for [{}]. Assuming {}={}", configAll.getName(), KEY_GLOSSARY_FROM, langFrom); |
836 | |
} |
837 | 0 | testLanguage(KEY_GLOSSARY_FROM, langFrom); |
838 | |
|
839 | 0 | if (langTo == null) { |
840 | 0 | langTo = Language.DEFAULT_LANG.getGivenSpecification(); |
841 | 0 | setProperty(KEY_GLOSSARY_TO, langTo); |
842 | 0 | LOGGER.warn("Missing data for [{}]. Assuming {}={}", configAll.getName(), KEY_GLOSSARY_TO, langTo); |
843 | |
} |
844 | 0 | testLanguage(KEY_GLOSSARY_TO, langTo); |
845 | |
|
846 | |
|
847 | 0 | if (!langFrom.equals(lang) && !langTo.equals(lang)) { |
848 | 0 | LOGGER.error("Data error in [{}]. Neither {} or {} match {}", configAll.getName(), KEY_GLOSSARY_FROM, KEY_GLOSSARY_TO, KEY_LANG); |
849 | |
} |
850 | |
} |
851 | |
|
852 | 0 | setLanguage((Language) getValue(KEY_LANG)); |
853 | 0 | } |
854 | |
|
855 | |
private void testLanguage(String key, String lang) { |
856 | 0 | Language language = new Language(lang); |
857 | 0 | if (!language.isValidLanguage()) { |
858 | 0 | LOGGER.warn("Unknown language [{}]{}={}", configAll.getName(), key, lang); |
859 | |
} |
860 | 0 | } |
861 | |
|
862 | |
private void adjustBookType() { |
863 | |
|
864 | |
|
865 | 0 | BookCategory focusedCategory = (BookCategory) getValue(KEY_CATEGORY); |
866 | 0 | questionable = focusedCategory == BookCategory.QUESTIONABLE; |
867 | |
|
868 | 0 | String modTypeName = getProperty(KEY_MOD_DRV); |
869 | 0 | if (modTypeName == null) { |
870 | 0 | LOGGER.error("Book not supported: malformed conf file for [{}] no {} found.", configAll.getName(), KEY_MOD_DRV); |
871 | 0 | supported = false; |
872 | 0 | return; |
873 | |
} |
874 | |
|
875 | 0 | String v11n = getProperty(KEY_VERSIFICATION); |
876 | 0 | if (!Versifications.instance().isDefined(v11n)) { |
877 | 0 | LOGGER.error("Book not supported: Unknown versification for [{}]{}={}.", configAll.getName(), KEY_VERSIFICATION, v11n); |
878 | 0 | supported = false; |
879 | 0 | return; |
880 | |
} |
881 | |
|
882 | 0 | bookType = BookType.fromString(modTypeName); |
883 | 0 | if (bookType == null) { |
884 | 0 | LOGGER.error("Book not supported: malformed conf file for [{}] no book type found", configAll.getName()); |
885 | 0 | supported = false; |
886 | 0 | return; |
887 | |
} |
888 | |
|
889 | |
|
890 | |
|
891 | 0 | if (focusedCategory == BookCategory.OTHER) { |
892 | 0 | focusedCategory = bookType.getBookCategory(); |
893 | |
} |
894 | |
|
895 | 0 | setProperty(KEY_CATEGORY, focusedCategory.getName()); |
896 | 0 | } |
897 | |
|
898 | |
private void adjustName() { |
899 | |
|
900 | 0 | if (configAll.get(KEY_DESCRIPTION) == null) { |
901 | 0 | LOGGER.error("Malformed conf file: missing [{}]{}=. Using {}", configAll.getName(), KEY_DESCRIPTION, configAll.getName()); |
902 | 0 | setProperty(KEY_DESCRIPTION, configAll.getName()); |
903 | |
} |
904 | 0 | } |
905 | |
|
906 | |
|
907 | |
|
908 | |
private void adjustLocation() throws BookException { |
909 | |
|
910 | 0 | URI library = getLibrary(); |
911 | 0 | if (library == null) { |
912 | 0 | return; |
913 | |
} |
914 | |
|
915 | |
|
916 | |
|
917 | |
|
918 | |
|
919 | |
|
920 | 0 | String datapath = getProperty(KEY_DATA_PATH); |
921 | 0 | int lastSlash = datapath.lastIndexOf('/'); |
922 | |
|
923 | |
|
924 | |
|
925 | 0 | if (lastSlash == -1) { |
926 | 0 | return; |
927 | |
} |
928 | |
|
929 | |
|
930 | |
|
931 | 0 | boolean isDirectoryPath = false; |
932 | 0 | if (lastSlash == datapath.length() - 1) { |
933 | 0 | isDirectoryPath = true; |
934 | 0 | datapath = datapath.substring(0, lastSlash); |
935 | |
} |
936 | |
|
937 | 0 | URI location = NetUtil.lengthenURI(library, datapath); |
938 | 0 | File bookDir = new File(location.getPath()); |
939 | |
|
940 | |
|
941 | 0 | if (!bookDir.isDirectory()) { |
942 | 0 | if (isDirectoryPath) { |
943 | |
|
944 | 0 | throw new BookException(JSMsg.gettext("The book {0} is missing its data files", configAll.getName())); |
945 | |
} |
946 | |
|
947 | |
|
948 | |
|
949 | |
|
950 | 0 | if (!new File(location.getPath() + ".dat").exists()) { |
951 | |
|
952 | |
|
953 | 0 | throw new BookException(JSMsg.gettext("The book {0} is missing its data files", configAll.getName())); |
954 | |
} |
955 | |
|
956 | |
|
957 | |
|
958 | 0 | lastSlash = datapath.lastIndexOf('/'); |
959 | 0 | datapath = datapath.substring(0, lastSlash); |
960 | 0 | location = NetUtil.lengthenURI(library, datapath); |
961 | |
} |
962 | |
|
963 | 0 | setLocation(location); |
964 | 0 | } |
965 | |
|
966 | |
|
967 | |
|
968 | |
|
969 | |
private static void adjustHistory(IniSection config) { |
970 | |
|
971 | |
|
972 | |
|
973 | 0 | List<String> keys = new ArrayList(config.getKeys()); |
974 | 0 | for (String key : keys) { |
975 | 0 | String value = config.get(key); |
976 | 0 | ConfigEntryType type = ConfigEntryType.fromString(key); |
977 | 0 | if (ConfigEntryType.HISTORY.equals(type)) { |
978 | 0 | config.remove(key); |
979 | 0 | int pos = key.indexOf('_'); |
980 | 0 | value = key.substring(pos + 1) + ' ' + value; |
981 | 0 | config.add(KEY_HISTORY, value); |
982 | |
} |
983 | 0 | } |
984 | 0 | } |
985 | |
|
986 | |
public static void report(final IniSection config) { |
987 | 0 | StringBuilder buf = new StringBuilder(config.report()); |
988 | 0 | for (String key : config.getKeys()) { |
989 | 0 | ConfigEntryType type = ConfigEntryType.fromString(key); |
990 | |
|
991 | 0 | if (type == null) { |
992 | 0 | if (key.contains("_")) { |
993 | 0 | String baseKey = key.substring(0, key.indexOf('_')); |
994 | 0 | type = ConfigEntryType.fromString(baseKey); |
995 | |
} |
996 | |
} |
997 | |
|
998 | |
|
999 | 0 | int count = config.size(key); |
1000 | 0 | for (int i = 0; i < count; i++) { |
1001 | 0 | String value = config.get(key, i); |
1002 | |
|
1003 | |
|
1004 | 0 | if (type == null) { |
1005 | 0 | buf.append("Unknown entry: ").append(key).append(" = ").append(value).append('\n'); |
1006 | 0 | continue; |
1007 | |
} |
1008 | |
|
1009 | |
|
1010 | 0 | if (value.length() == 0 && type != ConfigEntryType.CIPHER_KEY) { |
1011 | 0 | buf.append("Unexpected empty entry: ").append(key).append(" = ").append(value).append('\n'); |
1012 | 0 | continue; |
1013 | |
} |
1014 | |
|
1015 | |
|
1016 | 0 | value = type.filter(value); |
1017 | |
|
1018 | |
|
1019 | 0 | if (!type.allowsRTF() && RTF_PATTERN.matcher(value).find()) { |
1020 | 0 | buf.append("Unexpected RTF: ").append(key).append(" = ").append(value).append('\n'); |
1021 | |
} |
1022 | |
|
1023 | 0 | if (!type.allowsHTML() && HTML_PATTERN.matcher(value).find()) { |
1024 | 0 | buf.append("Unexpected HTML: ").append(key).append(" = ").append(value).append('\n'); |
1025 | |
} |
1026 | |
|
1027 | 0 | if (!type.isAllowed(value)) { |
1028 | 0 | buf.append("Unknown config value: ").append(key).append(" = ").append(value).append('\n'); |
1029 | |
} |
1030 | |
|
1031 | 0 | if (count > 1 && !type.mayRepeat()) { |
1032 | 0 | buf.append("Unexpected repeated config key: ").append(key).append(" = ").append(value).append('\n'); |
1033 | |
} |
1034 | |
} |
1035 | 0 | } |
1036 | 0 | if (buf.length() > 0) { |
1037 | 0 | LOGGER.info("Conf report for [{}]\n{}", config.getName(), buf.toString()); |
1038 | |
} |
1039 | 0 | } |
1040 | |
|
1041 | |
|
1042 | |
|
1043 | |
|
1044 | |
private boolean installed; |
1045 | |
|
1046 | |
|
1047 | |
|
1048 | |
|
1049 | |
|
1050 | |
private boolean filtered; |
1051 | |
|
1052 | |
|
1053 | |
|
1054 | |
|
1055 | |
private String bookConf; |
1056 | |
|
1057 | |
|
1058 | |
|
1059 | |
|
1060 | |
|
1061 | |
private IniSection configAll; |
1062 | |
|
1063 | |
|
1064 | |
|
1065 | |
|
1066 | |
private IniSection configJSword; |
1067 | |
|
1068 | |
|
1069 | |
|
1070 | |
|
1071 | |
private IniSection configFrontend; |
1072 | |
|
1073 | |
|
1074 | |
|
1075 | |
|
1076 | |
private boolean supported; |
1077 | |
|
1078 | |
|
1079 | |
|
1080 | |
|
1081 | |
private BookCategory bookCat; |
1082 | |
|
1083 | |
|
1084 | |
|
1085 | |
|
1086 | |
private BookType bookType; |
1087 | |
|
1088 | |
|
1089 | |
|
1090 | |
|
1091 | |
private boolean questionable; |
1092 | |
|
1093 | |
|
1094 | |
|
1095 | |
|
1096 | |
|
1097 | |
private File configFile; |
1098 | |
|
1099 | |
|
1100 | |
|
1101 | |
|
1102 | 0 | private static final String[] REQUIRED = { |
1103 | |
KEY_ABBREVIATION, |
1104 | |
KEY_DESCRIPTION, |
1105 | |
KEY_LANG, |
1106 | |
KEY_CATEGORY, |
1107 | |
KEY_VERSION, |
1108 | |
KEY_FEATURE, |
1109 | |
KEY_GLOBAL_OPTION_FILTER, |
1110 | |
KEY_SIGLUM1, |
1111 | |
KEY_SIGLUM2, |
1112 | |
KEY_SIGLUM3, |
1113 | |
KEY_SIGLUM4, |
1114 | |
KEY_SIGLUM5, |
1115 | |
KEY_FONT, |
1116 | |
KEY_DATA_PATH, |
1117 | |
KEY_MOD_DRV, |
1118 | |
KEY_SOURCE_TYPE, |
1119 | |
KEY_BLOCK_TYPE, |
1120 | |
KEY_BLOCK_COUNT, |
1121 | |
KEY_COMPRESS_TYPE, |
1122 | |
KEY_ENCODING, |
1123 | |
KEY_DIRECTION, |
1124 | |
KEY_KEY_TYPE, |
1125 | |
KEY_DISPLAY_LEVEL, |
1126 | |
KEY_VERSIFICATION, |
1127 | |
KEY_CASE_SENSITIVE_KEYS, |
1128 | |
KEY_LOCAL_STRIP_FILTER, |
1129 | |
KEY_PREFERRED_CSS_XHTML, |
1130 | |
KEY_STRONGS_PADDING, |
1131 | |
KEY_SEARCH_OPTION, |
1132 | |
KEY_INSTALL_SIZE, |
1133 | |
KEY_SCOPE, |
1134 | |
KEY_BOOKLIST, |
1135 | |
KEY_CIPHER_KEY |
1136 | |
}; |
1137 | |
|
1138 | |
|
1139 | |
|
1140 | |
|
1141 | |
|
1142 | 0 | private static final class KeyFilter implements Filter<String> { |
1143 | |
|
1144 | |
|
1145 | |
|
1146 | |
|
1147 | 0 | KeyFilter(String[] keepers) { |
1148 | 0 | this.keepers = new HashSet(); |
1149 | |
|
1150 | |
|
1151 | 0 | for (String key : keepers) { |
1152 | 0 | this.keepers.add(key); |
1153 | |
} |
1154 | 0 | } |
1155 | |
public boolean test(String key) { |
1156 | 0 | return keepers.contains(key); |
1157 | |
} |
1158 | |
private Set keepers; |
1159 | |
} |
1160 | |
|
1161 | |
private static boolean partialLoading; |
1162 | |
|
1163 | |
private static Filter keyKeepers; |
1164 | |
|
1165 | 0 | private static final String[] OSIS_INFO = { |
1166 | |
KEY_ABBREVIATION, |
1167 | |
KEY_DESCRIPTION, |
1168 | |
KEY_LANG, |
1169 | |
KEY_CATEGORY, |
1170 | |
KEY_LCSH, |
1171 | |
KEY_SWORD_VERSION_DATE, |
1172 | |
KEY_VERSION, |
1173 | |
KEY_HISTORY, |
1174 | |
KEY_OBSOLETES, |
1175 | |
KEY_GLOSSARY_FROM, |
1176 | |
KEY_GLOSSARY_TO, |
1177 | |
KEY_ABOUT, |
1178 | |
KEY_SHORT_PROMO, |
1179 | |
KEY_DISTRIBUTION_LICENSE, |
1180 | |
KEY_DISTRIBUTION_NOTES, |
1181 | |
KEY_DISTRIBUTION_SOURCE, |
1182 | |
KEY_SHORT_COPYRIGHT, |
1183 | |
KEY_COPYRIGHT, |
1184 | |
KEY_COPYRIGHT_DATE, |
1185 | |
KEY_COPYRIGHT_HOLDER, |
1186 | |
KEY_COPYRIGHT_CONTACT_NAME, |
1187 | |
KEY_COPYRIGHT_CONTACT_ADDRESS, |
1188 | |
KEY_COPYRIGHT_CONTACT_EMAIL, |
1189 | |
KEY_COPYRIGHT_CONTACT_NOTES, |
1190 | |
KEY_COPYRIGHT_NOTES, |
1191 | |
KEY_TEXT_SOURCE, |
1192 | |
KEY_FEATURE, |
1193 | |
KEY_GLOBAL_OPTION_FILTER, |
1194 | |
KEY_SIGLUM1, |
1195 | |
KEY_SIGLUM2, |
1196 | |
KEY_SIGLUM3, |
1197 | |
KEY_SIGLUM4, |
1198 | |
KEY_SIGLUM5, |
1199 | |
KEY_FONT, |
1200 | |
KEY_DATA_PATH, |
1201 | |
KEY_MOD_DRV, |
1202 | |
KEY_SOURCE_TYPE, |
1203 | |
KEY_BLOCK_TYPE, |
1204 | |
KEY_BLOCK_COUNT, |
1205 | |
KEY_COMPRESS_TYPE, |
1206 | |
KEY_ENCODING, |
1207 | |
KEY_MINIMUM_VERSION, |
1208 | |
KEY_OSIS_VERSION, |
1209 | |
KEY_OSIS_Q_TO_TICK, |
1210 | |
KEY_DIRECTION, |
1211 | |
KEY_KEY_TYPE, |
1212 | |
KEY_DISPLAY_LEVEL, |
1213 | |
KEY_VERSIFICATION, |
1214 | |
KEY_CASE_SENSITIVE_KEYS, |
1215 | |
KEY_LOCAL_STRIP_FILTER, |
1216 | |
KEY_PREFERRED_CSS_XHTML, |
1217 | |
KEY_STRONGS_PADDING, |
1218 | |
KEY_SEARCH_OPTION, |
1219 | |
KEY_INSTALL_SIZE, |
1220 | |
KEY_SCOPE, |
1221 | |
KEY_BOOKLIST |
1222 | |
}; |
1223 | |
|
1224 | 0 | private static final String[] HIDDEN = { |
1225 | |
KEY_CIPHER_KEY, |
1226 | |
KEY_LANGUAGE |
1227 | |
}; |
1228 | |
|
1229 | 0 | private static final Pattern RTF_PATTERN = Pattern.compile("\\\\pard|\\\\pa[er]|\\\\qc|\\\\[bi]|\\\\u-?[0-9]{4,6}+"); |
1230 | 0 | private static final Pattern HTML_PATTERN = Pattern.compile("(<[a-zA-Z]|[a-zA-Z]>)"); |
1231 | |
|
1232 | |
|
1233 | |
|
1234 | |
|
1235 | |
|
1236 | |
|
1237 | |
private static final String ENCODING_UTF8 = "UTF-8"; |
1238 | |
private static final String ENCODING_LATIN1 = "WINDOWS-1252"; |
1239 | 0 | private static final PropertyMap ENCODING_JAVA = new PropertyMap(); |
1240 | |
static { |
1241 | 0 | ENCODING_JAVA.put("Latin-1", ENCODING_LATIN1); |
1242 | 0 | ENCODING_JAVA.put("UTF-8", ENCODING_UTF8); |
1243 | |
} |
1244 | |
|
1245 | |
|
1246 | |
|
1247 | |
|
1248 | 0 | private static final Logger LOGGER = LoggerFactory.getLogger(SwordBookMetaData.class); |
1249 | |
|
1250 | |
} |