/*
* 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 = "";
}