001: /*
002: * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.javadoc;
027:
028: import java.util.Locale;
029: import java.util.HashSet;
030: import java.text.Collator;
031: import java.text.BreakIterator;
032:
033: /**
034: * This class holds the information about locales.
035: *
036: * @since 1.4
037: * @author Robert Field
038: */
039: class DocLocale {
040:
041: /**
042: * The locale name will be set by Main, if option is provided on the
043: * command line.
044: */
045: final String localeName;
046:
047: /**
048: * The locale to be used. If user doesen't provide this,
049: * then set it to default locale value.
050: */
051: final Locale locale;
052:
053: /**
054: * The collator for this application. This is to take care of Locale
055: * Specific or Natural Language Text sorting.
056: */
057: final Collator collator;
058:
059: /**
060: * Enclosing DocEnv
061: */
062: private final DocEnv docenv;
063:
064: /**
065: * Sentence instance from the BreakIterator.
066: */
067: private final BreakIterator sentenceBreaker;
068:
069: /**
070: * True is we should use <code>BreakIterator</code>
071: * to compute first sentence.
072: */
073: private boolean useBreakIterator = false;
074:
075: /**
076: * The HTML sentence terminators.
077: */
078: static final String[] sentenceTerminators = { "<p>", "</p>",
079: "<h1>", "<h2>", "<h3>", "<h4>", "<h5>", "<h6>", "</h1>",
080: "</h2>", "</h3>", "</h4>", "</h5>", "</h6>", "<hr>",
081: "<pre>", "</pre>" };
082:
083: /**
084: * Constructor
085: */
086: DocLocale(DocEnv docenv, String localeName, boolean useBreakIterator) {
087: this .docenv = docenv;
088: this .localeName = localeName;
089: this .useBreakIterator = useBreakIterator;
090: locale = getLocale();
091: if (locale == null) {
092: docenv.exit();
093: } else {
094: Locale.setDefault(locale);
095: }
096: collator = Collator.getInstance(locale);
097: sentenceBreaker = BreakIterator.getSentenceInstance(locale);
098: }
099:
100: /**
101: * Get the locale if specified on the command line
102: * else return null and if locale option is not used
103: * then return default locale.
104: */
105: private Locale getLocale() {
106: Locale userlocale = null;
107: if (localeName.length() > 0) {
108: int firstuscore = localeName.indexOf('_');
109: int seconduscore = -1;
110: String language = null;
111: String country = null;
112: String variant = null;
113: if (firstuscore == 2) {
114: language = localeName.substring(0, firstuscore);
115: seconduscore = localeName.indexOf('_', firstuscore + 1);
116: if (seconduscore > 0) {
117: if (seconduscore != firstuscore + 3
118: || localeName.length() <= seconduscore + 1) {
119: docenv.error(null,
120: "main.malformed_locale_name",
121: localeName);
122: return null;
123: }
124: country = localeName.substring(firstuscore + 1,
125: seconduscore);
126: variant = localeName.substring(seconduscore + 1);
127: } else if (localeName.length() == firstuscore + 3) {
128: country = localeName.substring(firstuscore + 1);
129: } else {
130: docenv.error(null, "main.malformed_locale_name",
131: localeName);
132: return null;
133: }
134: } else if (firstuscore == -1 && localeName.length() == 2) {
135: language = localeName;
136: } else {
137: docenv.error(null, "main.malformed_locale_name",
138: localeName);
139: return null;
140: }
141: userlocale = searchLocale(language, country, variant);
142: if (userlocale == null) {
143: docenv.error(null, "main.illegal_locale_name",
144: localeName);
145: return null;
146: } else {
147: return userlocale;
148: }
149: } else {
150: return Locale.getDefault();
151: }
152: }
153:
154: /**
155: * Search the locale for specified language, specified country and
156: * specified variant.
157: */
158: private Locale searchLocale(String language, String country,
159: String variant) {
160: Locale[] locales = Locale.getAvailableLocales();
161: for (int i = 0; i < locales.length; i++) {
162: if (locales[i].getLanguage().equals(language)
163: && (country == null || locales[i].getCountry()
164: .equals(country))
165: && (variant == null || locales[i].getVariant()
166: .equals(variant))) {
167: return locales[i];
168: }
169: }
170: return null;
171: }
172:
173: String localeSpecificFirstSentence(DocImpl doc, String s) {
174: if (s == null || s.length() == 0) {
175: return "";
176: }
177: int index = s.indexOf("-->");
178: if (s.trim().startsWith("<!--") && index != -1) {
179: return localeSpecificFirstSentence(doc, s.substring(
180: 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: */
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: */
234: private boolean htmlSentenceTerminatorFound(String str, int index) {
235: for (int i = 0; i < sentenceTerminators.length; i++) {
236: String terminator = sentenceTerminators[i];
237: if (str.regionMatches(true, index, terminator, 0,
238: terminator.length())) {
239: return true;
240: }
241: }
242: return false;
243: }
244: }
|