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.book;
21  
22  import org.crosswire.jsword.internationalisation.LocaleProviderManager;
23  
24  /**
25   * Types of Sentence Case.
26   * 
27   * @see gnu.lgpl.License The GNU Lesser General Public License for details.
28   * @author Joe Walker
29   * @author DM Smith
30   */
31  public enum CaseType {
32      LOWER  {
33          @Override
34          public String setCase(String word) {
35              return word.toLowerCase(LocaleProviderManager.getLocale());
36          }
37      },
38  
39      SENTENCE {
40          @Override
41          public String setCase(String word) {
42              int index = word.indexOf('-');
43              if (index == -1) {
44                  return toSentenceCase(word);
45              }
46  
47              // So there is a "-", however first some exceptions
48              if ("maher-shalal-hash-baz".equalsIgnoreCase(word)) {
49                  return "Maher-Shalal-Hash-Baz";
50              }
51  
52              if ("no-one".equalsIgnoreCase(word)) {
53                  return "No-one";
54              }
55  
56              if ("god-".equalsIgnoreCase(word.substring(0, 4))) {
57                  return toSentenceCase(word);
58              }
59  
60              // So cut by the -
61              return toSentenceCase(word.substring(0, index)) + "-" + toSentenceCase(word.substring(index + 1));
62          }
63      },
64  
65      UPPER {
66          @Override
67          public String setCase(String word) {
68              return word.toUpperCase(LocaleProviderManager.getLocale());
69          }
70      };
71  
72      /**
73       * Adjust the case of the string as defined by the type.
74       * 
75       * @param word the string to transform
76       * @return the transformed string
77       */
78      public abstract String setCase(String word);
79  
80      /**
81       * Change to sentence case - that is first character in caps, the rest in lower.
82       * 
83       * @param word
84       *            The word to be manipulated
85       * @return The altered word
86       */
87      public static String toSentenceCase(String word) {
88          assert word != null;
89  
90          if (word.length() == 0) {
91              return "";
92          }
93  
94          return Character.toUpperCase(word.charAt(0)) + word.substring(1).toLowerCase(LocaleProviderManager.getLocale());
95      }
96  
97      /**
98       * What case is the specified word?. A blank word is LOWER, a word with a
99       * single upper case letter is SENTENCE and not UPPER - Simply because this
100      * is more likely, however TO BE SURE I WOULD NEED TO THE CONTEXT. I could
101      * not tell otherwise.
102      * <p>
103      * The issue here is that getCase("FreD") is undefined. Telling if this is
104      * SENTENCE (Tubal-Cain) or MIXED (really the case) is complex and would
105      * slow things down for a case that I don't believe happens with Bible text.
106      * </p>
107      * 
108      * @param word
109      *            The word to be tested
110      * @return LOWER, SENTENCE, UPPER or MIXED
111      * @exception IllegalArgumentException
112      *                is the word is null
113      */
114     public static CaseType getCase(String word) {
115         assert word != null;
116 
117         // Blank word
118         if (word.length() == 0) {
119             return LOWER;
120         }
121 
122         // Lower case?
123         if (word.equals(word.toLowerCase(LocaleProviderManager.getLocale()))) {
124             return LOWER;
125         }
126 
127         // Upper case?
128         // A string length of 1 is no good ('I' or 'A' is sentence case)
129         if (word.equals(word.toUpperCase(LocaleProviderManager.getLocale())) && word.length() != 1) {
130             return UPPER;
131         }
132 
133         // So ...
134         return SENTENCE;
135     }
136 
137     /**
138      * Get an integer representation for this CaseType
139      * 
140      * @return the ordinal value of this CaseType
141      */
142     public int toInteger() {
143         return ordinal();
144     }
145 
146     /**
147      * Lookup method to convert from a String
148      * 
149      * @param name the name of the CaseType
150      * @return the CaseType that matches
151      */
152     public static CaseType fromString(String name) {
153         for (CaseType v : values()) {
154             if (v.name().equalsIgnoreCase(name)) {
155                 return v;
156             }
157         }
158 
159         // cannot get here
160         assert false;
161         return null;
162     }
163 
164     /**
165      * Lookup method to convert from an integer
166      * 
167      * @param i the ordinal value of the CaseType
168      * @return the matching CaseType
169      */
170     public static CaseType fromInteger(int i) {
171         for (CaseType v : values()) {
172             if (v.ordinal() == i) {
173                 return v;
174             }
175         }
176 
177         // cannot get here
178         assert false;
179         return null;
180     }
181 
182 }
183