Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
VerseRangeFactory |
|
| 2.5;2.5 |
1 | /** | |
2 | * Distribution License: | |
3 | * JSword is free software; you can redistribute it and/or modify it under | |
4 | * the terms of the GNU Lesser General Public License, version 2.1 or later | |
5 | * as published by the Free Software Foundation. This program is distributed | |
6 | * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even | |
7 | * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
8 | * See the GNU Lesser General Public License for more details. | |
9 | * | |
10 | * The License is available on the internet at: | |
11 | * http://www.gnu.org/copyleft/lgpl.html | |
12 | * or by writing to: | |
13 | * Free Software Foundation, Inc. | |
14 | * 59 Temple Place - Suite 330 | |
15 | * Boston, MA 02111-1307, USA | |
16 | * | |
17 | * © CrossWire Bible Society, 2005 - 2016 | |
18 | * | |
19 | */ | |
20 | package org.crosswire.jsword.passage; | |
21 | ||
22 | import org.crosswire.common.util.StringUtil; | |
23 | import org.crosswire.jsword.JSMsg; | |
24 | import org.crosswire.jsword.versification.Versification; | |
25 | ||
26 | /** | |
27 | * A factory that creates VerseRanges from user input. | |
28 | * | |
29 | * @see gnu.lgpl.License The GNU Lesser General Public License for details. | |
30 | * @author Joe Walker | |
31 | * @author DM Smith | |
32 | */ | |
33 | public final class VerseRangeFactory { | |
34 | ||
35 | /** | |
36 | * prevent instantiation | |
37 | */ | |
38 | 0 | private VerseRangeFactory() { |
39 | 0 | } |
40 | ||
41 | /** | |
42 | * Construct a VerseRange from a human readable string. For example | |
43 | * "Gen 1:1-3" in case the user does not want to have their typing 'fixed' | |
44 | * by a meddling patronizing computer. | |
45 | * | |
46 | * @param v11n | |
47 | * The versification for this VerseRange | |
48 | * @param orginal | |
49 | * The textual representation | |
50 | * @return the verse range for the string | |
51 | * @exception NoSuchVerseException | |
52 | * If the text can not be understood | |
53 | */ | |
54 | public static VerseRange fromString(Versification v11n, String orginal) throws NoSuchVerseException { | |
55 | 0 | return fromString(v11n, orginal, null); |
56 | } | |
57 | ||
58 | /** | |
59 | * Construct a VerseRange from a String and a VerseRange. For example given | |
60 | * "2:2" and a basis of Gen 1:1-2 the result would be range of 1 verse | |
61 | * starting at Gen 2:2. Also given "2:2-5" and a basis of Gen 1:1-2 the | |
62 | * result would be a range of 5 verses starting at Gen 1:1. | |
63 | * <p> | |
64 | * This constructor is different from the (String, Verse) constructor in | |
65 | * that if the basis is a range that exactly covers a chapter and the string | |
66 | * is a single number, then we assume that the number refers to a chapter | |
67 | * and not to a verse. This allows us to have a Passage like "Gen 1,2" and | |
68 | * have the 2 understood as chapter 2 and not verse 2 of Gen 1, which would | |
69 | * have occurred otherwise. | |
70 | * | |
71 | * @param v11n | |
72 | * The versification for this VerseRange | |
73 | * @param original | |
74 | * The string describing the verse e.g "2:2" | |
75 | * @param basis | |
76 | * The verse that forms the basis by which to understand the | |
77 | * original. | |
78 | * @return the verse range | |
79 | * @exception NoSuchVerseException | |
80 | * If the reference is illegal | |
81 | */ | |
82 | public static VerseRange fromString(Versification v11n, String original, VerseRange basis) throws NoSuchVerseException { | |
83 | 0 | String[] parts = StringUtil.splitAll(original, VerseRange.RANGE_OSIS_DELIM); |
84 | ||
85 | 0 | switch (parts.length) { |
86 | case 1: | |
87 | 0 | return fromText(v11n, original, parts[0], parts[0], basis); |
88 | ||
89 | case 2: | |
90 | 0 | return fromText(v11n, original, parts[0], parts[1], basis); |
91 | ||
92 | default: | |
93 | // TRANSLATOR: The user specified a verse range with too many separators. {0} is a placeholder for the allowable separators. | |
94 | 0 | throw new NoSuchVerseException(JSMsg.gettext("A verse range cannot have more than 2 parts. (Parts are separated by {0}) Given {1}", VerseRange.RANGE_OSIS_DELIM, original)); |
95 | } | |
96 | } | |
97 | ||
98 | /** | |
99 | * The internal mechanism by which we construct a VerseRange | |
100 | * | |
101 | * @param v11n | |
102 | * The versification for this VerseRange | |
103 | * @param original | |
104 | * The string describing the verse e.g "2:2" | |
105 | * @param startVerseDesc | |
106 | * The part of the range before the range separator | |
107 | * @param endVerseDesc | |
108 | * The part of the range after the range separator | |
109 | * @param basis | |
110 | * The verse that forms the basis by which to understand the | |
111 | * original. | |
112 | * @exception NoSuchVerseException | |
113 | * If the reference is illegal | |
114 | */ | |
115 | private static VerseRange fromText(Versification v11n, String original, String startVerseDesc, String endVerseDesc, VerseRange basis) throws NoSuchVerseException { | |
116 | 0 | String[] startParts = AccuracyType.tokenize(startVerseDesc); |
117 | 0 | AccuracyType accuracyStart = AccuracyType.fromText(v11n, original, startParts, basis); |
118 | 0 | Verse start = accuracyStart.createStartVerse(v11n, basis, startParts); |
119 | 0 | v11n.validate(start.getBook(), start.getChapter(), start.getVerse()); |
120 | ||
121 | String[] endParts; | |
122 | 0 | if (startVerseDesc.equals(endVerseDesc)) { |
123 | 0 | endParts = startParts; |
124 | } else { | |
125 | 0 | endParts = AccuracyType.tokenize(endVerseDesc); |
126 | } | |
127 | ||
128 | 0 | AccuracyType accuracyEnd = AccuracyType.fromText(v11n, original, endParts, accuracyStart, basis); |
129 | 0 | Verse end = accuracyEnd.createEndVerse(v11n, start, endParts); |
130 | 0 | v11n.validate(end.getBook(), end.getChapter(), end.getVerse()); |
131 | ||
132 | 0 | return new VerseRange(v11n, start, end); |
133 | } | |
134 | } |