| VerseRangeFactory.java |
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 as published by
5 * the Free Software Foundation. This program is distributed in the hope
6 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
7 * 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 * Copyright: 2005
18 * The copyright to this program is held by it's authors.
19 *
20 * ID: $Id: VerseRangeFactory.java 2226 2012-02-02 19:25:21Z dmsmith $
21 */
22 package org.crosswire.jsword.passage;
23
24 import org.crosswire.common.util.StringUtil;
25 import org.crosswire.jsword.JSMsg;
26 import org.crosswire.jsword.versification.Versification;
27
28 /**
29 * A factory that creates VerseRanges from user input.
30 *
31 * @see gnu.lgpl.License for license details.<br>
32 * The copyright to this program is held by it's authors.
33 * @author Joe Walker [joe at eireneh dot com]
34 * @author DM Smith [dmsmith555 at yahoo dot com]
35 */
36 public final class VerseRangeFactory {
37
38 /**
39 * prevent instantiation
40 */
41 private VerseRangeFactory() {
42 }
43
44 /**
45 * Construct a VerseRange from a human readable string. For example
46 * "Gen 1:1-3" in case the user does not want to have their typing 'fixed'
47 * by a meddling patronizing computer.
48 *
49 * @param orginal
50 * The textual representation
51 * @exception NoSuchVerseException
52 * If the text can not be understood
53 * @deprecated use {@link #fromString(Versification, String)} instead
54 */
55 @Deprecated
56 public static VerseRange fromString(String orginal) throws NoSuchVerseException {
57 return fromString(null, orginal, null);
58 }
59
60 public static VerseRange fromString(Versification v11n, String orginal) throws NoSuchVerseException {
61 return fromString(v11n, orginal, null);
62 }
63
64 /**
65 * Construct a VerseRange from a String and a VerseRange. For example given
66 * "2:2" and a basis of Gen 1:1-2 the result would be range of 1 verse
67 * starting at Gen 2:2. Also given "2:2-5" and a basis of Gen 1:1-2 the
68 * result would be a range of 5 verses starting at Gen 1:1.
69 * <p>
70 * This constructor is different from the (String, Verse) constructor in
71 * that if the basis is a range that exactly covers a chapter and the string
72 * is a single number, then we assume that the number refers to a chapter
73 * and not to a verse. This allows us to have a Passage like "Gen 1,2" and
74 * have the 2 understood as chapter 2 and not verse 2 of Gen 1, which would
75 * have occurred otherwise.
76 *
77 * @param original
78 * The string describing the verse e.g "2:2"
79 * @param basis
80 * The verse that forms the basis by which to understand the
81 * original.
82 * @exception NoSuchVerseException
83 * If the reference is illegal
84 * @deprecated use {@link #fromString(Versification, String, VerseRange)} instead
85 */
86 @Deprecated
87 public static VerseRange fromString(String original, VerseRange basis) throws NoSuchVerseException {
88 return fromString(null, original, basis);
89 }
90
91 public static VerseRange fromString(Versification v11n, String original, VerseRange basis) throws NoSuchVerseException {
92 String[] parts = StringUtil.split(original, VerseRange.RANGE_ALLOWED_DELIMS);
93
94 switch (parts.length) {
95 case 1:
96 return fromText(v11n, original, parts[0], parts[0], basis);
97
98 case 2:
99 return fromText(v11n, original, parts[0], parts[1], basis);
100
101 default:
102 // TRANSLATOR: The user specified a verse range with too many separators. {0} is a placeholder for the allowable separators.
103 throw new NoSuchVerseException(JSMsg.gettext("A verse range cannot have more than 2 parts. (Parts are separated by {0}) Given {1}", VerseRange.RANGE_ALLOWED_DELIMS, original));
104 }
105 }
106
107 private static VerseRange fromText(Versification v11n, String original, String startVerseDesc, String endVerseDesc, VerseRange basis) throws NoSuchVerseException {
108 String[] startParts = AccuracyType.tokenize(startVerseDesc);
109 AccuracyType accuracyStart = AccuracyType.fromText(v11n, original, startParts, basis);
110 Verse start = accuracyStart.createStartVerse(v11n, startVerseDesc, basis, startParts);
111 v11n.validate(start.getBook(), start.getChapter(), start.getVerse());
112
113 String[] endParts;
114 if (startVerseDesc.equals(endVerseDesc)) {
115 endParts = startParts;
116 } else {
117 endParts = AccuracyType.tokenize(endVerseDesc);
118 }
119
120 AccuracyType accuracyEnd = AccuracyType.fromText(v11n, original, endParts, accuracyStart, basis);
121 Verse end = accuracyEnd.createEndVerse(v11n, endVerseDesc, start, endParts);
122 v11n.validate(end.getBook(), end.getChapter(), end.getVerse());
123
124 return new VerseRange(v11n, original, start, end);
125 }
126 }
127