You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
307 lines
9.3 KiB
307 lines
9.3 KiB
/*
|
|
* Copyright (c) 1996, 2000, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
|
|
* (C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
|
|
*
|
|
* The original version of this source code and documentation is copyrighted
|
|
* and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
|
|
* materials are provided under terms of a License Agreement between Taligent
|
|
* and Sun. This technology is protected by multiple US and International
|
|
* patents. This notice and attribution to Taligent may not be removed.
|
|
* Taligent is a registered trademark of Taligent, Inc.
|
|
*
|
|
*/
|
|
|
|
package java.text;
|
|
|
|
import java.lang.Character;
|
|
|
|
/**
|
|
* Utility class for normalizing and merging patterns for collation.
|
|
* This is to be used with MergeCollation for adding patterns to an
|
|
* existing rule table.
|
|
* @see MergeCollation
|
|
* @author Mark Davis, Helena Shih
|
|
*/
|
|
|
|
class PatternEntry {
|
|
/**
|
|
* Gets the current extension, quoted
|
|
*/
|
|
public void appendQuotedExtension(StringBuffer toAddTo) {
|
|
appendQuoted(extension,toAddTo);
|
|
}
|
|
|
|
/**
|
|
* Gets the current chars, quoted
|
|
*/
|
|
public void appendQuotedChars(StringBuffer toAddTo) {
|
|
appendQuoted(chars,toAddTo);
|
|
}
|
|
|
|
/**
|
|
* WARNING this is used for searching in a Vector.
|
|
* Because Vector.indexOf doesn't take a comparator,
|
|
* this method is ill-defined and ignores strength.
|
|
*/
|
|
public boolean equals(Object obj) {
|
|
if (obj == null) return false;
|
|
PatternEntry other = (PatternEntry) obj;
|
|
boolean result = chars.equals(other.chars);
|
|
return result;
|
|
}
|
|
|
|
public int hashCode() {
|
|
return chars.hashCode();
|
|
}
|
|
|
|
/**
|
|
* For debugging.
|
|
*/
|
|
public String toString() {
|
|
StringBuffer result = new StringBuffer();
|
|
addToBuffer(result, true, false, null);
|
|
return result.toString();
|
|
}
|
|
|
|
/**
|
|
* Gets the strength of the entry.
|
|
*/
|
|
final int getStrength() {
|
|
return strength;
|
|
}
|
|
|
|
/**
|
|
* Gets the expanding characters of the entry.
|
|
*/
|
|
final String getExtension() {
|
|
return extension;
|
|
}
|
|
|
|
/**
|
|
* Gets the core characters of the entry.
|
|
*/
|
|
final String getChars() {
|
|
return chars;
|
|
}
|
|
|
|
// ===== privates =====
|
|
|
|
void addToBuffer(StringBuffer toAddTo,
|
|
boolean showExtension,
|
|
boolean showWhiteSpace,
|
|
PatternEntry lastEntry)
|
|
{
|
|
if (showWhiteSpace && toAddTo.length() > 0)
|
|
if (strength == Collator.PRIMARY || lastEntry != null)
|
|
toAddTo.append('\n');
|
|
else
|
|
toAddTo.append(' ');
|
|
if (lastEntry != null) {
|
|
toAddTo.append('&');
|
|
if (showWhiteSpace)
|
|
toAddTo.append(' ');
|
|
lastEntry.appendQuotedChars(toAddTo);
|
|
appendQuotedExtension(toAddTo);
|
|
if (showWhiteSpace)
|
|
toAddTo.append(' ');
|
|
}
|
|
switch (strength) {
|
|
case Collator.IDENTICAL: toAddTo.append('='); break;
|
|
case Collator.TERTIARY: toAddTo.append(','); break;
|
|
case Collator.SECONDARY: toAddTo.append(';'); break;
|
|
case Collator.PRIMARY: toAddTo.append('<'); break;
|
|
case RESET: toAddTo.append('&'); break;
|
|
case UNSET: toAddTo.append('?'); break;
|
|
}
|
|
if (showWhiteSpace)
|
|
toAddTo.append(' ');
|
|
appendQuoted(chars,toAddTo);
|
|
if (showExtension && extension.length() != 0) {
|
|
toAddTo.append('/');
|
|
appendQuoted(extension,toAddTo);
|
|
}
|
|
}
|
|
|
|
static void appendQuoted(String chars, StringBuffer toAddTo) {
|
|
boolean inQuote = false;
|
|
char ch = chars.charAt(0);
|
|
if (Character.isSpaceChar(ch)) {
|
|
inQuote = true;
|
|
toAddTo.append('\'');
|
|
} else {
|
|
if (PatternEntry.isSpecialChar(ch)) {
|
|
inQuote = true;
|
|
toAddTo.append('\'');
|
|
} else {
|
|
switch (ch) {
|
|
case 0x0010: case '\f': case '\r':
|
|
case '\t': case '\n': case '@':
|
|
inQuote = true;
|
|
toAddTo.append('\'');
|
|
break;
|
|
case '\'':
|
|
inQuote = true;
|
|
toAddTo.append('\'');
|
|
break;
|
|
default:
|
|
if (inQuote) {
|
|
inQuote = false; toAddTo.append('\'');
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
toAddTo.append(chars);
|
|
if (inQuote)
|
|
toAddTo.append('\'');
|
|
}
|
|
|
|
//========================================================================
|
|
// Parsing a pattern into a list of PatternEntries....
|
|
//========================================================================
|
|
|
|
PatternEntry(int strength,
|
|
StringBuffer chars,
|
|
StringBuffer extension)
|
|
{
|
|
this.strength = strength;
|
|
this.chars = chars.toString();
|
|
this.extension = (extension.length() > 0) ? extension.toString()
|
|
: "";
|
|
}
|
|
|
|
static class Parser {
|
|
private String pattern;
|
|
private int i;
|
|
|
|
public Parser(String pattern) {
|
|
this.pattern = pattern;
|
|
this.i = 0;
|
|
}
|
|
|
|
public PatternEntry next() throws ParseException {
|
|
int newStrength = UNSET;
|
|
|
|
newChars.setLength(0);
|
|
newExtension.setLength(0);
|
|
|
|
boolean inChars = true;
|
|
boolean inQuote = false;
|
|
mainLoop:
|
|
while (i < pattern.length()) {
|
|
char ch = pattern.charAt(i);
|
|
if (inQuote) {
|
|
if (ch == '\'') {
|
|
inQuote = false;
|
|
} else {
|
|
if (newChars.length() == 0) newChars.append(ch);
|
|
else if (inChars) newChars.append(ch);
|
|
else newExtension.append(ch);
|
|
}
|
|
} else switch (ch) {
|
|
case '=': if (newStrength != UNSET) break mainLoop;
|
|
newStrength = Collator.IDENTICAL; break;
|
|
case ',': if (newStrength != UNSET) break mainLoop;
|
|
newStrength = Collator.TERTIARY; break;
|
|
case ';': if (newStrength != UNSET) break mainLoop;
|
|
newStrength = Collator.SECONDARY; break;
|
|
case '<': if (newStrength != UNSET) break mainLoop;
|
|
newStrength = Collator.PRIMARY; break;
|
|
case '&': if (newStrength != UNSET) break mainLoop;
|
|
newStrength = RESET; break;
|
|
case '\t':
|
|
case '\n':
|
|
case '\f':
|
|
case '\r':
|
|
case ' ': break; // skip whitespace TODO use Character
|
|
case '/': inChars = false; break;
|
|
case '\'':
|
|
inQuote = true;
|
|
ch = pattern.charAt(++i);
|
|
if (newChars.length() == 0) newChars.append(ch);
|
|
else if (inChars) newChars.append(ch);
|
|
else newExtension.append(ch);
|
|
break;
|
|
default:
|
|
if (newStrength == UNSET) {
|
|
throw new ParseException
|
|
("missing char (=,;<&) : " +
|
|
pattern.substring(i,
|
|
(i+10 < pattern.length()) ?
|
|
i+10 : pattern.length()),
|
|
i);
|
|
}
|
|
if (PatternEntry.isSpecialChar(ch) && (inQuote == false))
|
|
throw new ParseException
|
|
("Unquoted punctuation character : " + Integer.toString(ch, 16), i);
|
|
if (inChars) {
|
|
newChars.append(ch);
|
|
} else {
|
|
newExtension.append(ch);
|
|
}
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if (newStrength == UNSET)
|
|
return null;
|
|
if (newChars.length() == 0) {
|
|
throw new ParseException
|
|
("missing chars (=,;<&): " +
|
|
pattern.substring(i,
|
|
(i+10 < pattern.length()) ?
|
|
i+10 : pattern.length()),
|
|
i);
|
|
}
|
|
|
|
return new PatternEntry(newStrength, newChars, newExtension);
|
|
}
|
|
|
|
// We re-use these objects in order to improve performance
|
|
private StringBuffer newChars = new StringBuffer();
|
|
private StringBuffer newExtension = new StringBuffer();
|
|
|
|
}
|
|
|
|
static boolean isSpecialChar(char ch) {
|
|
return ((ch == '\u0020') ||
|
|
((ch <= '\u002F') && (ch >= '\u0022')) ||
|
|
((ch <= '\u003F') && (ch >= '\u003A')) ||
|
|
((ch <= '\u0060') && (ch >= '\u005B')) ||
|
|
((ch <= '\u007E') && (ch >= '\u007B')));
|
|
}
|
|
|
|
|
|
static final int RESET = -2;
|
|
static final int UNSET = -1;
|
|
|
|
int strength = UNSET;
|
|
String chars = "";
|
|
String extension = "";
|
|
}
|