1 /* 2 * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.javadoc.main; 27 28 import java.text.BreakIterator; 29 import java.text.Collator; 30 import java.util.Locale; 31 32 /** 33 * This class holds the information about locales. 34 * 35 * <p><b>This is NOT part of any supported API. 36 * If you write code that depends on this, you do so at your own risk. 37 * This code and its internal interfaces are subject to change or 38 * deletion without notice.</b> 39 * 40 * @since 1.4 41 * @author Robert Field 42 */ 43 @Deprecated(since="9", forRemoval=true) 44 @SuppressWarnings("removal") 45 class DocLocale { 46 47 /** 48 * The locale name will be set by Main, if option is provided on the 49 * command line. 50 */ 51 final String localeName; 52 53 /** 54 * The locale to be used. If user doesn't provide this, 55 * then set it to default locale value. 56 */ 57 final Locale locale; 58 59 /** 60 * The collator for this application. This is to take care of Locale 61 * Specific or Natural Language Text sorting. 62 */ 63 final Collator collator; 64 65 /** 66 * Enclosing DocEnv 67 */ 68 private final DocEnv docenv; 69 70 /** 71 * Sentence instance from the BreakIterator. 72 */ 73 private final BreakIterator sentenceBreaker; 74 75 /** 76 * True is we should use <code>BreakIterator</code> 77 * to compute first sentence. 78 */ 79 private boolean useBreakIterator = false; 80 81 /** 82 * The HTML sentence terminators. 83 */ 84 static final String[] sentenceTerminators = 85 { 86 "<p>", "</p>", "<h1>", "<h2>", 87 "<h3>", "<h4>", "<h5>", "<h6>", 88 "</h1>", "</h2>", "</h3>", "</h4>", "</h5>", 89 "</h6>", "<hr>", "<pre>", "</pre>" 90 }; 91 92 /** 93 * Constructor 94 */ DocLocale(DocEnv docenv, String localeName, boolean useBreakIterator)95 DocLocale(DocEnv docenv, String localeName, boolean useBreakIterator) { 96 this.docenv = docenv; 97 this.localeName = localeName; 98 this.useBreakIterator = useBreakIterator; 99 locale = getLocale(); 100 if (locale == null) { 101 docenv.exit(); 102 } else { 103 Locale.setDefault(locale); // NOTE: updating global state 104 } 105 collator = Collator.getInstance(locale); 106 sentenceBreaker = BreakIterator.getSentenceInstance(locale); 107 } 108 109 /** 110 * Get the locale if specified on the command line 111 * else return null and if locale option is not used 112 * then return default locale. 113 */ getLocale()114 private Locale getLocale() { 115 Locale userlocale = null; 116 if (localeName.length() > 0) { 117 int firstuscore = localeName.indexOf('_'); 118 int seconduscore = -1; 119 String language = null; 120 String country = null; 121 String variant = null; 122 if (firstuscore == 2) { 123 language = localeName.substring(0, firstuscore); 124 seconduscore = localeName.indexOf('_', firstuscore + 1); 125 if (seconduscore > 0) { 126 if (seconduscore != firstuscore + 3 || 127 localeName.length() <= seconduscore + 1) { 128 docenv.error(null, "main.malformed_locale_name", localeName); 129 return null; 130 } 131 country = localeName.substring(firstuscore + 1, 132 seconduscore); 133 variant = localeName.substring(seconduscore + 1); 134 } else if (localeName.length() == firstuscore + 3) { 135 country = localeName.substring(firstuscore + 1); 136 } else { 137 docenv.error(null, "main.malformed_locale_name", localeName); 138 return null; 139 } 140 } else if (firstuscore == -1 && localeName.length() == 2) { 141 language = localeName; 142 } else { 143 docenv.error(null, "main.malformed_locale_name", localeName); 144 return null; 145 } 146 userlocale = searchLocale(language, country, variant); 147 if (userlocale == null) { 148 docenv.error(null, "main.illegal_locale_name", localeName); 149 return null; 150 } else { 151 return userlocale; 152 } 153 } else { 154 return Locale.getDefault(); 155 } 156 } 157 158 /** 159 * Search the locale for specified language, specified country and 160 * specified variant. 161 */ searchLocale(String language, String country, String variant)162 private Locale searchLocale(String language, String country, 163 String variant) { 164 for (Locale loc : Locale.getAvailableLocales()) { 165 if (loc.getLanguage().equals(language) && 166 (country == null || loc.getCountry().equals(country)) && 167 (variant == null || loc.getVariant().equals(variant))) { 168 return loc; 169 } 170 } 171 return null; 172 } 173 localeSpecificFirstSentence(DocImpl doc, String s)174 String localeSpecificFirstSentence(DocImpl doc, String s) { 175 if (s == null || s.length() == 0) { 176 return ""; 177 } 178 int index = s.indexOf("-->"); 179 if(s.trim().startsWith("<!--") && index != -1) { 180 return localeSpecificFirstSentence(doc, s.substring(index + 3, s.length())); 181 } 182 if (useBreakIterator || !locale.getLanguage().equals("en")) { 183 sentenceBreaker.setText(s.replace('\n', ' ')); 184 int start = sentenceBreaker.first(); 185 int end = sentenceBreaker.next(); 186 return s.substring(start, end).trim(); 187 } else { 188 return englishLanguageFirstSentence(s).trim(); 189 } 190 } 191 192 /** 193 * Return the first sentence of a string, where a sentence ends 194 * with a period followed be white space. 195 */ englishLanguageFirstSentence(String s)196 private String englishLanguageFirstSentence(String s) { 197 if (s == null) { 198 return null; 199 } 200 int len = s.length(); 201 boolean period = false; 202 for (int i = 0 ; i < len ; i++) { 203 switch (s.charAt(i)) { 204 case '.': 205 period = true; 206 break; 207 case ' ': 208 case '\t': 209 case '\n': 210 case '\r': 211 case '\f': 212 if (period) { 213 return s.substring(0, i); 214 } 215 break; 216 case '<': 217 if (i > 0) { 218 if (htmlSentenceTerminatorFound(s, i)) { 219 return s.substring(0, i); 220 } 221 } 222 break; 223 default: 224 period = false; 225 } 226 } 227 return s; 228 } 229 230 /** 231 * Find out if there is any HTML tag in the given string. If found 232 * return true else return false. 233 */ htmlSentenceTerminatorFound(String str, int index)234 private boolean htmlSentenceTerminatorFound(String str, int index) { 235 for (String terminator : sentenceTerminators) { 236 if (str.regionMatches(true, index, terminator, 237 0, terminator.length())) { 238 return true; 239 } 240 } 241 return false; 242 } 243 } 244