Initial revision

From-SVN: r102074
This commit is contained in:
Tom Tromey
2005-07-16 00:30:23 +00:00
parent 6f4434b39b
commit f911ba985a
4557 changed files with 1000262 additions and 0 deletions
+113
View File
@@ -0,0 +1,113 @@
/* Annotation.java -- Wrapper for a text attribute object
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
/**
* This class is used as a wrapper for a text attribute object. Annotation
* objects are associated with a specific range of text. Changing either
* the text range or the underlying text invalidates the object.
*
* @version 0.0
*
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
public class Annotation
{
/*
* Instance Variables
*/
/**
* This is the attribute object being wrappered
*/
private Object attrib;
/*************************************************************************/
/**
* Constructors
*/
/**
* This method initializes a new instance of <code>Annotation</code> to
* wrapper the specified text attribute object.
*
* @param attrib The text attribute <code>Object</code> to wrapper.
*/
public
Annotation(Object attrib)
{
this.attrib = attrib;
}
/*************************************************************************/
/*
* Instance Variables
*/
/**
* This method returns the text attribute object this <code>Annotation</code>
* instance is wrappering.
*
* @return The text attribute object for this <code>Annotation</code>.
*/
public Object
getValue()
{
return(attrib);
}
/*************************************************************************/
/**
* This method returns a <code>String</code> representation of this
* object.
*
* @return This object as a <code>String</code>.
*/
public String
toString()
{
return(getClass().getName() + "[value=" + attrib.toString() + "]");
}
} // class Annotation
@@ -0,0 +1,268 @@
/* AttributedCharacterIterator.java -- Iterate over attributes
Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.io.InvalidObjectException;
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
/**
* This interface extends the <code>CharacterIterator</code> interface
* in order to support iteration over character attributes as well as
* over the characters themselves.
* <p>
* In addition to attributes of specific characters, this interface
* supports the concept of the "attribute run", which is an attribute
* that is defined for a particular value across an entire range of
* characters or which is undefined over a range of characters.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
public interface AttributedCharacterIterator extends CharacterIterator
{
/**
* This class defines attribute keys that are used as text attributes.
*/
public static class Attribute implements Serializable
{
private static final long serialVersionUID = -9142742483513960612L;
/**
* This is the attribute for the language of the text. The value of
* attributes of this key type are instances of <code>Locale</code>.
*/
public static final Attribute LANGUAGE = new Attribute ("LANGUAGE");
/**
* This is the attribute for the reading form of text. This is used
* for storing pronunciation along with the written text for languages
* which need it. The value of attributes of this key type are
* instances of <code>Annotation</code> which wrappers a <code>String</code>.
*/
public static final Attribute READING = new Attribute ("READING");
/**
* This is the attribute for input method segments. The value of attributes
* of this key type are instances of <code>Annotation</code> which wrapper
* a <code>String</code>.
*/
public static final Attribute INPUT_METHOD_SEGMENT =
new Attribute ("INPUT_METHOD_SEGMENT");
/**
* This is the name of the attribute key
* @serial
*/
private String name;
/**
* This method initializes a new instance of this class with the specified
* name.
*
* @param name The name of this attribute key.
*/
protected Attribute (String name)
{
this.name = name;
}
/**
* This method returns the name of this attribute.
*
* @return The attribute name
*/
protected String getName()
{
return name;
}
/**
* This method resolves an instance of <code>AttributedCharacterIterator.Attribute</code>
* that is being deserialized to one of the three pre-defined attribute
* constants. It does this by comparing the names of the attributes. The
* constant that the deserialized object resolves to is returned.
*
* @return The resolved contant value
*
* @exception InvalidObjectException If the object being deserialized cannot be resolved.
*/
protected Object readResolve() throws InvalidObjectException
{
if (this.equals (READING))
return READING;
if (this.equals (LANGUAGE))
return LANGUAGE;
if (this.equals (INPUT_METHOD_SEGMENT))
return INPUT_METHOD_SEGMENT;
throw new InvalidObjectException ("Can't resolve Attribute: " + getName());
}
/**
* This method tests this object for equality against the specified object.
* The two objects will be considered equal if and only if:
* <ul>
* <li>The specified object is not <code>null</code>.
* <li>The specified object is an instance of <code>AttributedCharacterIterator.Attribute</code>.
* <li>The specified object has the same attribute name as this object.
* </ul>
*
* @param The <code>Object</code> to test for equality against this object.
*
* @return <code>true</code> if the specified object is equal to this one, <code>false</code> otherwise.
*/
public final boolean equals (Object obj)
{
if (obj == this)
return true;
else
return false;
}
/**
* This method returns a hash value for this object.
*
* @return A hash value for this object.
*/
public final int hashCode()
{
return super.hashCode();
}
/**
* This method returns a <code>String</code> representation of this object.
*
* @return A <code>String</code> representation of this object.
*/
public String toString()
{
return getClass().getName() + "(" + getName() + ")";
}
} // Inner class Attribute
/**
* This method returns a list of all keys that are defined for the
* text range. This can be an empty list if no attributes are defined.
*
* @return A list of keys
*/
Set getAllAttributeKeys();
/**
* This method returns a <code>Map</code> of the attributed defined for
* the current character.
*
* @return A <code>Map</code> of the attributes for the current character.
*/
Map getAttributes();
/**
* This method returns the value of the specified attribute for the
* current character. If the attribute is not defined for the current
* character, <code>null</code> is returned.
*
* @param attrib The attribute to retrieve the value of.
*
* @return The value of the specified attribute
*/
Object getAttribute (AttributedCharacterIterator.Attribute attrib);
/**
* This method returns the index of the first character in the run that
* contains all attributes defined for the current character.
*
* @return The start index of the run
*/
int getRunStart();
/**
* This method returns the index of the first character in the run that
* contains all attributes in the specified <code>Set</code> defined for
* the current character.
*
* @param attribs The <code>Set</code> of attributes.
*
* @return The start index of the run.
*/
int getRunStart (Set attribs);
/**
* This method returns the index of the first character in the run that
* contains the specified attribute defined for the current character.
*
* @param attrib The attribute.
*
* @return The start index of the run.
*/
int getRunStart (AttributedCharacterIterator.Attribute attrib);
/**
* This method returns the index of the character after the end of the run
* that contains all attributed defined for the current character.
*
* @return The end index of the run.
*/
int getRunLimit();
/**
* This method returns the index of the character after the end of the run
* that contains all attributes in the specified <code>Set</code> defined
* for the current character.
*
* @param attribs The <code>Set</code> of attributes.
*
* @return The end index of the run.
*/
int getRunLimit (Set attribs);
/**
* This methods returns the index of the character after the end of the run
* that contains the specified attribute defined for the current character.
*
* @param attrib The attribute.
*
* @return The end index of the run.
*/
int getRunLimit (AttributedCharacterIterator.Attribute attrib);
} // interface AttributedCharacterIterator
@@ -0,0 +1,425 @@
/* AttributedString.java -- Models text with attributes
Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* This class models a <code>String</code> with attributes over various
* subranges of the string. It allows applications to access this
* information via the <code>AttributedCharcterIterator</code> interface.
*
* @version 0.0
*
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
public class AttributedString
{
/*************************************************************************/
/*
* Inner Classes
*/
/**
* This class contains the attributes and ranges of text over which
* that attributes apply.
*/
final class AttributeRange
{
/*
* Instance Variables
*/
/**
* A Map of the attributes
*/
Map attribs;
/**
* The beginning index of the attributes
*/
int begin_index;
/**
* The ending index of the attributes
*/
int end_index;
/*************************************************************************/
/*
* Constructors
*/
AttributeRange(Map attribs, int begin_index, int end_index)
{
this.attribs = attribs;
this.begin_index = begin_index;
this.end_index = end_index;
}
} // Inner class AttributeRange
/*************************************************************************/
/*
* Instance Variables
*/
/**
* This object holds the string we are representing.
*/
private StringCharacterIterator sci;
/**
* This is the attribute information
*/
private AttributeRange[] attribs;
/*************************************************************************/
/*
* Constructors
*/
/**
* This method initializes a new instance of <code>AttributedString</code>
* that represents the specified <code>String</code> with no attributes.
*
* @param str The <code>String</code> to be attributed.
*/
public
AttributedString(String str)
{
sci = new StringCharacterIterator(str);
attribs = new AttributeRange[0];
}
/*************************************************************************/
/**
* This method initializes a new instance of <code>AttributedString</code>
* that represents that specified <code>String</code> with the specified
* attributes over the entire length of the <code>String</code>.
*
* @param str The <code>String</code> to be attributed.
* @param attributes The attribute list.
*/
public
AttributedString(String str, Map attributes)
{
this(str);
attribs = new AttributeRange[1];
attribs[0] = new AttributeRange(attributes, 0, str.length());
}
/*************************************************************************/
/**
* This method initializes a new instance of <code>AttributedString</code>
* that will use the text and attribute information from the specified
* <code>AttributedCharacterIterator</code>.
*
* @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information.
*/
public
AttributedString(AttributedCharacterIterator aci)
{
this(aci, aci.getBeginIndex(), aci.getEndIndex(), null);
}
/*************************************************************************/
/**
* This method initializes a new instance of <code>AttributedString</code>
* that will use the text and attribute information from the specified
* subrange of the specified <code>AttributedCharacterIterator</code>.
*
* @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information.
* @param begin_index The beginning index of the text subrange.
* @param end_index The ending index of the text subrange.
*/
public
AttributedString(AttributedCharacterIterator aci, int begin_index,
int end_index)
{
this(aci, begin_index, end_index, null);
}
/*************************************************************************/
/**
* This method initializes a new instance of <code>AttributedString</code>
* that will use the text and attribute information from the specified
* subrange of the specified <code>AttributedCharacterIterator</code>.
* Only attributes from the source iterator that are present in the
* specified array of attributes will be included in the attribute list
* for this object.
*
* @param aci The <code>AttributedCharacterIterator</code> containing the text and attribute information.
* @param begin_index The beginning index of the text subrange.
* @param end_index The ending index of the text subrange.
* @param attributes A list of attributes to include from the iterator, or <code>null</code> to include all attributes.
*/
public
AttributedString(AttributedCharacterIterator aci, int begin_index,
int end_index, AttributedCharacterIterator.Attribute[] attributes)
{
// Validate some arguments
if ((begin_index < 0) || (end_index < begin_index))
throw new IllegalArgumentException("Bad index values");
StringBuffer sb = new StringBuffer("");
// Get the valid attribute list
Set all_attribs = aci.getAllAttributeKeys();
if (attributes != null)
all_attribs.retainAll(Arrays.asList(attributes));
// Loop through and extract the attributes
char c = aci.setIndex(begin_index);
ArrayList accum = new ArrayList();
do
{
sb.append(c);
Iterator iter = all_attribs.iterator();
while(iter.hasNext())
{
Object obj = iter.next();
// What should we do if this is not true?
if (!(obj instanceof AttributedCharacterIterator.Attribute))
continue;
AttributedCharacterIterator.Attribute attrib =
(AttributedCharacterIterator.Attribute)obj;
// Make sure the attribute is defined.
int rl = aci.getRunLimit(attrib);
if (rl == -1)
continue;
if (rl > end_index)
rl = end_index;
rl -= begin_index;
// Check to see if we already processed this one
int rs = aci.getRunStart(attrib);
if ((rs < aci.getIndex()) && (aci.getIndex() != begin_index))
continue;
// If the attribute run starts before the beginning index, we
// need to junk it if it is an Annotation.
Object attrib_obj = aci.getAttribute(attrib);
if (rs < begin_index)
{
if (attrib_obj instanceof Annotation)
continue;
rs = begin_index;
}
else
{
rs -= begin_index;
}
// Create a map object. Yes this will only contain one attribute
Map new_map = new Hashtable();
new_map.put(attrib, attrib_obj);
// Add it to the attribute list.
accum.add(new AttributeRange(new_map, rs, rl));
}
c = aci.next();
}
while(c != CharacterIterator.DONE);
attribs = new AttributeRange[accum.size()];
attribs = (AttributeRange[]) accum.toArray(attribs);
sci = new StringCharacterIterator(sb.toString());
}
/*************************************************************************/
/*
* Instance Methods
*/
/**
* This method adds a new attribute that will cover the entire string.
*
* @param attrib The attribute to add.
* @param value The value of the attribute.
*/
public void
addAttribute(AttributedCharacterIterator.Attribute attrib, Object value)
{
addAttribute(attrib, value, 0, sci.getEndIndex());
}
/*************************************************************************/
/**
* This method adds a new attribute that will cover the specified subrange
* of the string.
*
* @param attrib The attribute to add.
* @param value The value of the attribute, which may be null.
* @param begin_index The beginning index of the subrange.
* @param end_index The ending index of the subrange.
*
* @exception IllegalArgumentException If attribute is <code>null</code> or the subrange is not valid.
*/
public void
addAttribute(AttributedCharacterIterator.Attribute attrib, Object value,
int begin_index, int end_index)
{
if (attrib == null)
throw new IllegalArgumentException("null attribute");
HashMap hm = new HashMap();
hm.put(attrib, value);
addAttributes(hm, begin_index, end_index);
}
/*************************************************************************/
/**
* This method adds all of the attributes in the specified list to the
* specified subrange of the string.
*
* @param attributes The list of attributes.
* @param begin_index The beginning index.
* @param end_index The ending index
*
* @param IllegalArgumentException If the list is <code>null</code> or the subrange is not valid.
*/
public void
addAttributes(Map attributes, int begin_index, int end_index)
{
if (attributes == null)
throw new IllegalArgumentException("null attribute");
if ((begin_index < 0) || (end_index > sci.getEndIndex()) ||
(end_index < begin_index))
throw new IllegalArgumentException("bad range");
AttributeRange[] new_list = new AttributeRange[attribs.length + 1];
System.arraycopy(attribs, 0, new_list, 0, attribs.length);
attribs = new_list;
attribs[attribs.length - 1] = new AttributeRange(attributes, begin_index,
end_index);
}
/*************************************************************************/
/**
* This method returns an <code>AttributedCharacterIterator</code> that
* will iterate over the entire string.
*
* @return An <code>AttributedCharacterIterator</code> for the entire string.
*/
public AttributedCharacterIterator
getIterator()
{
return(new AttributedStringIterator(sci, attribs, 0, sci.getEndIndex(), null));
}
/*************************************************************************/
/**
* This method returns an <code>AttributedCharacterIterator</code> that
* will iterate over the entire string. This iterator will return information
* about the list of attributes in the specified array. Attributes not in
* the array may or may not be returned by the iterator. If the specified
* array is <code>null</code>, all attributes will be returned.
*
* @param attributes A list of attributes to include in the returned iterator.
*
* @return An <code>AttributedCharacterIterator</code> for this string.
*/
public AttributedCharacterIterator
getIterator(AttributedCharacterIterator.Attribute[] attributes)
{
return(getIterator(attributes, 0, sci.getEndIndex()));
}
/*************************************************************************/
/**
* This method returns an <code>AttributedCharacterIterator</code> that
* will iterate over the specified subrange. This iterator will return information
* about the list of attributes in the specified array. Attributes not in
* the array may or may not be returned by the iterator. If the specified
* array is <code>null</code>, all attributes will be returned.
*
* @param attributes A list of attributes to include in the returned iterator.
* @param begin_index The beginning index of the subrange.
* @param end_index The ending index of the subrange.
*
* @return An <code>AttributedCharacterIterator</code> for this string.
*/
public AttributedCharacterIterator
getIterator(AttributedCharacterIterator.Attribute[] attributes,
int begin_index, int end_index)
{
if ((begin_index < 0) || (end_index > sci.getEndIndex()) ||
(end_index < begin_index))
throw new IllegalArgumentException("bad range");
return(new AttributedStringIterator(sci, attribs, begin_index, end_index,
attributes));
}
} // class AttributedString
@@ -0,0 +1,348 @@
/* AttributedStringIterator.java -- Class to iterate over AttributedString
Copyright (C) 1998, 1999, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* This class implements the AttributedCharacterIterator interface. It
* is used by AttributedString.getIterator().
*
* @version 0.0
*
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
class AttributedStringIterator implements AttributedCharacterIterator
{
/*************************************************************************/
/**
* Instance Variables
*/
/**
* The character iterator containing the text
*/
private CharacterIterator ci;
/**
* The list of attributes and ranges
*/
private AttributedString.AttributeRange[] attribs;
/**
* The list of attributes that the user is interested in. We may,
* at our option, not return any other attributes.
*/
private AttributedCharacterIterator.Attribute[] restricts;
/*************************************************************************/
/*
* Constructors
*/
AttributedStringIterator(StringCharacterIterator sci,
AttributedString.AttributeRange[] attribs,
int begin_index, int end_index,
AttributedCharacterIterator.Attribute[] restricts)
{
this.ci = new StringCharacterIterator(sci, begin_index, end_index);
this.attribs = attribs;
this.restricts = restricts;
}
/*************************************************************************/
/*
* Instance Methods
*/
// First we have a bunch of stupid redirects. If StringCharacterIterator
// weren't final, I just would have extended that for this class. Alas, no.
public Object
clone()
{
return(ci.clone());
}
public char
current()
{
return(ci.current());
}
public char
next()
{
return(ci.next());
}
public char
previous()
{
return(ci.previous());
}
public char
first()
{
return(ci.first());
}
public char
last()
{
return(ci.last());
}
public int
getIndex()
{
return(ci.getIndex());
}
public char
setIndex(int index)
{
return(ci.setIndex(index));
}
public int
getBeginIndex()
{
return(ci.getBeginIndex());
}
public int
getEndIndex()
{
return(ci.getEndIndex());
}
/*
* Here is where the AttributedCharacterIterator methods start.
*/
/*************************************************************************/
/**
* Returns a list of all the attribute keys that are defined anywhere
* on this string.
*/
public Set
getAllAttributeKeys()
{
HashSet s = new HashSet();
if (attribs == null)
return(s);
for (int i = 0; i < attribs.length; i++)
{
if (attribs[i].begin_index > getEndIndex()
|| attribs[i].end_index <= getBeginIndex())
continue;
Set key_set = attribs[i].attribs.keySet();
Iterator iter = key_set.iterator();
while (iter.hasNext())
{
s.add(iter.next());
}
}
return(s);
}
/*************************************************************************/
/**
* Various methods that determine how far the run extends for various
* attribute combinations.
*/
public int
getRunLimit()
{
return(getRunLimit(getAttributes().keySet()));
}
public int
getRunLimit(AttributedCharacterIterator.Attribute attrib)
{
HashSet s = new HashSet();
s.add(attrib);
return(getRunLimit(s));
}
public synchronized int
getRunLimit(Set attribute_set)
{
boolean hit = false;
int runLimit = ci.getEndIndex ();
int pos = ci.getIndex ();
for (int i = 0; i < attribs.length; ++i)
{
if (pos >= attribs[i].begin_index &&
pos < attribs[i].end_index)
{
Iterator iter = attribute_set.iterator();
while(iter.hasNext())
if (attribs[i].attribs.containsKey(iter.next()))
{
hit = true;
runLimit = Math.min(runLimit, attribs[i].end_index);
}
}
}
if (hit)
return runLimit;
else
return ci.getEndIndex();
}
/*************************************************************************/
/**
* Various methods that determine where the run begins for various
* attribute combinations.
*/
public int
getRunStart()
{
return(getRunStart(getAttributes().keySet()));
}
public int
getRunStart(AttributedCharacterIterator.Attribute attrib)
{
HashSet s = new HashSet();
s.add(attrib);
return(getRunStart(s));
}
public int
getRunStart(Set attribute_set)
{
boolean hit = false;
int runBegin = 0;
int pos = ci.getIndex ();
for (int i = 0; i < attribs.length; ++i)
{
if (pos >= attribs[i].begin_index &&
pos <= attribs[i].end_index)
{
Iterator iter = attribute_set.iterator();
while(iter.hasNext())
if (attribs[i].attribs.containsKey(iter.next()))
{
hit = true;
runBegin = Math.max(runBegin, attribs[i].begin_index);
}
}
}
if (hit)
return runBegin;
else
return -1;
}
/*************************************************************************/
public Object
getAttribute(AttributedCharacterIterator.Attribute attrib)
{
if (attribs == null)
return(null);
for (int i = 0; i < attribs.length; i++)
{
Set key_set = attribs[i].attribs.keySet();
Iterator iter = key_set.iterator();
while (iter.hasNext())
{
Object obj = iter.next();
// Check for attribute match and range match
if (obj.equals(attrib))
if ((ci.getIndex() >= attribs[i].begin_index) &&
(ci.getIndex() < attribs[i].end_index))
return(attribs[i].attribs.get(obj));
}
}
return(null);
}
/*************************************************************************/
/**
* Return a list of all the attributes and values defined for this
* character
*/
public Map
getAttributes()
{
HashMap m = new HashMap();
if (attribs == null)
return(m);
for (int i = 0; i < attribs.length; i++)
{
if ((ci.getIndex() >= attribs[i].begin_index) &&
(ci.getIndex() < attribs[i].end_index))
m.putAll(attribs[i].attribs);
}
return(m);
}
} // class AttributedStringIterator
@@ -0,0 +1,374 @@
/* BreakIterator.java -- Breaks text into elements
Copyright (C) 1998, 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* This class iterates over text elements such as words, lines, sentences,
* and characters. It can only iterate over one of these text elements at
* a time. An instance of this class configured for the desired iteration
* type is created by calling one of the static factory methods, not
* by directly calling a constructor.
*
* The standard iterators created by the factory methods in this
* class will be valid upon creation. That is, their methods will
* not cause exceptions if called before you call setText().
*
* @author Tom Tromey (tromey@cygnus.com)
* @author Aaron M. Renn (arenn@urbanophile.com)
* @date March 19, 1999
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Believed complete and correct to 1.1.
*/
public abstract class BreakIterator implements Cloneable
{
/**
* This value is returned by the <code>next()</code> and
* <code>previous</code> in order to indicate that the end of the
* text has been reached.
*/
// The value was discovered by writing a test program.
public static final int DONE = -1;
/**
* This method initializes a new instance of <code>BreakIterator</code>.
* This protected constructor is available to subclasses as a default
* no-arg superclass constructor.
*/
protected BreakIterator ()
{
}
/**
* Create a clone of this object.
*/
public Object clone ()
{
try
{
return super.clone();
}
catch (CloneNotSupportedException e)
{
return null;
}
}
/**
* This method returns the index of the current text element boundary.
*
* @return The current text boundary.
*/
public abstract int current ();
/**
* This method returns the first text element boundary in the text being
* iterated over.
*
* @return The first text boundary.
*/
public abstract int first ();
/**
* This methdod returns the offset of the text element boundary following
* the specified offset.
*
* @param offset The text index from which to find the next text boundary.
*
* @param The next text boundary following the specified index.
*/
public abstract int following (int pos);
/**
* This method returns a list of locales for which instances of
* <code>BreakIterator</code> are available.
*
* @return A list of available locales
*/
public static synchronized Locale[] getAvailableLocales ()
{
Locale[] l = new Locale[1];
l[0] = Locale.US;
return l;
}
private static BreakIterator getInstance (String type, Locale loc)
{
String className;
try
{
ResourceBundle res
= ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
loc, ClassLoader.getSystemClassLoader());
className = res.getString(type);
}
catch (MissingResourceException x)
{
return null;
}
try
{
Class k = Class.forName(className);
return (BreakIterator) k.newInstance();
}
catch (ClassNotFoundException x1)
{
return null;
}
catch (InstantiationException x2)
{
return null;
}
catch (IllegalAccessException x3)
{
return null;
}
}
/**
* This method returns an instance of <code>BreakIterator</code> that will
* iterate over characters as defined in the default locale.
*
* @return A <code>BreakIterator</code> instance for the default locale.
*/
public static BreakIterator getCharacterInstance ()
{
return getCharacterInstance (Locale.getDefault());
}
/**
* This method returns an instance of <code>BreakIterator</code> that will
* iterate over characters as defined in the specified locale. If the
* desired locale is not available, the default locale is used.
*
* @param locale The desired locale.
*
* @return A <code>BreakIterator</code> instance for the default locale.
*/
public static BreakIterator getCharacterInstance (Locale loc)
{
BreakIterator r = getInstance ("CharacterIterator", loc);
if (r == null)
r = new gnu.java.text.CharacterBreakIterator ();
return r;
}
/**
* This method returns an instance of <code>BreakIterator</code> that will
* iterate over line breaks as defined in the default locale.
*
* @return A <code>BreakIterator</code> instance for the default locale.
*/
public static BreakIterator getLineInstance ()
{
return getLineInstance (Locale.getDefault());
}
/**
* This method returns an instance of <code>BreakIterator</code> that will
* iterate over line breaks as defined in the specified locale. If the
* desired locale is not available, the default locale is used.
*
* @param locale The desired locale.
*
* @return A <code>BreakIterator</code> instance for the default locale.
*/
public static BreakIterator getLineInstance (Locale loc)
{
BreakIterator r = getInstance ("LineIterator", loc);
if (r == null)
r = new gnu.java.text.LineBreakIterator ();
return r;
}
/**
* This method returns an instance of <code>BreakIterator</code> that will
* iterate over sentences as defined in the default locale.
*
* @return A <code>BreakIterator</code> instance for the default locale.
*/
public static BreakIterator getSentenceInstance ()
{
return getSentenceInstance (Locale.getDefault());
}
/**
* This method returns an instance of <code>BreakIterator</code> that will
* iterate over sentences as defined in the specified locale. If the
* desired locale is not available, the default locale is used.
*
* @param locale The desired locale.
*
* @return A <code>BreakIterator</code> instance for the default locale.
*/
public static BreakIterator getSentenceInstance (Locale loc)
{
BreakIterator r = getInstance ("SentenceIterator", loc);
if (r == null)
r = new gnu.java.text.SentenceBreakIterator ();
return r;
}
/**
* This method returns the text this object is iterating over as a
* <code>CharacterIterator</code>.
*
* @param The text being iterated over.
*/
public abstract CharacterIterator getText ();
/**
* This method returns an instance of <code>BreakIterator</code> that will
* iterate over words as defined in the default locale.
*
* @return A <code>BreakIterator</code> instance for the default locale.
*/
public static BreakIterator getWordInstance ()
{
return getWordInstance (Locale.getDefault());
}
/**
* This method returns an instance of <code>BreakIterator</code> that will
* iterate over words as defined in the specified locale. If the
* desired locale is not available, the default locale is used.
*
* @param locale The desired locale.
*
* @return A <code>BreakIterator</code> instance for the default locale.
*/
public static BreakIterator getWordInstance (Locale loc)
{
BreakIterator r = getInstance ("WordIterator", loc);
if (r == null)
r = new gnu.java.text.WordBreakIterator ();
return r;
}
/**
* This method tests whether or not the specified position is a text
* element boundary.
*
* @param offset The text position to test.
*
* @return <code>true</code> if the position is a boundary,
* <code>false</code> otherwise.
*/
public boolean isBoundary (int pos)
{
if (pos == 0)
return true;
return following (pos - 1) == pos;
}
/**
* This method returns the last text element boundary in the text being
* iterated over.
*
* @return The last text boundary.
*/
public abstract int last ();
/**
* This method returns the text element boundary following the current
* text position.
*
* @return The next text boundary.
*/
public abstract int next ();
/**
* This method returns the n'th text element boundary following the current
* text position.
*
* @param n The number of text element boundaries to skip.
*
* @return The next text boundary.
*/
public abstract int next (int n);
/**
* This methdod returns the offset of the text element boundary preceding
* the specified offset.
*
* @param offset The text index from which to find the preceding
* text boundary.
*
* @returns The next text boundary preceding the specified index.
*/
public int preceding (int pos)
{
if (following (pos) == DONE)
last ();
while (previous () >= pos)
;
return current ();
}
/**
* This method returns the text element boundary preceding the current
* text position.
*
* @return The previous text boundary.
*/
public abstract int previous ();
/**
* This method sets the text string to iterate over.
*
* @param str The <code>String</code> to iterate over.
*/
public void setText (String newText)
{
setText (new StringCharacterIterator (newText));
}
/**
* This method sets the text to iterate over from the specified
* <code>CharacterIterator</code>.
*
* @param ci The desired <code>CharacterIterator</code>.
*/
public abstract void setText (CharacterIterator newText);
}
@@ -0,0 +1,144 @@
/* CharacterIterator.java -- Iterate over a character range
Copyright (C) 1998, 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
/**
* This interface defines a mechanism for iterating over a range of
* characters. For a given range of text, a beginning and ending index,
* as well as a current index are defined. These values can be queried
* by the methods in this interface. Additionally, various methods allow
* the index to be set.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
*/
public interface CharacterIterator extends Cloneable
{
/**
* This is a special constant value that is returned when the beginning or
* end of the character range has been reached.
*/
char DONE = '\uFFFF';
/**
* This method returns the character at the current index position
*
* @return The character at the current index position.
*/
char current();
/**
* This method increments the current index and then returns the character
* at the new index value. If the index is already at <code>getEndIndex() - 1</code>,
* it will not be incremented.
*
* @return The character at the position of the incremented index value,
* or <code>DONE</code> if the index has reached getEndIndex() - 1
*/
char next();
/**
* This method decrements the current index and then returns the character
* at the new index value. If the index value is already at the beginning
* index, it will not be decremented.
*
* @return The character at the position of the decremented index value,
* or <code>DONE</code> if index was already equal to the beginning index value.
*/
char previous();
/**
* This method sets the index value to the beginning of the range and returns
* the character there.
*
* @return The character at the beginning of the range, or <code>DONE</code> if the range is empty.
*/
char first();
/**
* This method sets the index value to <code>getEndIndex() - 1</code> and
* returns the character there. If the range is empty, then the index value
* will be set equal to the beginning index.
*
* @return The character at the end of the range, or <code>DONE</code> if the range is empty.
*/
char last();
/**
* This method returns the current value of the index.
*
* @return The current index value
*/
int getIndex();
/**
* This method sets the value of the index to the specified value, then
* returns the character at that position.
*
* @param index The new index value.
*
* @return The character at the new index value or <code>DONE</code> if the index value is equal to <code>getEndIndex</code>.
*/
char setIndex (int index) throws IllegalArgumentException;
/**
* This method returns the character position of the first character in the
* range.
*
* @return The index of the first character in the range.
*/
int getBeginIndex();
/**
* This method returns the character position of the end of the text range.
* This will actually be the index of the first character following the
* end of the range. In the event the text range is empty, this will be
* equal to the first character in the range.
*
* @return The index of the end of the range.
*/
int getEndIndex();
/**
* This method creates a copy of this <code>CharacterIterator</code>.
*
* @return A copy of this <code>CharacterIterator</code>.
*/
Object clone();
} // interface CharacterIterator
@@ -0,0 +1,503 @@
/* ChoiceFormat.java -- Format over a range of numbers
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.util.Vector;
/**
* This class allows a format to be specified based on a range of numbers.
* To use this class, first specify two lists of formats and range terminators.
* These lists must be arrays of equal length. The format of index
* <code>i</code> will be selected for value <code>X</code> if
* <code>terminator[i] &lt;= X &lt; limit[i + 1]</code>. If the value X is not
* included in any range, then either the first or last format will be
* used depending on whether the value X falls outside the range.
* <p>
* This sounds complicated, but that is because I did a poor job of
* explaining it. Consider the following example:
* <p>
*
<pre>terminators = { 1, ChoiceFormat.nextDouble(1) }
formats = { "file", "files" }</pre>
*
* <p>
* In this case if the actual number tested is one or less, then the word
* "file" is used as the format value. If the number tested is greater than
* one, then "files" is used. This allows plurals to be handled
* gracefully. Note the use of the method <code>nextDouble</code>. This
* method selects the next highest double number than its argument. This
* effectively makes any double greater than 1.0 cause the "files" string
* to be selected. (Note that all terminator values are specified as
* doubles.
* <p>
* Note that in order for this class to work properly, the range terminator
* array must be sorted in ascending order and the format string array
* must be the same length as the terminator array.
*
* @author Tom Tromey (tromey@cygnus.com)
* @author Aaron M. Renn (arenn@urbanophile.com)
* @date March 9, 1999
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 from http://www.javasoft.com.
* Status: Believed complete and correct to 1.1.
*/
public class ChoiceFormat extends NumberFormat
{
/**
* This method sets new range terminators and format strings for this
* object based on the specified pattern. This pattern is of the form
* "term#string|term#string...". For example "1#Sunday|2#Monday|#Tuesday".
*
* @param pattern The pattern of terminators and format strings.
*
* @exception IllegalArgumentException If the pattern is not valid
*/
public void applyPattern (String newPattern)
{
// Note: we assume the same kind of quoting rules apply here.
// This isn't explicitly documented. But for instance we accept
// '#' as a literal hash in a format string.
int index = 0, max = newPattern.length();
Vector stringVec = new Vector ();
Vector limitVec = new Vector ();
StringBuffer buf = new StringBuffer ();
while (true)
{
// Find end of double.
int dstart = index;
while (index < max)
{
char c = newPattern.charAt(index);
if (c == '#' || c == '\u2064' || c == '<')
break;
++index;
}
if (index == max)
throw new IllegalArgumentException ("unexpected end of text");
Double d = new Double (newPattern.substring(dstart, index));
if (newPattern.charAt(index) == '<')
d = new Double (nextDouble (d.doubleValue()));
limitVec.addElement(d);
// Scan text.
++index;
buf.setLength(0);
while (index < max)
{
char c = newPattern.charAt(index);
if (c == '\'' && index < max + 1
&& newPattern.charAt(index + 1) == '\'')
{
buf.append(c);
++index;
}
else if (c == '\'' && index < max + 2)
{
buf.append(newPattern.charAt(index + 1));
index += 2;
}
else if (c == '|')
break;
else
buf.append(c);
++index;
}
stringVec.addElement(buf.toString());
if (index == max)
break;
++index;
}
choiceFormats = new String[stringVec.size()];
stringVec.copyInto(choiceFormats);
choiceLimits = new double[limitVec.size()];
for (int i = 0; i < choiceLimits.length; ++i)
{
Double d = (Double) limitVec.elementAt(i);
choiceLimits[i] = d.doubleValue();
}
}
/**
* This method initializes a new instance of <code>ChoiceFormat</code> that
* generates its range terminator and format string arrays from the
* specified pattern. This pattern is of the form
* "term#string|term#string...". For example "1#Sunday|2#Monday|#Tuesday".
* This is the same pattern type used by the <code>applyPattern</code>
* method.
*
* @param pattern The pattern of terminators and format strings.
*
* @exception IllegalArgumentException If the pattern is not valid
*/
public ChoiceFormat (String newPattern)
{
super ();
applyPattern (newPattern);
}
/**
* This method initializes a new instance of <code>ChoiceFormat</code> that
* will use the specified range terminators and format strings.
*
* @param choiceLimits The array of range terminators
* @param choiceFormats The array of format strings
*/
public ChoiceFormat (double[] choiceLimits, String[] choiceFormats)
{
super ();
setChoices (choiceLimits, choiceFormats);
}
/**
* This method tests this object for equality with the specified
* object. This will be true if and only if:
* <ul>
* <li>The specified object is not <code>null</code>.</li>
* <li>The specified object is an instance of <code>ChoiceFormat</code>.</li>
* <li>The termination ranges and format strings are identical to
* this object's. </li>
* </ul>
*
* @param obj The object to test for equality against.
*
* @return <code>true</code> if the specified object is equal to
* this one, <code>false</code> otherwise.
*/
public boolean equals (Object obj)
{
if (! (obj instanceof ChoiceFormat))
return false;
ChoiceFormat cf = (ChoiceFormat) obj;
if (choiceLimits.length != cf.choiceLimits.length)
return false;
for (int i = choiceLimits.length - 1; i >= 0; --i)
{
if (choiceLimits[i] != cf.choiceLimits[i]
|| !choiceFormats[i].equals(cf.choiceFormats[i]))
return false;
}
return true;
}
/**
* This method appends the appropriate format string to the specified
* <code>StringBuffer</code> based on the supplied <code>long</code>
* argument.
*
* @param number The number used for determine (based on the range
* terminators) which format string to append.
* @param sb The <code>StringBuffer</code> to append the format string to.
* @param status Unused.
*
* @return The <code>StringBuffer</code> with the format string appended.
*/
public StringBuffer format (long num, StringBuffer appendBuf,
FieldPosition pos)
{
return format ((double) num, appendBuf, pos);
}
/**
* This method appends the appropriate format string to the specified
* <code>StringBuffer</code> based on the supplied <code>double</code>
* argument.
*
* @param number The number used for determine (based on the range
* terminators) which format string to append.
* @param sb The <code>StringBuffer</code> to append the format string to.
* @param status Unused.
*
* @return The <code>StringBuffer</code> with the format string appended.
*/
public StringBuffer format (double num, StringBuffer appendBuf,
FieldPosition pos)
{
if (choiceLimits.length == 0)
return appendBuf;
int index = 0;
if (! Double.isNaN(num) && num >= choiceLimits[0])
{
for (; index < choiceLimits.length - 1; ++index)
{
if (choiceLimits[index] <= num && num < choiceLimits[index + 1])
break;
}
}
return appendBuf.append(choiceFormats[index]);
}
/**
* This method returns the list of format strings in use.
*
* @return The list of format objects.
*/
public Object[] getFormats ()
{
return (Object[]) choiceFormats.clone();
}
/**
* This method returns the list of range terminators in use.
*
* @return The list of range terminators.
*/
public double[] getLimits ()
{
return (double[]) choiceLimits.clone();
}
/**
* This method returns a hash value for this object
*
* @return A hash value for this object.
*/
public int hashCode ()
{
int hash = 0;
for (int i = 0; i < choiceLimits.length; ++i)
{
long v = Double.doubleToLongBits(choiceLimits[i]);
hash ^= (v ^ (v >>> 32));
hash ^= choiceFormats[i].hashCode();
}
return hash;
}
/**
* This method returns the lowest possible double greater than the
* specified double. If the specified double value is equal to
* <code>Double.NaN</code> then that is the value returned.
*
* @param d The specified double
*
* @return The lowest double value greater than the specified double.
*/
public static final double nextDouble (double d)
{
return nextDouble (d, true);
}
/**
* This method returns a double that is either the next highest double
* or next lowest double compared to the specified double depending on the
* value of the passed boolean parameter. If the boolean parameter is
* <code>true</code>, then the lowest possible double greater than the
* specified double will be returned. Otherwise the highest possible
* double less than the specified double will be returned.
*
* @param d The specified double
* @param positive <code>true</code> to return the next highest
* double, <code>false</code> otherwise.
*
* @return The next highest or lowest double value.
*/
public static double nextDouble (double d, boolean next)
{
if (Double.isInfinite(d) || Double.isNaN(d))
return d;
long bits = Double.doubleToLongBits(d);
long mantMask = (1L << mantissaBits) - 1;
long mantissa = bits & mantMask;
long expMask = (1L << exponentBits) - 1;
long exponent = (bits >>> mantissaBits) & expMask;
if (next ^ (bits < 0)) // Increment magnitude
{
if (mantissa == (1L << mantissaBits) - 1)
{
mantissa = 0L;
exponent++;
// Check for absolute overflow.
if (exponent >= (1L << mantissaBits))
return (bits > 0) ? Double.POSITIVE_INFINITY
: Double.NEGATIVE_INFINITY;
}
else
mantissa++;
}
else // Decrement magnitude
{
if (exponent == 0L && mantissa == 0L)
{
// The only case where there is a change of sign
return next ? Double.MIN_VALUE : -Double.MIN_VALUE;
}
else
{
if (mantissa == 0L)
{
mantissa = (1L << mantissaBits) - 1;
exponent--;
}
else
mantissa--;
}
}
long result = bits < 0 ? 1 : 0;
result = (result << exponentBits) | exponent;
result = (result << mantissaBits) | mantissa;
return Double.longBitsToDouble(result);
}
/**
* I'm not sure what this method is really supposed to do, as it is
* not documented.
*/
public Number parse (String sourceStr, ParsePosition pos)
{
int index = pos.getIndex();
for (int i = 0; i < choiceLimits.length; ++i)
{
if (sourceStr.startsWith(choiceFormats[i], index))
{
pos.setIndex(index + choiceFormats[i].length());
return new Double (choiceLimits[i]);
}
}
pos.setErrorIndex(index);
return new Double (Double.NaN);
}
/**
* This method returns the highest possible double less than the
* specified double. If the specified double value is equal to
* <code>Double.NaN</code> then that is the value returned.
*
* @param d The specified double
*
* @return The highest double value less than the specified double.
*/
public static final double previousDouble (double d)
{
return nextDouble (d, false);
}
/**
* This method sets new range terminators and format strings for this
* object.
*
* @param choiceLimits The new range terminators
* @param choiceFormats The new choice formats
*/
public void setChoices (double[] choiceLimits, String[] choiceFormats)
{
if (choiceLimits == null || choiceFormats == null)
throw new NullPointerException ();
if (choiceLimits.length != choiceFormats.length)
throw new IllegalArgumentException ();
this.choiceFormats = (String[]) choiceFormats.clone();
this.choiceLimits = (double[]) choiceLimits.clone();
}
private void quoteString (StringBuffer dest, String text)
{
int max = text.length();
for (int i = 0; i < max; ++i)
{
char c = text.charAt(i);
if (c == '\'')
{
dest.append(c);
dest.append(c);
}
else if (c == '#' || c == '|' || c == '\u2064' || c == '<')
{
dest.append('\'');
dest.append(c);
dest.append('\'');
}
else
dest.append(c);
}
}
/**
* This method returns the range terminator list and format string list
* as a <code>String</code> suitable for using with the
* <code>applyPattern</code> method.
*
* @return A pattern string for this object
*/
public String toPattern ()
{
StringBuffer result = new StringBuffer ();
for (int i = 0; i < choiceLimits.length; ++i)
{
result.append(choiceLimits[i]);
result.append('#');
quoteString (result, choiceFormats[i]);
}
return result.toString();
}
/**
* This is the list of format strings. Note that this variable is
* specified by the serialization spec of this class.
*/
private String[] choiceFormats;
/**
* This is the list of range terminator values. Note that this variable is
* specified by the serialization spec of this class.
*/
private double[] choiceLimits;
// Number of mantissa bits in double.
private static final int mantissaBits = 52;
// Number of exponent bits in a double.
private static final int exponentBits = 11;
private static final long serialVersionUID = 1795184449645032964L;
}
@@ -0,0 +1,467 @@
/* CollationElementIterator.java -- Walks through collation elements
Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.util.ArrayList;
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 from http://www.javasoft.com.
* Status: Believed complete and correct to JDK 1.1.
*/
/**
* This class walks through the character collation elements of a
* <code>String</code> as defined by the collation rules in an instance of
* <code>RuleBasedCollator</code>. There is no public constructor for
* this class. An instance is created by calling the
* <code>getCollationElementIterator</code> method on
* <code>RuleBasedCollator</code>.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Tom Tromey (tromey@cygnus.com)
* @author Guilhem Lavaux (guilhem.lavaux@free.fr)
*/
public final class CollationElementIterator
{
/**
* This is a constant value that is returned to indicate that the end of
* the string was encountered.
*/
public static final int NULLORDER = -1;
/**
* This is the RuleBasedCollator this object was created from.
*/
RuleBasedCollator collator;
/**
* This is the String that is being iterated over.
*/
String text;
/**
* This is the index into the collation decomposition where we are currently scanning.
*/
int index;
/**
* This is the index into the String where we are currently scanning.
*/
int textIndex;
/**
* Array containing the collation decomposition of the
* text given to the constructor.
*/
private RuleBasedCollator.CollationElement[] text_decomposition;
/**
* Array containing the index of the specified block.
*/
private int[] text_indexes;
/**
* This method initializes a new instance of <code>CollationElementIterator</code>
* to iterate over the specified <code>String</code> using the rules in the
* specified <code>RuleBasedCollator</code>.
*
* @param collator The <code>RuleBasedCollation</code> used for calculating collation values
* @param text The <code>String</code> to iterate over.
*/
CollationElementIterator(RuleBasedCollator collator, String text)
{
this.collator = collator;
setText (text);
}
RuleBasedCollator.CollationElement nextBlock()
{
if (index >= text_decomposition.length)
return null;
RuleBasedCollator.CollationElement e = text_decomposition[index];
textIndex = text_indexes[index+1];
index++;
return e;
}
RuleBasedCollator.CollationElement previousBlock()
{
if (index == 0)
return null;
index--;
RuleBasedCollator.CollationElement e = text_decomposition[index];
textIndex = text_indexes[index+1];
return e;
}
/**
* This method returns the collation ordering value of the next character sequence
* in the string (it may be an extended character following collation rules).
* This method will return <code>NULLORDER</code> if the
* end of the string was reached.
*
* @return The collation ordering value.
*/
public int next()
{
RuleBasedCollator.CollationElement e = nextBlock();
if (e == null)
return NULLORDER;
return e.getValue();
}
/**
* This method returns the collation ordering value of the previous character
* in the string. This method will return <code>NULLORDER</code> if the
* beginning of the string was reached.
*
* @return The collation ordering value.
*/
public int previous()
{
RuleBasedCollator.CollationElement e = previousBlock();
if (e == null)
return NULLORDER;
return e.getValue();
}
/**
* This method returns the primary order value for the given collation
* value.
*
* @param value The collation value returned from <code>next()</code> or <code>previous()</code>.
*
* @return The primary order value of the specified collation value. This is the high 16 bits.
*/
public static int primaryOrder(int order)
{
// From the JDK 1.2 spec.
return order >>> 16;
}
/**
* This method resets the internal position pointer to read from the
* beginning of the <code>String</code> again.
*/
public void reset()
{
index = 0;
textIndex = 0;
}
/**
* This method returns the secondary order value for the given collation
* value.
*
* @param value The collation value returned from <code>next()</code> or <code>previous()</code>.
*
* @return The secondary order value of the specified collation value. This is the bits 8-15.
*/
public static short secondaryOrder(int order)
{
// From the JDK 1.2 spec.
return (short) ((order >>> 8) & 255);
}
/**
* This method returns the tertiary order value for the given collation
* value.
*
* @param value The collation value returned from <code>next()</code> or <code>previous()</code>.
*
* @return The tertiary order value of the specified collation value. This is the low eight bits.
*/
public static short tertiaryOrder(int order)
{
// From the JDK 1.2 spec.
return (short) (order & 255);
}
/**
* This method sets the <code>String</code> that it is iterating over
* to the specified <code>String</code>.
*
* @param text The new <code>String</code> to iterate over.
*
* @since 1.2
*/
public void setText(String text)
{
int idx = 0;
int idx_idx = 0;
int alreadyExpanded = 0;
int idxToMove = 0;
this.text = text;
this.index = 0;
String work_text = text.intern();
ArrayList a_element = new ArrayList();
ArrayList a_idx = new ArrayList();
// Build element collection ordered as they come in "text".
while (idx < work_text.length())
{
String key, key_old;
Object object = null;
int p = 1;
// IMPROVE: use a TreeMap with a prefix-ordering rule.
key_old = key = null;
do
{
if (object != null)
key_old = key;
key = work_text.substring (idx, idx+p);
object = collator.prefix_tree.get (key);
if (object != null && idx < alreadyExpanded)
{
RuleBasedCollator.CollationElement prefix = (RuleBasedCollator.CollationElement)object;
if (prefix.expansion != null &&
prefix.expansion.startsWith(work_text.substring(0, idx)))
{
object = null;
key = key_old;
}
}
p++;
}
while (idx+p <= work_text.length());
if (object == null)
key = key_old;
RuleBasedCollator.CollationElement prefix =
(RuleBasedCollator.CollationElement) collator.prefix_tree.get (key);
/*
* First case: There is no such sequence in the database.
* We will have to build one from the context.
*/
if (prefix == null)
{
/*
* We are dealing with sequences in an expansion. They
* are treated as accented characters (tertiary order).
*/
if (alreadyExpanded > 0)
{
RuleBasedCollator.CollationElement e =
collator.getDefaultAccentedElement (work_text.charAt (idx));
a_element.add (e);
a_idx.add (new Integer(idx_idx));
idx++;
alreadyExpanded--;
if (alreadyExpanded == 0)
{
/* There is not any characters left in the expansion set.
* We can increase the pointer in the source string.
*/
idx_idx += idxToMove;
idxToMove = 0;
}
else
idx_idx++;
}
else
{
/* This is a normal character. */
RuleBasedCollator.CollationElement e =
collator.getDefaultElement (work_text.charAt (idx));
Integer i_ref = new Integer(idx_idx);
/* Don't forget to mark it as a special sequence so the
* string can be ordered.
*/
a_element.add (RuleBasedCollator.SPECIAL_UNKNOWN_SEQ);
a_idx.add (i_ref);
a_element.add (e);
a_idx.add (i_ref);
idx_idx++;
idx++;
}
continue;
}
/*
* Second case: Here we have found a matching sequence.
* Here we have an expansion string prepend it to the "work text" and
* add the corresponding sorting element. We must also mark
*/
if (prefix.expansion != null)
{
work_text = prefix.expansion
+ work_text.substring (idx+prefix.key.length());
idx = 0;
a_element.add (prefix);
a_idx.add (new Integer(idx_idx));
if (alreadyExpanded == 0)
idxToMove = prefix.key.length();
alreadyExpanded += prefix.expansion.length()-prefix.key.length();
}
else
{
/* Third case: the simplest. We have got the prefix and it
* has not to be expanded.
*/
a_element.add (prefix);
a_idx.add (new Integer(idx_idx));
idx += prefix.key.length();
/* If the sequence is in an expansion, we must decrease the
* counter.
*/
if (alreadyExpanded > 0)
{
alreadyExpanded -= prefix.key.length();
if (alreadyExpanded == 0)
{
idx_idx += idxToMove;
idxToMove = 0;
}
}
else
idx_idx += prefix.key.length();
}
}
text_decomposition = (RuleBasedCollator.CollationElement[])
a_element.toArray(new RuleBasedCollator.CollationElement[a_element.size()]);
text_indexes = new int[a_idx.size()+1];
for (int i = 0; i < a_idx.size(); i++)
{
text_indexes[i] = ((Integer)a_idx.get(i)).intValue();
}
text_indexes[a_idx.size()] = text.length();
}
/**
* This method sets the <code>String</code> that it is iterating over
* to the <code>String</code> represented by the specified
* <code>CharacterIterator</code>.
*
* @param source The <code>CharacterIterator</code> containing the new
* <code>String</code> to iterate over.
*/
public void setText(CharacterIterator source)
{
StringBuffer expand = new StringBuffer();
// For now assume we read from the beginning of the string.
for (char c = source.first();
c != CharacterIterator.DONE;
c = source.next())
expand.append(c);
setText(expand.toString());
}
/**
* This method returns the current offset into the <code>String</code>
* that is being iterated over.
*
* @return The iteration index position.
*
* @since 1.2
*/
public int getOffset()
{
return textIndex;
}
/**
* This method sets the iteration index position into the current
* <code>String</code> to the specified value. This value must not
* be negative and must not be greater than the last index position
* in the <code>String</code>.
*
* @param offset The new iteration index position.
*
* @exception IllegalArgumentException If the new offset is not valid.
*/
public void setOffset(int offset)
{
if (offset < 0)
throw new IllegalArgumentException("Negative offset: " + offset);
if (offset > (text.length() - 1))
throw new IllegalArgumentException("Offset too large: " + offset);
for (index = 0; index < text_decomposition.length; index++)
{
if (offset <= text_indexes[index])
break;
}
/*
* As text_indexes[0] == 0, we should not have to take care whether index is
* greater than 0. It is always.
*/
if (text_indexes[index] == offset)
textIndex = offset;
else
textIndex = text_indexes[index-1];
}
/**
* This method returns the maximum length of any expansion sequence that
* ends with the specified collation order value. (Whatever that means).
*
* @param value The collation order value
*
* @param The maximum length of an expansion sequence.
*/
public int getMaxExpansion(int value)
{
return 1;
}
}
@@ -0,0 +1,199 @@
/* CollationKey.java -- Precomputed collation value
Copyright (C) 1998, 1999, 2000, 2003, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 from http://www.javasoft.com.
* Status: Believed complete and correct.
*/
/**
* This class represents a pre-computed series of bits representing a
* <code>String</code> for under a particular <code>Collator</code>. This
* value may be compared bitwise against another <code>CollationKey</code>
* representing a different <code>String</code> under the same
* <code>Collator</code> in a manner than is usually more efficient than
* using the raw <code>Collator</code> compare methods. There is overhead
* associated with calculating this value, so it is generally not
* advisable to compute <code>CollationKey</code>'s unless multiple
* comparisons against a <code>String</code> will be done. (For example,
* in a sort routine).
* <p>
* This class cannot be instantiated directly. Instead, a
* <code>CollationKey</code> is created by calling the
* <code>getCollationKey</code> method on an instance of <code>Collator</code>.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Tom Tromey (tromey@cygnus.com)
* @date March 25, 1999
*/
public final class CollationKey implements Comparable
{
/**
* This is the <code>Collator</code> this object was created from.
*/
private Collator collator;
/**
* This is the <code>String</code> this object represents.
*/
private String originalText;
/**
* This is the bit value for this key.
*/
private byte[] key;
CollationKey (Collator collator, String originalText, byte[] key)
{
this.collator = collator;
this.originalText = originalText;
this.key = key;
}
/**
* This method compares the specified object to this one. An integer is
* returned which indicates whether the specified object is less than,
* greater than, or equal to this object.
*
* @param ck The <code>CollationKey</code> to compare against this one.
*
* @return A negative integer if this object is less than the specified object, 0 if it is equal or a positive integer if it is greater than the specified object.
*/
public int compareTo (CollationKey ck)
{
int max = Math.min (key.length, ck.key.length);
for (int i = 0; i < max; ++i)
{
if (key[i] != ck.key[i])
return key[i] - ck.key[i];
}
return key.length - ck.key.length;
}
/**
* This method compares the specified object to this one. The specified
* object must be an instance of <code>CollationKey</code> or an exception
* will be thrown. An integer is returned which indicates whether the
* specified object is less than, greater than, or equal to this object.
*
* @param obj The <code>Object</code> to compare against this one.
*
* @return A negative integer if this object is less than the specified object, 0 if it is equal or a positive integer if it is greater than the specified object.
*/
public int compareTo (Object obj)
{
return compareTo ((CollationKey) obj);
}
/**
* This method tests the specified <code>Object</code> for equality with
* this object. This will be true if and only if:
* <p>
* <ul>
* <li>The specified object must not be <code>null</code></li>
* <li>The specified object is an instance of <code>CollationKey</code>.</li>
* <li>The specified object was created from the same <code>Collator</code>
* as this object.</li>
* <li>The specified object has the same source string and bit key as
* this object.</li>
* </ul>
*
* @param obj The <code>Object</code> to test for equality.
*
* @return <code>true</code> if the specified object is equal to this one, <code>false</code> otherwise.
*/
public boolean equals (Object obj)
{
if (! (obj instanceof CollationKey))
return false;
CollationKey ck = (CollationKey) obj;
if (ck.collator != collator)
return false;
if (!ck.getSourceString ().equals (getSourceString ()))
return false;
if (!ck.toByteArray ().equals (toByteArray ()))
return false;
return true;
}
/**
* This method returns the <code>String</code> that this object was created
* from.
*
* @return The source <code>String</code> for this object.
*/
public String getSourceString()
{
return originalText;
}
/**
* This method returns a hash value for this object. The hash value
* returned will be the hash code of the bit key so that identical bit
* keys will return the same value.
*
* @return A hash value for this object.
*/
public int hashCode()
{
// We just follow BitSet instead of thinking up something new.
long h = originalText.hashCode();
for (int i = key.length - 1; i >= 0; --i)
h ^= key[i] * (i + 1);
return (int) ((h >> 32) ^ h);
}
/**
* This method returns the collation bit sequence as a byte array.
*
* @param A byte array containing the collation bit sequence.
*/
public byte[] toByteArray()
{
return key;
}
}
+400
View File
@@ -0,0 +1,400 @@
/* Collator.java -- Perform locale dependent String comparisons.
Copyright (C) 1998, 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.util.Comparator;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* This class is the abstract superclass of classes which perform
* locale dependent <code>String</code> comparisons. A caller requests
* an instance of <code>Collator</code> for a particular locale using
* the <code>getInstance()</code> static method in this class. That method
* will return a locale specific subclass of <code>Collator</code> which
* can be used to perform <code>String</code> comparisons for that locale.
* If a subclass of <code>Collator</code> cannot be located for a particular
* locale, a default instance for the current locale will be returned.
*
* In addition to setting the correct locale, there are two additional
* settings that can be adjusted to affect <code>String</code> comparisons:
* strength and decomposition. The strength value determines the level
* of signficance of character differences required for them to sort
* differently. (For example, whether or not capital letters are considered
* different from lower case letters). The decomposition value affects how
* variants of the same character are treated for sorting purposes. (For
* example, whether or not an accent is signficant or not). These settings
* are described in detail in the documentation for the methods and values
* that are related to them.
*
* @author Tom Tromey (tromey@cygnus.com)
* @author Aaron M. Renn (arenn@urbanophile.com)
* @date March 18, 1999
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 from http://www.javasoft.com.
* Status: Mostly complete, but parts stubbed out. Look for FIXME.
*/
public abstract class Collator implements Comparator, Cloneable
{
/**
* This constant is a strength value which indicates that only primary
* differences between characters will be considered signficant. As an
* example, two completely different English letters such as 'a' and 'b'
* are considered to have a primary difference.
*/
public static final int PRIMARY = 0;
/**
* This constant is a strength value which indicates that only secondary
* or primary differences between characters will be considered
* significant. An example of a secondary difference between characters
* are instances of the same letter with different accented forms.
*/
public static final int SECONDARY = 1;
/**
* This constant is a strength value which indicates that tertiary,
* secondary, and primary differences will be considered during sorting.
* An example of a tertiary difference is capitalization of a given letter.
* This is the default value for the strength setting.
*/
public static final int TERTIARY = 2;
/**
* This constant is a strength value which indicates that any difference
* at all between character values are considered significant.
*/
public static final int IDENTICAL = 3;
/**
* This constant indicates that accented characters won't be decomposed
* when performing comparisons. This will yield the fastest results, but
* will only work correctly in call cases for languages which do not
* use accents such as English.
*/
public static final int NO_DECOMPOSITION = 0;
/**
* This constant indicates that only characters which are canonical variants
* in Unicode 2.0 will be decomposed prior to performing comparisons. This
* will cause accented languages to be sorted correctly. This is the
* default decomposition value.
*/
public static final int CANONICAL_DECOMPOSITION = 1;
/**
* This constant indicates that both canonical variants and compatibility
* variants in Unicode 2.0 will be decomposed prior to performing
* comparisons. This is the slowest mode, but is required to get the
* correct sorting for certain languages with certain special formats.
*/
public static final int FULL_DECOMPOSITION = 2;
/**
* This method initializes a new instance of <code>Collator</code> to have
* the default strength (TERTIARY) and decomposition
* (CANONICAL_DECOMPOSITION) settings. This constructor is protected and
* is for use by subclasses only. Non-subclass callers should use the
* static <code>getInstance()</code> methods of this class to instantiate
* <code>Collation</code> objects for the desired locale.
*/
protected Collator ()
{
strength = TERTIARY;
decmp = CANONICAL_DECOMPOSITION;
}
/**
* This method compares the two <code>String</code>'s and returns an
* integer indicating whether or not the first argument is less than,
* equal to, or greater than the second argument. The comparison is
* performed according to the rules of the locale for this
* <code>Collator</code> and the strength and decomposition rules in
* effect.
*
* @param str1 The first object to compare
* @param str2 The second object to compare
*
* @return A negative integer if str1 &lt; str2, 0 if str1 == str2, or
* a positive integer if str1 &gt; str2.
*/
public abstract int compare (String source, String target);
/**
* This method compares the two <code>Object</code>'s and returns an
* integer indicating whether or not the first argument is less than,
* equal to, or greater than the second argument. These two objects
* must be <code>String</code>'s or an exception will be thrown.
*
* @param obj1 The first object to compare
* @param obj2 The second object to compare
*
* @return A negative integer if obj1 &lt; obj2, 0 if obj1 == obj2, or
* a positive integer if obj1 &gt; obj2.
*
* @exception ClassCastException If the arguments are not instances
* of <code>String</code>.
*/
public int compare (Object o1, Object o2)
{
return compare ((String) o1, (String) o2);
}
/**
* This method tests the specified object for equality against this
* object. This will be true if and only if the following conditions are
* met:
* <ul>
* <li>The specified object is not <code>null</code>.</li>
* <li>The specified object is an instance of <code>Collator</code>.</li>
* <li>The specified object has the same strength and decomposition
* settings as this object.</li>
* </ul>
*
* @param obj The <code>Object</code> to test for equality against
* this object.
*
* @return <code>true</code> if the specified object is equal to
* this one, <code>false</code> otherwise.
*/
public boolean equals (Object obj)
{
if (! (obj instanceof Collator))
return false;
Collator c = (Collator) obj;
return decmp == c.decmp && strength == c.strength;
}
/**
* This method tests whether the specified <code>String</code>'s are equal
* according to the collation rules for the locale of this object and
* the current strength and decomposition settings.
*
* @param str1 The first <code>String</code> to compare
* @param str2 The second <code>String</code> to compare
*
* @return <code>true</code> if the two strings are equal,
* <code>false</code> otherwise.
*/
public boolean equals (String source, String target)
{
return compare (source, target) == 0;
}
/**
* This method returns a copy of this <code>Collator</code> object.
*
* @return A duplicate of this object.
*/
public Object clone ()
{
try
{
return super.clone ();
}
catch (CloneNotSupportedException _)
{
return null;
}
}
/**
* This method returns an array of <code>Locale</code> objects which is
* the list of locales for which <code>Collator</code> objects exist.
*
* @return The list of locales for which <code>Collator</code>'s exist.
*/
public static synchronized Locale[] getAvailableLocales ()
{
// FIXME
Locale[] l = new Locale[1];
l[0] = Locale.US;
return l;
}
/**
* This method transforms the specified <code>String</code> into a
* <code>CollationKey</code> for faster comparisons. This is useful when
* comparisons against a string might be performed multiple times, such
* as during a sort operation.
*
* @param str The <code>String</code> to convert.
*
* @return A <code>CollationKey</code> for the specified <code>String</code>.
*/
public abstract CollationKey getCollationKey (String source);
/**
* This method returns the current decomposition setting for this
* object. This * will be one of NO_DECOMPOSITION,
* CANONICAL_DECOMPOSITION, or * FULL_DECOMPOSITION. See the
* documentation for those constants for an * explanation of this
* setting.
*
* @return The current decomposition setting.
*/
public synchronized int getDecomposition ()
{
return decmp;
}
/**
* This method returns an instance of <code>Collator</code> for the
* default locale.
*
* @return A <code>Collator</code> for the default locale.
*/
public static Collator getInstance ()
{
return getInstance (Locale.getDefault());
}
/**
* This method returns an instance of <code>Collator</code> for the
* specified locale. If no <code>Collator</code> exists for the desired
* locale, a <code>Collator</code> for the default locale will be returned.
*
* @param locale The desired localed to load a <code>Collator</code> for.
*
* @return A <code>Collator</code> for the requested locale
*/
public static Collator getInstance (Locale loc)
{
ResourceBundle res;
String pattern;
try
{
res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
loc, ClassLoader.getSystemClassLoader());
pattern = res.getString("collation_rules");
}
catch (MissingResourceException x)
{
pattern = "<0<1<2<3<4<5<6<7<8<9<A,a<b,B<c,C<d,D<e,E<f,F<g,G<h,H<i,I<j,J<k,K" +
"<l,L<m,M<n,N<o,O<p,P<q,Q<r,R<s,S<t,T<u,U<v,V<w,W<x,X<y,Y<z,Z";
}
try
{
return new RuleBasedCollator (pattern);
}
catch (ParseException x)
{
throw (InternalError)new InternalError().initCause(x);
}
}
/**
* This method returns the current strength setting for this object. This
* will be one of PRIMARY, SECONDARY, TERTIARY, or IDENTICAL. See the
* documentation for those constants for an explanation of this setting.
*
* @return The current strength setting.
*/
public synchronized int getStrength ()
{
return strength;
}
/**
* This method returns a hash code value for this object.
*
* @return A hash value for this object.
*/
public abstract int hashCode ();
/**
* This method sets the decomposition setting for this object to the
* specified value. This must be one of NO_DECOMPOSITION,
* CANONICAL_DECOMPOSITION, or FULL_DECOMPOSITION. Otherwise an
* exception will be thrown. See the documentation for those
* contants for an explanation of this setting.
*
* @param decmp The new decomposition setting.
*
* @exception IllegalArgumentException If the requested
* decomposition setting is not valid.
*/
public synchronized void setDecomposition (int mode)
{
if (mode != NO_DECOMPOSITION
&& mode != CANONICAL_DECOMPOSITION
&& mode != FULL_DECOMPOSITION)
throw new IllegalArgumentException ();
decmp = mode;
}
/**
* This method sets the strength setting for this object to the specified
* value. This must be one of PRIMARY, SECONDARY, TERTIARY, or IDENTICAL.
* Otherwise an exception is thrown. See the documentation for these
* constants for an explanation of this setting.
*
* @param strength The new strength setting.
*
* @exception IllegalArgumentException If the requested strength
* setting value is not valid.
*/
public synchronized void setStrength (int strength)
{
if (strength != PRIMARY && strength != SECONDARY
&& strength != TERTIARY && strength != IDENTICAL)
throw new IllegalArgumentException ();
this.strength = strength;
}
// Decompose a single character and append results to the buffer.
// FIXME: for libgcj this is a native method which handles
// decomposition. For Classpath, for now, it does nothing.
final void decomposeCharacter (char c, StringBuffer buf)
{
buf.append (c);
}
/**
* This is the current collation decomposition setting.
*/
int decmp;
/**
* This is the current collation strength setting.
*/
int strength;
}
+892
View File
@@ -0,0 +1,892 @@
/* DateFormat.java -- Class for formatting/parsing date/times
Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.io.InvalidObjectException;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.TimeZone;
/**
* @author Per Bothner (bothner@cygnus.com)
* @date October 25, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 beta from http://www.javasoft.com.
* Status: Mostly complete; search for FIXME to see omissions.
*/
public abstract class DateFormat extends Format implements Cloneable
{
protected Calendar calendar;
protected NumberFormat numberFormat;
// (Values determined using a test program.)
public static final int FULL = 0;
public static final int LONG = 1;
public static final int MEDIUM = 2;
public static final int SHORT = 3;
public static final int DEFAULT = MEDIUM;
/* These constants need to have these exact values. They
* correspond to index positions within the localPatternChars
* string for a given locale. Each locale may specify its
* own character for a particular field, but the position
* of these characters must correspond to an appropriate field
* number (as listed below), in order for their meaning to
* be determined. For example, the US locale uses
* the string "GyMdkHmsSEDFwWahKzYeugAZ", where 'G' is the character
* for era, 'y' for year, and so on down to 'Z' for time zone.
*/
/**
* Represents the position of the era
* pattern character in the array of
* localized pattern characters.
* For example, 'AD' is an era used
* in the Gregorian calendar system.
* In the U.S. locale, this is 'G'.
*/
public static final int ERA_FIELD = 0;
/**
* Represents the position of the year
* pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'y'.
*/
public static final int YEAR_FIELD = 1;
/**
* Represents the position of the month
* pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'M'.
*/
public static final int MONTH_FIELD = 2;
/**
* Represents the position of the date
* or day of the month pattern character
* in the array of localized pattern
* characters. In the U.S. locale,
* this is 'd'.
*/
public static final int DATE_FIELD = 3;
/**
* Represents the position of the 24
* hour pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'k'.
* This field numbers hours from 1 to 24.
*/
public static final int HOUR_OF_DAY1_FIELD = 4;
/**
* Represents the position of the 24
* hour pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'H'.
* This field numbers hours from 0 to 23.
*/
public static final int HOUR_OF_DAY0_FIELD = 5;
/**
* Represents the position of the minute
* pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'm'.
*/
public static final int MINUTE_FIELD = 6;
/**
* Represents the position of the second
* pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 's'.
*/
public static final int SECOND_FIELD = 7;
/**
* Represents the position of the millisecond
* pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'S'.
*/
public static final int MILLISECOND_FIELD = 8;
/**
* Represents the position of the day of the
* week pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'E'.
*/
public static final int DAY_OF_WEEK_FIELD = 9;
/**
* Represents the position of the day of the
* year pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'D'.
*/
public static final int DAY_OF_YEAR_FIELD = 10;
/**
* Represents the position of the day of the
* week in the month pattern character in the
* array of localized pattern characters.
* In the U.S. locale, this is 'F'.
*/
public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
/**
* Represents the position of the week of the
* year pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'w'.
*/
public static final int WEEK_OF_YEAR_FIELD = 12;
/**
* Represents the position of the week of the
* month pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'W'.
*/
public static final int WEEK_OF_MONTH_FIELD = 13;
/**
* Represents the position of the am/pm
* pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'a'.
*/
public static final int AM_PM_FIELD = 14;
/**
* Represents the position of the 12
* hour pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'h'.
* This field numbers hours from 1 to 12.
*/
public static final int HOUR1_FIELD = 15;
/**
* Represents the position of the 12
* hour pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'K'.
* This field numbers hours from 0 to 11.
*/
public static final int HOUR0_FIELD = 16;
/**
* Represents the position of the generic
* timezone pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'z'.
*/
public static final int TIMEZONE_FIELD = 17;
/**
* Represents the position of the ISO year
* pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'Y'.
* This is a GNU extension in accordance with
* the CLDR data used. This value may
* differ from the normal year value.
*/
public static final int ISO_YEAR_FIELD = 18;
/**
* Represents the position of the localized
* day of the week pattern character in the
* array of localized pattern characters.
* In the U.S. locale, this is 'e'.
* This is a GNU extension in accordance with
* the CLDR data used. This value only
* differs from the day of the week with
* numeric formatting, in which case the
* locale's first day of the week is used.
*/
public static final int LOCALIZED_DAY_OF_WEEK_FIELD = 19;
/**
* Represents the position of the extended year
* pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'u'.
* This is a GNU extension in accordance with
* the CLDR data used. This value modifies
* the year value, so as to incorporate the era.
* For example, in the Gregorian calendar system,
* the extended year is negative instead of being
* marked as BC.
*/
public static final int EXTENDED_YEAR_FIELD = 20;
/**
* Represents the position of the modified Julian
* day pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'g'.
* This is a GNU extension in accordance with
* the CLDR data used. This value differs
* from the standard Julian day in that days
* are marked from midnight onwards rather than
* noon, and the local time zone affects the value.
* In simple terms, it can be thought of as all
* the date fields represented as a single number.
*/
public static final int MODIFIED_JULIAN_DAY_FIELD = 21;
/**
* Represents the position of the millisecond
* in the day pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'A'.
* This is a GNU extension in accordance with
* the CLDR data used. This value represents
* all the time fields (excluding the time zone)
* numerically, giving the number of milliseconds
* into the day (e.g. 10 in the morning would
* be 10 * 60 * 60 * 1000). Any daylight savings
* offset also affects this value.
*/
public static final int MILLISECOND_IN_DAY_FIELD = 22;
/**
* Represents the position of the RFC822
* timezone pattern character in the array of
* localized pattern characters.
* In the U.S. locale, this is 'Z'.
* This is a GNU extension in accordance with
* the CLDR data used. The value is the offset
* of the current time from GMT e.g. -0500 would
* be five hours prior to GMT.
*/
public static final int RFC822_TIMEZONE_FIELD = 23;
public static class Field extends Format.Field
{
static final long serialVersionUID = 7441350119349544720L;
private int calendarField;
public static final DateFormat.Field ERA
= new Field("era", Calendar.ERA);
public static final DateFormat.Field YEAR
= new Field("year", Calendar.YEAR);
public static final DateFormat.Field MONTH
= new Field("month", Calendar.MONTH);
public static final DateFormat.Field DAY_OF_MONTH
= new Field("day of month", Calendar.DAY_OF_MONTH);
public static final DateFormat.Field HOUR_OF_DAY1
= new Field("hour of day 1", Calendar.HOUR_OF_DAY);
public static final DateFormat.Field HOUR_OF_DAY0
= new Field("hour of day 0", Calendar.HOUR_OF_DAY);
public static final DateFormat.Field MINUTE
= new Field("minute", Calendar.MINUTE);
public static final DateFormat.Field SECOND
= new Field("second", Calendar.SECOND);
public static final DateFormat.Field MILLISECOND
= new Field("millisecond", Calendar.MILLISECOND);
public static final DateFormat.Field DAY_OF_WEEK
= new Field("day of week", Calendar.DAY_OF_WEEK);
public static final DateFormat.Field DAY_OF_YEAR
= new Field("day of year", Calendar.DAY_OF_YEAR);
public static final DateFormat.Field DAY_OF_WEEK_IN_MONTH
= new Field("day of week in month", Calendar.DAY_OF_WEEK_IN_MONTH);
public static final DateFormat.Field WEEK_OF_YEAR
= new Field("week of year", Calendar.WEEK_OF_YEAR);
public static final DateFormat.Field WEEK_OF_MONTH
= new Field("week of month", Calendar.WEEK_OF_MONTH);
public static final DateFormat.Field AM_PM
= new Field("am/pm", Calendar.AM_PM);
public static final DateFormat.Field HOUR1
= new Field("hour1", Calendar.HOUR);
public static final DateFormat.Field HOUR0
= new Field("hour0", Calendar.HOUR);
public static final DateFormat.Field TIME_ZONE
= new Field("timezone", Calendar.ZONE_OFFSET);
public static final DateFormat.Field ISO_YEAR
= new Field("iso year", Calendar.YEAR);
public static final DateFormat.Field LOCALIZED_DAY_OF_WEEK
= new Field("localized day of week", Calendar.DAY_OF_WEEK);
public static final DateFormat.Field EXTENDED_YEAR
= new Field("extended year", Calendar.YEAR);
public static final DateFormat.Field MODIFIED_JULIAN_DAY
= new Field("julian day", -1);
public static final DateFormat.Field MILLISECOND_IN_DAY
= new Field("millisecond in day", -1);
public static final DateFormat.Field RFC822_TIME_ZONE
= new Field("rfc822 timezone", Calendar.ZONE_OFFSET);
static final DateFormat.Field[] allFields =
{
ERA, YEAR, MONTH, DAY_OF_MONTH, HOUR_OF_DAY1,
HOUR_OF_DAY0, MINUTE, SECOND, MILLISECOND,
DAY_OF_WEEK, DAY_OF_YEAR, DAY_OF_WEEK_IN_MONTH,
WEEK_OF_YEAR, WEEK_OF_MONTH, AM_PM, HOUR1, HOUR0,
TIME_ZONE, ISO_YEAR, LOCALIZED_DAY_OF_WEEK,
EXTENDED_YEAR, MODIFIED_JULIAN_DAY, MILLISECOND_IN_DAY,
RFC822_TIME_ZONE
};
// For deserialization
private Field()
{
super("");
}
protected Field(String name, int calendarField)
{
super(name);
this.calendarField = calendarField;
}
public int getCalendarField()
{
return calendarField;
}
public static Field ofCalendarField(int calendarField)
{
if (calendarField >= allFields.length || calendarField < 0)
throw new IllegalArgumentException("no such calendar field ("
+ calendarField + ")");
return allFields[calendarField];
}
protected Object readResolve() throws InvalidObjectException
{
String s = getName();
for (int i=0;i<allFields.length;i++)
if (s.equals(allFields[i].getName()))
return allFields[i];
throw new InvalidObjectException("no such DateFormat field called " + s);
}
}
/**
* This method initializes a new instance of <code>DateFormat</code>.
*/
protected DateFormat ()
{
}
/**
* This method tests this object for equality against the specified object.
* The two objects will be considered equal if an only if the specified
* object:
* <P>
* <ul>
* <li>Is not <code>null</code>.</li>
* <li>Is an instance of <code>DateFormat</code>.</li>
* <li>Has the same numberFormat field value as this object.</li>
* </ul>
*
* @param obj The object to test for equality against.
*
* @return <code>true</code> if the specified object is equal to this object,
* <code>false</code> otherwise.
*/
public boolean equals (Object obj)
{
if (!(obj instanceof DateFormat))
return false;
DateFormat d = (DateFormat) obj;
return numberFormat.equals(d.numberFormat);
}
/**
* This method returns a copy of this object.
*
* @return A copy of this object.
*/
public Object clone ()
{
// We know the superclass just call's Object's generic cloner.
return super.clone ();
}
/**
* This method formats the specified <code>Object</code> into a date string
* and appends it to the specified <code>StringBuffer</code>.
* The specified object must be an instance of <code>Number</code> or
* <code>Date</code> or an <code>IllegalArgumentException</code> will be
* thrown.
*
* @param obj The <code>Object</code> to format.
* @param toAppendTo The <code>StringBuffer</code> to append the resultant
* <code>String</code> to.
* @param fieldPosition Is updated to the start and end index of the
* specified field.
*
* @return The <code>StringBuffer</code> supplied on input, with the
* formatted date/time appended.
*/
public final StringBuffer format (Object obj,
StringBuffer buf, FieldPosition pos)
{
if (obj instanceof Number)
obj = new Date(((Number) obj).longValue());
else if (! (obj instanceof Date))
throw new IllegalArgumentException
("Cannot format given Object as a Date");
return format ((Date) obj, buf, pos);
}
/**
* Formats the date argument according to the pattern specified.
*
* @param date The formatted date.
*/
public final String format (Date date)
{
StringBuffer sb = new StringBuffer ();
format (date, sb, new FieldPosition (MONTH_FIELD));
return sb.toString();
}
/**
* This method formats a <code>Date</code> into a string and appends it
* to the specified <code>StringBuffer</code>.
*
* @param date The <code>Date</code> value to format.
* @param toAppendTo The <code>StringBuffer</code> to append the resultant
* <code>String</code> to.
* @param fieldPosition Is updated to the start and end index of the
* specified field.
*
* @return The <code>StringBuffer</code> supplied on input, with the
* formatted date/time appended.
*/
public abstract StringBuffer format (Date date,
StringBuffer buf, FieldPosition pos);
/**
* This method returns a list of available locales supported by this
* class.
*/
public static Locale[] getAvailableLocales()
{
return Locale.getAvailableLocales();
}
/**
* This method returns the <code>Calendar</code> object being used by
* this object to parse/format datetimes.
*
* @return The <code>Calendar</code> being used by this object.
*
* @see java.util.Calendar
*/
public Calendar getCalendar ()
{
return calendar;
}
private static DateFormat computeInstance (int style, Locale loc,
boolean use_date, boolean use_time)
{
return computeInstance (style, style, loc, use_date, use_time);
}
private static DateFormat computeInstance (int dateStyle, int timeStyle,
Locale loc, boolean use_date,
boolean use_time)
{
ResourceBundle res;
try
{
res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
loc, ClassLoader.getSystemClassLoader());
}
catch (MissingResourceException x)
{
res = null;
}
String pattern = null;
if (use_date)
{
String name, def;
switch (dateStyle)
{
case FULL:
name = "fullDateFormat";
def = "EEEE MMMM d, yyyy G";
break;
case LONG:
name = "longDateFormat";
def = "MMMM d, yyyy";
break;
case MEDIUM:
name = "mediumDateFormat";
def = "d-MMM-yy";
break;
case SHORT:
name = "shortDateFormat";
def = "M/d/yy";
break;
default:
throw new IllegalArgumentException ();
}
try
{
pattern = res == null ? def : res.getString(name);
}
catch (MissingResourceException x)
{
pattern = def;
}
}
if (use_time)
{
if (pattern == null)
pattern = "";
else
pattern += " ";
String name, def;
switch (timeStyle)
{
case FULL:
name = "fullTimeFormat";
def = "h:mm:ss;S 'o''clock' a z";
break;
case LONG:
name = "longTimeFormat";
def = "h:mm:ss a z";
break;
case MEDIUM:
name = "mediumTimeFormat";
def = "h:mm:ss a";
break;
case SHORT:
name = "shortTimeFormat";
def = "h:mm a";
break;
default:
throw new IllegalArgumentException ();
}
String s;
try
{
s = res == null ? def : res.getString(name);
}
catch (MissingResourceException x)
{
s = def;
}
pattern += s;
}
return new SimpleDateFormat (pattern, loc);
}
/**
* This method returns an instance of <code>DateFormat</code> that will
* format using the default formatting style for dates.
*
* @return A new <code>DateFormat</code> instance.
*/
public static final DateFormat getDateInstance ()
{
return getDateInstance (DEFAULT, Locale.getDefault());
}
/**
* This method returns an instance of <code>DateFormat</code> that will
* format using the specified formatting style for dates.
*
* @param style The type of formatting to perform.
*
* @return A new <code>DateFormat</code> instance.
*/
public static final DateFormat getDateInstance (int style)
{
return getDateInstance (style, Locale.getDefault());
}
/**
* This method returns an instance of <code>DateFormat</code> that will
* format using the specified formatting style for dates. The specified
* localed will be used in place of the default.
*
* @param style The type of formatting to perform.
* @param aLocale The desired locale.
*
* @return A new <code>DateFormat</code> instance.
*/
public static final DateFormat getDateInstance (int style, Locale loc)
{
return computeInstance (style, loc, true, false);
}
/**
* This method returns a new instance of <code>DateFormat</code> that
* formats both dates and times using the <code>SHORT</code> style.
*
* @return A new <code>DateFormat</code>instance.
*/
public static final DateFormat getDateTimeInstance ()
{
return getDateTimeInstance (DEFAULT, DEFAULT, Locale.getDefault());
}
/**
* This method returns a new instance of <code>DateFormat</code> that
* formats both dates and times using the <code>DEFAULT</code> style.
*
* @return A new <code>DateFormat</code>instance.
*/
public static final DateFormat getDateTimeInstance (int dateStyle,
int timeStyle)
{
return getDateTimeInstance (dateStyle, timeStyle, Locale.getDefault());
}
/**
* This method returns a new instance of <code>DateFormat</code> that
* formats both dates and times using the specified styles.
*
* @param dateStyle The desired style for date formatting.
* @param timeStyle The desired style for time formatting
*
* @return A new <code>DateFormat</code>instance.
*/
public static final DateFormat getDateTimeInstance (int dateStyle,
int timeStyle,
Locale loc)
{
return computeInstance (dateStyle, timeStyle, loc, true, true);
}
/**
* This method returns a new instance of <code>DateFormat</code> that
* formats both dates and times using the <code>SHORT</code> style.
*
* @return A new <code>DateFormat</code>instance.
*/
public static final DateFormat getInstance ()
{
// JCL book says SHORT.
return getDateTimeInstance (SHORT, SHORT, Locale.getDefault());
}
/**
* This method returns the <code>NumberFormat</code> object being used
* by this object to parse/format time values.
*
* @return The <code>NumberFormat</code> in use by this object.
*/
public NumberFormat getNumberFormat ()
{
return numberFormat;
}
/**
* This method returns an instance of <code>DateFormat</code> that will
* format using the default formatting style for times.
*
* @return A new <code>DateFormat</code> instance.
*/
public static final DateFormat getTimeInstance ()
{
return getTimeInstance (DEFAULT, Locale.getDefault());
}
/**
* This method returns an instance of <code>DateFormat</code> that will
* format using the specified formatting style for times.
*
* @param style The type of formatting to perform.
*
* @return A new <code>DateFormat</code> instance.
*/
public static final DateFormat getTimeInstance (int style)
{
return getTimeInstance (style, Locale.getDefault());
}
/**
* This method returns an instance of <code>DateFormat</code> that will
* format using the specified formatting style for times. The specified
* localed will be used in place of the default.
*
* @param style The type of formatting to perform.
* @param aLocale The desired locale.
*
* @return A new <code>DateFormat</code> instance.
*/
public static final DateFormat getTimeInstance (int style, Locale loc)
{
return computeInstance (style, loc, false, true);
}
/**
* This method returns the <code>TimeZone</code> object being used by
* this instance.
*
* @return The time zone in use.
*/
public TimeZone getTimeZone ()
{
return calendar.getTimeZone();
}
/**
* This method returns a hash value for this object.
*
* @return A hash value for this object.
*/
public int hashCode ()
{
if (numberFormat != null)
return numberFormat.hashCode();
else
return 0;
}
/**
* This method indicates whether or not the parsing of date and time
* values should be done in a lenient value.
*
* @return <code>true</code> if date/time parsing is lenient,
* <code>false</code> otherwise.
*/
public boolean isLenient ()
{
return calendar.isLenient();
}
/**
* This method parses the specified date/time string.
*
* @param source The string to parse.
* @return The resultant date.
*
* @exception ParseException If the specified string cannot be parsed.
*/
public Date parse (String source) throws ParseException
{
ParsePosition pos = new ParsePosition(0);
Date result = parse (source, pos);
if (result == null)
{
int index = pos.getErrorIndex();
if (index < 0)
index = pos.getIndex();
throw new ParseException("invalid Date syntax in \""
+ source + '\"', index);
}
return result;
}
/**
* This method parses the specified <code>String</code> into a
* <code>Date</code>. The <code>pos</code> argument contains the
* starting parse position on method entry and the ending parse
* position on method exit.
*
* @param text The string to parse.
* @param pos The starting parse position in entry, the ending parse
* position on exit.
*
* @return The parsed date, or <code>null</code> if the string cannot
* be parsed.
*/
public abstract Date parse (String source, ParsePosition pos);
/**
* This method is identical to <code>parse(String, ParsePosition)</code>,
* but returns its result as an <code>Object</code> instead of a
* <code>Date</code>.
*
* @param source The string to parse.
* @param pos The starting parse position in entry, the ending parse
* position on exit.
*
* @return The parsed date, or <code>null</code> if the string cannot
* be parsed.
*/
public Object parseObject (String source, ParsePosition pos)
{
return parse(source, pos);
}
/**
* This method specified the <code>Calendar</code> that should be used
* by this object to parse/format datetimes.
*
* @param The new <code>Calendar</code> for this object.
*
* @see java.util.Calendar
*/
public void setCalendar (Calendar calendar)
{
this.calendar = calendar;
}
/**
* This method specifies whether or not this object should be lenient in
* the syntax it accepts while parsing date/time values.
*
* @param lenient <code>true</code> if parsing should be lenient,
* <code>false</code> otherwise.
*/
public void setLenient (boolean lenient)
{
calendar.setLenient(lenient);
}
/**
* This method specifies the <code>NumberFormat</code> object that should
* be used by this object to parse/format times.
*
* @param The <code>NumberFormat</code> in use by this object.
*/
public void setNumberFormat (NumberFormat numberFormat)
{
this.numberFormat = numberFormat;
}
/**
* This method sets the time zone that should be used by this object.
*
* @param The new time zone.
*/
public void setTimeZone (TimeZone timeZone)
{
calendar.setTimeZone(timeZone);
}
}
@@ -0,0 +1,525 @@
/* DateFormatSymbols.java -- Format over a range of numbers
Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
/**
* This class acts as container for locale specific date/time formatting
* information such as the days of the week and the months of the year.
* @author Per Bothner (bothner@cygnus.com)
* @date October 24, 1998.
*/
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3.
* Status: Believed complete and correct.
*/
public class DateFormatSymbols implements java.io.Serializable, Cloneable
{
String[] ampms;
String[] eras;
private String localPatternChars;
String[] months;
String[] shortMonths;
String[] shortWeekdays;
String[] weekdays;
private String[][] zoneStrings;
private static final long serialVersionUID = -5987973545549424702L;
// The order of these prefixes must be the same as in DateFormat
private static final String[] formatPrefixes =
{
"full", "long", "medium", "short"
};
// These are each arrays with a value for SHORT, MEDIUM, LONG, FULL,
// and DEFAULT (constants defined in java.text.DateFormat). While
// not part of the official spec, we need a way to get at locale-specific
// default formatting patterns. They are declared package scope so
// as to be easily accessible where needed (DateFormat, SimpleDateFormat).
transient String[] dateFormats;
transient String[] timeFormats;
private static String[] getStringArray(ResourceBundle res, String name)
{
return res.getString(name).split("\u00ae");
}
private String[][] getZoneStrings(ResourceBundle res)
{
try
{
int index = 0;
String data = res.getString("zoneStrings");
String[] zones = data.split("\u00a9");
String[][] array = new String[zones.length][];
for (int a = 0; a < zones.length; ++a)
array[a] = zones[a].split("\u00ae");
return array;
}
catch (MissingResourceException e)
{
return new String[0][];
}
}
private String[] formatsForKey(ResourceBundle res, String key)
{
String[] values = new String[formatPrefixes.length];
for (int i = 0; i < formatPrefixes.length; i++)
values[i] = res.getString(formatPrefixes[i] + key);
return values;
}
/**
* This method initializes a new instance of <code>DateFormatSymbols</code>
* by loading the date format information for the specified locale.
*
* @param locale The locale for which date formatting symbols should
* be loaded.
*/
public DateFormatSymbols (Locale locale) throws MissingResourceException
{
ResourceBundle res
= ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", locale,
ClassLoader.getSystemClassLoader());
ampms = getStringArray(res, "ampms");
eras = getStringArray(res, "eras");
localPatternChars = res.getString("localPatternChars");
months = getStringArray(res, "months");
shortMonths = getStringArray(res, "shortMonths");
shortWeekdays = getStringArray(res, "shortWeekdays");
weekdays = getStringArray(res, "weekdays");
zoneStrings = getZoneStrings(res);
dateFormats = formatsForKey(res, "DateFormat");
timeFormats = formatsForKey(res, "TimeFormat");
}
/**
* This method loads the format symbol information for the default
* locale.
*/
public DateFormatSymbols () throws MissingResourceException
{
this (Locale.getDefault());
}
/**
* This method returns the list of strings used for displaying AM or PM.
* This is a two element <code>String</code> array indexed by
* <code>Calendar.AM</code> and <code>Calendar.PM</code>
*
* @return The list of AM/PM display strings.
*/
public String[] getAmPmStrings()
{
return ampms;
}
/**
* This method returns the list of strings used for displaying eras
* (e.g., "BC" and "AD"). This is a two element <code>String</code>
* array indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
*
* @return The list of era disply strings.
*/
public String[] getEras()
{
return eras;
}
/**
* This method returns the pattern character information for this
* object. This is an 18 character string that contains the characters
* that are used in creating the date formatting strings in
* <code>SimpleDateFormat</code>. The following are the character
* positions in the string and which format character they correspond
* to (the character in parentheses is the default value in the US English
* locale):
* <p>
* <ul>
* <li>0 - era (G)</li>
* <li>1 - year (y)</li>
* <li>2 - month (M)</li>
* <li>3 - day of month (d)</li>
* <li>4 - hour out of 12, from 1-12 (h)</li>
* <li>5 - hour out of 24, from 0-23 (H)</li>
* <li>6 - minute (m)</li>
* <li>7 - second (s)</li>
* <li>8 - millisecond (S)</li>
* <li>9 - date of week (E)</li>
* <li>10 - date of year (D)</li>
* <li>11 - day of week in month, eg. "4th Thur in Nov" (F)</li>
* <li>12 - week in year (w)</li>
* <li>13 - week in month (W)</li>
* <li>14 - am/pm (a)</li>
* <li>15 - hour out of 24, from 1-24 (k)</li>
* <li>16 - hour out of 12, from 0-11 (K)</li>
* <li>17 - time zone (z)</li>
* </ul>
*
* @return The format patter characters
*/
public String getLocalPatternChars()
{
return localPatternChars;
}
/**
* This method returns the list of strings used for displaying month
* names (e.g., "January" and "February"). This is a thirteen element
* string array indexed by <code>Calendar.JANUARY</code> through
* <code>Calendar.UNDECEMBER</code>. Note that there are thirteen
* elements because some calendars have thriteen months.
*
* @return The list of month display strings.
*/
public String[] getMonths ()
{
return months;
}
/**
* This method returns the list of strings used for displaying abbreviated
* month names (e.g., "Jan" and "Feb"). This is a thirteen element
* <code>String</code> array indexed by <code>Calendar.JANUARY</code>
* through <code>Calendar.UNDECEMBER</code>. Note that there are thirteen
* elements because some calendars have thirteen months.
*
* @return The list of abbreviated month display strings.
*/
public String[] getShortMonths ()
{
return shortMonths;
}
/**
* This method returns the list of strings used for displaying abbreviated
* weekday names (e.g., "Sun" and "Mon"). This is an eight element
* <code>String</code> array indexed by <code>Calendar.SUNDAY</code>
* through <code>Calendar.SATURDAY</code>. Note that the first element
* of this array is ignored.
*
* @return This list of abbreviated weekday display strings.
*/
public String[] getShortWeekdays ()
{
return shortWeekdays;
}
/**
* This method returns the list of strings used for displaying weekday
* names (e.g., "Sunday" and "Monday"). This is an eight element
* <code>String</code> array indexed by <code>Calendar.SUNDAY</code>
* through <code>Calendar.SATURDAY</code>. Note that the first element
* of this array is ignored.
*
* @return This list of weekday display strings.
*/
public String[] getWeekdays ()
{
return weekdays;
}
/**
* This method returns this list of localized timezone display strings.
* This is a two dimensional <code>String</code> array where each row in
* the array contains five values:
* <P>
* <ul>
* <li>0 - The non-localized time zone id string.</li>
* <li>1 - The long name of the time zone (standard time).</li>
* <li>2 - The short name of the time zone (standard time).</li>
* <li>3 - The long name of the time zone (daylight savings time).</li>
* <li>4 - the short name of the time zone (daylight savings time).</li>
* </ul>
*
* @return The list of time zone display strings.
*/
public String[] [] getZoneStrings ()
{
return zoneStrings;
}
/**
* This method sets the list of strings used to display AM/PM values to
* the specified list.
* This is a two element <code>String</code> array indexed by
* <code>Calendar.AM</code> and <code>Calendar.PM</code>
*
* @param ampms The new list of AM/PM display strings.
*/
public void setAmPmStrings (String[] value)
{
ampms = value;
}
/**
* This method sets the list of strings used to display time eras to
* to the specified list.
* This is a two element <code>String</code>
* array indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
*
* @param eras The new list of era disply strings.
*/
public void setEras (String[] value)
{
eras = value;
}
/**
* This method sets the list of characters used to specific date/time
* formatting strings.
* This is an 18 character string that contains the characters
* that are used in creating the date formatting strings in
* <code>SimpleDateFormat</code>. The following are the character
* positions in the string and which format character they correspond
* to (the character in parentheses is the default value in the US English
* locale):
* <p>
* <ul>
* <li>0 - era (G)</li>
* <li>1 - year (y)</li>
* <li>2 - month (M)</li>
* <li>3 - day of month (d)</li>
* <li>4 - hour out of 12, from 1-12 (h)</li>
* <li>5 - hour out of 24, from 0-23 (H)</li>
* <li>6 - minute (m)</li>
* <li>7 - second (s)</li>
* <li>8 - millisecond (S)</li>
* <li>9 - date of week (E)</li>
* <li>10 - date of year (D)</li>
* <li>11 - day of week in month, eg. "4th Thur in Nov" (F)</li>
* <li>12 - week in year (w)</li>
* <li>13 - week in month (W)</li>
* <li>14 - am/pm (a)</li>
* <li>15 - hour out of 24, from 1-24 (k)</li>
* <li>16 - hour out of 12, from 0-11 (K)</li>
* <li>17 - time zone (z)</li>
* </ul>
*
* @param localPatternChars The new format patter characters
*/
public void setLocalPatternChars (String value)
{
localPatternChars = value;
}
/**
* This method sets the list of strings used to display month names.
* This is a thirteen element
* string array indexed by <code>Calendar.JANUARY</code> through
* <code>Calendar.UNDECEMBER</code>. Note that there are thirteen
* elements because some calendars have thriteen months.
*
* @param months The list of month display strings.
*/
public void setMonths (String[] value)
{
months = value;
}
/**
* This method sets the list of strings used to display abbreviated month
* names.
* This is a thirteen element
* <code>String</code> array indexed by <code>Calendar.JANUARY</code>
* through <code>Calendar.UNDECEMBER</code>. Note that there are thirteen
* elements because some calendars have thirteen months.
*
* @param shortMonths The new list of abbreviated month display strings.
*/
public void setShortMonths (String[] value)
{
shortMonths = value;
}
/**
* This method sets the list of strings used to display abbreviated
* weekday names.
* This is an eight element
* <code>String</code> array indexed by <code>Calendar.SUNDAY</code>
* through <code>Calendar.SATURDAY</code>. Note that the first element
* of this array is ignored.
*
* @param shortWeekdays This list of abbreviated weekday display strings.
*/
public void setShortWeekdays (String[] value)
{
shortWeekdays = value;
}
/**
* This method sets the list of strings used to display weekday names.
* This is an eight element
* <code>String</code> array indexed by <code>Calendar.SUNDAY</code>
* through <code>Calendar.SATURDAY</code>. Note that the first element
* of this array is ignored.
*
* @param weekdays This list of weekday display strings.
*/
public void setWeekdays (String[] value)
{
weekdays = value;
}
/**
* This method sets the list of display strings for time zones.
* This is a two dimensional <code>String</code> array where each row in
* the array contains five values:
* <P>
* <ul>
* <li>0 - The non-localized time zone id string.</li>
* <li>1 - The long name of the time zone (standard time).</li>
* <li>2 - The short name of the time zone (standard time).</li>
* <li>3 - The long name of the time zone (daylight savings time).</li>
* <li>4 - the short name of the time zone (daylight savings time).</li>
* </ul>
*
* @return The list of time zone display strings.
*/
public void setZoneStrings (String[][] value)
{
zoneStrings = value;
}
/* Does a "deep" equality test - recurses into arrays. */
private static boolean equals (Object x, Object y)
{
if (x == y)
return true;
if (x == null || y == null)
return false;
if (! (x instanceof Object[]) || ! (y instanceof Object[]))
return x.equals(y);
Object[] xa = (Object[]) x;
Object[] ya = (Object[]) y;
if (xa.length != ya.length)
return false;
for (int i = xa.length; --i >= 0; )
{
if (! equals(xa[i], ya[i]))
return false;
}
return true;
}
private static int hashCode (Object x)
{
if (x == null)
return 0;
if (! (x instanceof Object[]))
return x.hashCode();
Object[] xa = (Object[]) x;
int hash = 0;
for (int i = 0; i < xa.length; i++)
hash = 37 * hashCode(xa[i]);
return hash;
}
/**
* This method tests a specified object for equality against this object.
* This will be true if and only if the specified object:
* <p>
* <ul>
* <li> Is not <code>null</code>.</li>
* <li> Is an instance of <code>DateFormatSymbols</code>.</li>
* <li> Contains identical formatting symbols to this object.</li>
* </ul>
*
* @param obj The <code>Object</code> to test for equality against.
*
* @return <code>true</code> if the specified object is equal to this one,
* <code>false</code> otherwise.
*/
public boolean equals (Object obj)
{
if (! (obj instanceof DateFormatSymbols))
return false;
DateFormatSymbols other = (DateFormatSymbols) obj;
return (equals(ampms, other.ampms)
&& equals(eras, other.eras)
&& equals(localPatternChars, other.localPatternChars)
&& equals(months, other.months)
&& equals(shortMonths, other.shortMonths)
&& equals(shortWeekdays, other.shortWeekdays)
&& equals(weekdays, other.weekdays)
&& equals(zoneStrings, other.zoneStrings));
}
/**
* Returns a new copy of this object.
*
* @param A copy of this object
*/
public Object clone ()
{
try
{
return super.clone ();
}
catch (CloneNotSupportedException e)
{
return null;
}
}
/**
* This method returns a hash value for this object.
*
* @return A hash value for this object.
*/
public int hashCode ()
{
return (hashCode(ampms)
^ hashCode(eras)
^ hashCode(localPatternChars)
^ hashCode(months)
^ hashCode(shortMonths)
^ hashCode(shortWeekdays)
^ hashCode(weekdays)
^ hashCode(zoneStrings));
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,688 @@
/* DecimalFormatSymbols.java -- Format symbols used by DecimalFormat
Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Currency;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* This class is a container for the symbols used by
* <code>DecimalFormat</code> to format numbers and currency
* for a particular locale. These are
* normally handled automatically, but an application can override
* values as desired using this class.
*
* @author Tom Tromey (tromey@cygnus.com)
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @date February 24, 1999
* @see java.text.DecimalFormat
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 from http://www.javasoft.com.
* Status: Believed complete and correct to 1.2.
*/
public final class DecimalFormatSymbols implements Cloneable, Serializable
{
public Object clone ()
{
try
{
return super.clone ();
}
catch(CloneNotSupportedException e)
{
return null;
}
}
/**
* This method initializes a new instance of
* <code>DecimalFormatSymbols</code> for the default locale.
*/
public DecimalFormatSymbols ()
{
this (Locale.getDefault());
}
/**
* Retrieves a valid string, either using the supplied resource
* bundle or the default value.
*
* @param bundle the resource bundle to use to find the string.
* @param name key for the string in the resource bundle.
* @param def default value for the string.
*/
private String safeGetString(ResourceBundle bundle,
String name, String def)
{
if (bundle != null)
{
try
{
return bundle.getString(name);
}
catch (MissingResourceException x)
{
}
}
return def;
}
private char safeGetChar(ResourceBundle bundle,
String name, char def)
{
String r = null;
if (bundle != null)
{
try
{
r = bundle.getString(name);
}
catch (MissingResourceException x)
{
}
}
if (r == null || r.length() < 1)
return def;
return r.charAt(0);
}
/**
* This method initializes a new instance of
* <code>DecimalFormatSymbols</code> for the specified locale.
* <strong>Note</strong>: if the locale does not have an associated
* <code>Currency</code> instance, the currency symbol and
* international currency symbol will be set to the strings "?"
* and "XXX" respectively. This generally happens with language
* locales (those with no specified country), such as
* <code>Locale.ENGLISH</code>.
*
* @param locale The local to load symbols for.
* @throws NullPointerException if the locale is null.
*/
public DecimalFormatSymbols (Locale loc)
{
ResourceBundle res;
currency = Currency.getInstance("XXX");
currencySymbol = "?";
intlCurrencySymbol = "XXX";
try
{
res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
loc, ClassLoader.getSystemClassLoader());
}
catch (MissingResourceException x)
{
res = null;
}
try
{
Currency localeCurrency = Currency.getInstance(loc);
if (localeCurrency != null)
{
setCurrency(localeCurrency);
}
}
catch(IllegalArgumentException exception)
{
/* Locale has an invalid currency */
}
decimalSeparator = safeGetChar (res, "decimalSeparator", '.');
digit = safeGetChar (res, "digit", '#');
exponential = safeGetChar (res, "exponential", 'E');
groupingSeparator = safeGetChar (res, "groupingSeparator", ',');
infinity = safeGetString (res, "infinity", "\u221e");
try
{
monetarySeparator = safeGetChar (res, "monetarySeparator", '.');
}
catch (MissingResourceException x)
{
monetarySeparator = decimalSeparator;
}
minusSign = safeGetChar (res, "minusSign", '-');
NaN = safeGetString (res, "NaN", "\ufffd");
patternSeparator = safeGetChar (res, "patternSeparator", ';');
percent = safeGetChar (res, "percent", '%');
perMill = safeGetChar (res, "perMill", '\u2030');
zeroDigit = safeGetChar (res, "zeroDigit", '0');
locale = loc;
}
/**
* This method this this object for equality against the specified object.
* This will be true if and only if the following criteria are met with
* regard to the specified object:
* <p>
* <ul>
* <li>It is not <code>null</code>.</li>
* <li>It is an instance of <code>DecimalFormatSymbols</code>.</li>
* <li>All of its symbols are identical to the symbols in this object.</li>
* </ul>
*
* @return <code>true</code> if the specified object is equal to this
* object, <code>false</code> otherwise.
*/
public boolean equals (Object obj)
{
if (! (obj instanceof DecimalFormatSymbols))
return false;
DecimalFormatSymbols dfs = (DecimalFormatSymbols) obj;
return (currencySymbol.equals(dfs.currencySymbol)
&& decimalSeparator == dfs.decimalSeparator
&& digit == dfs.digit
&& exponential == dfs.exponential
&& groupingSeparator == dfs.groupingSeparator
&& infinity.equals(dfs.infinity)
&& intlCurrencySymbol.equals(dfs.intlCurrencySymbol)
&& minusSign == dfs.minusSign
&& monetarySeparator == dfs.monetarySeparator
&& NaN.equals(dfs.NaN)
&& patternSeparator == dfs.patternSeparator
&& percent == dfs.percent
&& perMill == dfs.perMill
&& zeroDigit == dfs.zeroDigit);
}
/**
* Returns the currency corresponding to the currency symbol stored
* in this instance of <code>DecimalFormatSymbols</code>.
*
* @return An instance of <code>Currency</code> which matches
* the currency used, or null if there is no corresponding
* instance.
*/
public Currency getCurrency ()
{
return currency;
}
/**
* This method returns the currency symbol in local format. For example,
* "$" for Canadian dollars.
*
* @return The currency symbol in local format.
*/
public String getCurrencySymbol ()
{
return currencySymbol;
}
/**
* This method returns the character used as the decimal point.
*
* @return The character used as the decimal point.
*/
public char getDecimalSeparator ()
{
return decimalSeparator;
}
/**
* This method returns the character used to represent a digit in a
* format pattern string.
*
* @return The character used to represent a digit in a format
* pattern string.
*/
public char getDigit ()
{
return digit;
}
/**
* This method returns the character used to represent the exponential
* format. This is a GNU Classpath extension.
*
* @return the character used to represent an exponential in a format
* pattern string.
*/
char getExponential ()
{
return exponential;
}
/**
* This method sets the character used to separate groups of digits. For
* example, the United States uses a comma (,) to separate thousands in
* a number.
*
* @return The character used to separate groups of digits.
*/
public char getGroupingSeparator ()
{
return groupingSeparator;
}
/**
* This method returns the character used to represent infinity.
*
* @return The character used to represent infinity.
*/
public String getInfinity ()
{
return infinity;
}
/**
* This method returns the ISO 4217 currency code for
* the currency used.
*
* @return the ISO 4217 currency code.
*/
public String getInternationalCurrencySymbol ()
{
return intlCurrencySymbol;
}
/**
* This method returns the character used to represent the minus sign.
*
* @return The character used to represent the minus sign.
*/
public char getMinusSign ()
{
return minusSign;
}
/**
* This method returns the character used to represent the decimal
* point for currency values.
*
* @return The decimal point character used in currency values.
*/
public char getMonetaryDecimalSeparator ()
{
return monetarySeparator;
}
/**
* This method returns the string used to represent the NaN (not a number)
* value.
*
* @return The string used to represent NaN
*/
public String getNaN ()
{
return NaN;
}
/**
* This method returns the character used to separate positive and negative
* subpatterns in a format pattern.
*
* @return The character used to separate positive and negative subpatterns
* in a format pattern.
*/
public char getPatternSeparator ()
{
return patternSeparator;
}
/**
* This method returns the character used as the percent sign.
*
* @return The character used as the percent sign.
*/
public char getPercent ()
{
return percent;
}
/**
* This method returns the character used as the per mille character.
*
* @return The per mille character.
*/
public char getPerMill ()
{
return perMill;
}
/**
* This method returns the character used to represent the digit zero.
*
* @return The character used to represent the digit zero.
*/
public char getZeroDigit ()
{
return zeroDigit;
}
/**
* This method returns a hash value for this object.
*
* @return A hash value for this object.
*/
public int hashCode ()
{
// Compute based on zero digit, grouping separator, and decimal
// separator -- JCL book. This probably isn't a very good hash
// code.
return zeroDigit << 16 + groupingSeparator << 8 + decimalSeparator;
}
/**
* This method sets the currency symbol and ISO 4217 currency
* code to the values obtained from the supplied currency.
*
* @param currency the currency from which to obtain the values.
* @throws NullPointerException if the currency is null.
*/
public void setCurrency (Currency currency)
{
intlCurrencySymbol = currency.getCurrencyCode();
currencySymbol = currency.getSymbol();
this.currency = currency;
}
/**
* This method sets the currency symbol to the specified value.
*
* @param currencySymbol The new currency symbol
*/
public void setCurrencySymbol (String currency)
{
currencySymbol = currency;
}
/**
* This method sets the decimal point character to the specified value.
*
* @param decimalSeparator The new decimal point character
*/
public void setDecimalSeparator (char decimalSep)
{
decimalSeparator = decimalSep;
}
/**
* This method sets the character used to represents a digit in a format
* string to the specified value.
*
* @param digit The character used to represent a digit in a format pattern.
*/
public void setDigit (char digit)
{
this.digit = digit;
}
/**
* This method sets the exponential character used in the format string to
* the specified value. This is a GNU Classpath extension.
*
* @param exp the character used for the exponential in a format pattern.
*/
void setExponential (char exp)
{
exponential = exp;
}
/**
* This method sets the character used to separate groups of digits.
*
* @param groupingSeparator The character used to separate groups of digits.
*/
public void setGroupingSeparator (char groupSep)
{
groupingSeparator = groupSep;
}
/**
* This method sets the string used to represents infinity.
*
* @param infinity The string used to represent infinity.
*/
public void setInfinity (String infinity)
{
this.infinity = infinity;
}
/**
* This method sets the international currency symbol to the
* specified value. If a valid <code>Currency</code> instance
* exists for the international currency code, then this is
* used for the currency attribute, and the currency symbol
* is set to the corresponding value from this instance.
* Otherwise, the currency attribute is set to null and the
* symbol is left unmodified.
*
* @param currencyCode The new international currency symbol.
*/
public void setInternationalCurrencySymbol (String currencyCode)
{
intlCurrencySymbol = currencyCode;
try
{
currency = Currency.getInstance(currencyCode);
}
catch (IllegalArgumentException exception)
{
currency = null;
}
if (currency != null)
{
setCurrencySymbol(currency.getSymbol(locale));
}
}
/**
* This method sets the character used to represent the minus sign.
*
* @param minusSign The character used to represent the minus sign.
*/
public void setMinusSign (char minusSign)
{
this.minusSign = minusSign;
}
/**
* This method sets the character used for the decimal point in currency
* values.
*
* @param monetarySeparator The decimal point character used in
* currency values.
*/
public void setMonetaryDecimalSeparator (char decimalSep)
{
monetarySeparator = decimalSep;
}
/**
* This method sets the string used to represent the NaN (not a
* number) value.
*
* @param NaN The string used to represent NaN
*/
public void setNaN (String nan)
{
NaN = nan;
}
/**
* This method sets the character used to separate positive and negative
* subpatterns in a format pattern.
*
* @param patternSeparator The character used to separate positive and
* negative subpatterns in a format pattern.
*/
public void setPatternSeparator (char patternSep)
{
patternSeparator = patternSep;
}
/**
* This method sets the character used as the percent sign.
*
* @param percent The character used as the percent sign.
*/
public void setPercent (char percent)
{
this.percent = percent;
}
/**
* This method sets the character used as the per mille character.
*
* @param perMill The per mille character.
*/
public void setPerMill (char perMill)
{
this.perMill = perMill;
}
/**
* This method sets the character used to represent the digit zero.
*
* @param zeroDigit The character used to represent the digit zero.
*/
public void setZeroDigit (char zeroDigit)
{
this.zeroDigit = zeroDigit;
}
/**
* @serial A string used for the local currency
*/
private String currencySymbol;
/**
* @serial The <code>char</code> used to separate decimals in a number.
*/
private char decimalSeparator;
/**
* @serial This is the <code>char</code> used to represent a digit in
* a format specification.
*/
private char digit;
/**
* @serial This is the <code>char</code> used to represent the exponent
* separator in exponential notation.
*/
private char exponential;
/**
* @serial This separates groups of thousands in numbers.
*/
private char groupingSeparator;
/**
* @serial This string represents infinity.
*/
private String infinity;
/**
* @serial This string represents the local currency in an international
* context, eg, "C$" for Canadian dollars.
*/
private String intlCurrencySymbol;
/**
* @serial This is the character used to represent the minus sign.
*/
private char minusSign;
/**
* @serial This character is used to separate decimals when formatting
* currency values.
*/
private char monetarySeparator;
/**
* @serial This string is used the represent the Java NaN value for
* "not a number".
*/
private String NaN;
/**
* @serial This is the character used to separate positive and negative
* subpatterns in a format pattern.
*/
private char patternSeparator;
/**
* @serial This is the percent symbols
*/
private char percent;
/**
* @serial This character is used for the mille percent sign.
*/
private char perMill;
/**
* @serial This value represents the type of object being de-serialized.
* 0 indicates a pre-Java 1.1.6 version, 1 indicates 1.1.6 or later.
* 0 indicates a pre-Java 1.1.6 version, 1 indicates 1.1.6 or later,
* 2 indicates 1.4 or later
*/
private int serialVersionOnStream = 2;
/**
* @serial This is the character used to represent 0.
*/
private char zeroDigit;
/**
* @serial The locale of these currency symbols.
*/
private Locale locale;
/**
* The currency used for the symbols in this instance.
* This is stored temporarily for efficiency reasons,
* as well as to ensure that the correct instance
* is restored from the currency code.
*
* @serial Ignored.
*/
private transient Currency currency;
private static final long serialVersionUID = 5772796243397350300L;
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
if (serialVersionOnStream < 1)
{
monetarySeparator = decimalSeparator;
exponential = 'E';
}
if (serialVersionOnStream < 2)
locale = Locale.getDefault();
serialVersionOnStream = 2;
}
}
@@ -0,0 +1,232 @@
/* FieldPosition.java -- Keeps track of field positions while formatting
Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
/**
* This class is used by the java.text formatting classes to track
* field positions. A field position is defined by an identifier value
* and begin and end index positions. The formatting classes in java.text
* typically define constant values for the field identifiers.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Per Bothner (bothner@cygnus.com)
*/
public class FieldPosition
{
/**
* This is the field identifier value.
*/
private int field_id;
/**
* This is the beginning index of the field.
*/
private int begin;
/**
* This is the ending index of the field.
*/
private int end;
/**
* This is the field attribute value.
*/
private Format.Field field_attribute;
/**
* This method initializes a new instance of <code>FieldPosition</code>
* to have the specified field attribute. The attribute will be used as
* an id. It is formally equivalent to calling FieldPosition(field, -1).
*
* @param field The field format attribute.
*/
public FieldPosition (Format.Field field)
{
this(field, -1);
}
/**
* This method initializes a new instance of <code>FieldPosition</code>
* to have the specified field attribute. The attribute will be used as
* an id is non null. The integer field id is only used if the Format.Field
* attribute is not used by the formatter.
*
* @param field The field format attribute.
* @param field_id The field identifier value.
*/
public FieldPosition (Format.Field field, int field_id)
{
this.field_attribute = field;
this.field_id = field_id;
}
/**
* This method initializes a new instance of <code>FieldPosition</code> to
* have the specified field id.
*
* @param field_id The field identifier value.
*/
public FieldPosition (int field_id)
{
this.field_id = field_id;
}
/**
* This method returns the field identifier value for this object.
*
* @return The field identifier.
*/
public int getField ()
{
return field_id;
}
public Format.Field getFieldAttribute ()
{
return field_attribute;
}
/**
* This method returns the beginning index for this field.
*
* @return The beginning index.
*/
public int getBeginIndex ()
{
return begin;
}
/**
* This method sets the beginning index of this field to the specified value.
*
* @param begin The new beginning index.
*/
public void setBeginIndex (int begin)
{
this.begin = begin;
}
/**
* This method returns the ending index for the field.
*
* @return The ending index.
*/
public int getEndIndex ()
{
return end;
}
/**
* This method sets the ending index of this field to the specified value.
*
* @param end The new ending index.
*/
public void setEndIndex (int end)
{
this.end = end;
}
/**
* This method tests this object for equality against the specified object.
* The objects will be considered equal if and only if:
* <p>
* <ul>
* <li>The specified object is not <code>null</code>.
* <li>The specified object has the same class as this object.
* <li>The specified object has the same field identifier, field attribute
* and beginning and ending index as this object.
* </ul>
*
* @param obj The object to test for equality to this object.
*
* @return <code>true</code> if the specified object is equal to
* this object, <code>false</code> otherwise.
*/
public boolean equals (Object obj)
{
if (this == obj)
return true;
if (obj == null || obj.getClass() != this.getClass())
return false;
FieldPosition fp = (FieldPosition) obj;
return (field_id == fp.field_id
&& (field_attribute == fp.field_attribute
|| (field_attribute != null
&& field_attribute.equals(fp.field_attribute)))
&& begin == fp.begin
&& end == fp.end);
}
/**
* This method returns a hash value for this object
*
* @return A hash value for this object.
*/
public int hashCode ()
{
int hash = 5;
hash = 31 * hash + field_id;
hash = 31 * hash + begin;
hash = 31 * hash + end;
hash = 31 * hash +
(null == field_attribute ? 0 : field_attribute.hashCode());
return hash;
}
/**
* This method returns a <code>String</code> representation of this
* object.
*
* @return A <code>String</code> representation of this object.
*/
public String toString ()
{
return (getClass ().getName ()
+ "[field=" + getField ()
+ ",attribute=" + getFieldAttribute ()
+ ",beginIndex=" + getBeginIndex ()
+ ",endIndex=" + getEndIndex ()
+ "]");
}
}
+181
View File
@@ -0,0 +1,181 @@
/* Format.java -- Abstract superclass for formatting/parsing strings.
Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import gnu.java.text.FormatCharacterIterator;
import java.io.Serializable;
/**
* This class is the abstract superclass of classes that format and parse
* data to/from <code>Strings</code>. It is guaranteed that any
* <code>String</code> produced by a concrete subclass of <code>Format</code>
* will be parseable by that same subclass.
* <p>
* In addition to implementing the abstract methods in this class, subclasses
* should provide static factory methods of the form
* <code>getInstance()</code> and <code>getInstance(Locale)</code> if the
* subclass loads different formatting/parsing schemes based on locale.
* These subclasses should also implement a static method called
* <code>getAvailableLocales()</code> which returns an array of
* available locales in the current runtime environment.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Per Bothner (bothner@cygnus.com)
*/
public abstract class Format implements Serializable, Cloneable
{
/**
* For compatability with Sun's JDK 1.4.2 rev. 5
*/
static final long serialVersionUID = -299282585814624189L;
public static class Field extends AttributedCharacterIterator.Attribute
{
static final long serialVersionUID = 276966692217360283L;
protected Field(String name)
{
super(name);
}
}
/**
* This method initializes a new instance of <code>Format</code>.
* It performs no actions, but acts as a default constructor for
* subclasses.
*/
public Format ()
{
}
/**
* This method formats an <code>Object</code> into a <code>String</code>.
*
* @param obj The <code>Object</code> to format.
*
* @return The formatted <code>String</code>.
*
* @exception IllegalArgumentException If the <code>Object</code>
* cannot be formatted.
*/
public final String format(Object obj) throws IllegalArgumentException
{
StringBuffer sb = new StringBuffer ();
format (obj, sb, new FieldPosition (0));
return sb.toString ();
}
/**
* This method formats an <code>Object</code> into a <code>String</code> and
* appends the <code>String</code> to a <code>StringBuffer</code>.
*
* @param obj The <code>Object</code> to format.
* @param sb The <code>StringBuffer</code> to append to.
* @param pos The desired <code>FieldPosition</code>, which is also
* updated by this call.
*
* @return The updated <code>StringBuffer</code>.
*
* @exception IllegalArgumentException If the <code>Object</code>
* cannot be formatted.
*/
public abstract StringBuffer format (Object obj, StringBuffer sb,
FieldPosition pos)
throws IllegalArgumentException;
/**
* This method parses a <code>String</code> and converts the parsed
* contents into an <code>Object</code>.
*
* @param str The <code>String</code> to parse.
*
* @return The resulting <code>Object</code>.
*
* @exception ParseException If the <code>String</code> cannot be parsed.
*/
public Object parseObject (String str) throws ParseException
{
ParsePosition pos = new ParsePosition(0);
Object result = parseObject (str, pos);
if (result == null)
{
int index = pos.getErrorIndex();
if (index < 0)
index = pos.getIndex();
throw new ParseException("parseObject failed", index);
}
return result;
}
/**
* This method parses a <code>String</code> and converts the parsed
* contents into an <code>Object</code>.
*
* @param str The <code>String</code> to parse.
* @param pos The starting parse index on input, the ending parse
* index on output.
*
* @return The parsed <code>Object</code>, or <code>null</code> in
* case of error.
*/
public abstract Object parseObject (String str, ParsePosition pos);
public AttributedCharacterIterator formatToCharacterIterator(Object obj)
{
return new FormatCharacterIterator(format(obj), null, null);
}
/**
* Creates a copy of this object.
*
* @return The copied <code>Object</code>.
*/
public Object clone ()
{
try
{
return super.clone ();
}
catch (CloneNotSupportedException e)
{
return null;
}
}
}
@@ -0,0 +1,832 @@
/* MessageFormat.java - Localized message formatting.
Copyright (C) 1999, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import gnu.java.text.FormatCharacterIterator;
import java.io.InvalidObjectException;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Vector;
public class MessageFormat extends Format
{
/**
* @author Tom Tromey (tromey@cygnus.com)
* @author Jorge Aliss (jaliss@hotmail.com)
* @date March 3, 1999
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 from http://www.javasoft.com.
* Status: Believed complete and correct to 1.2, except serialization.
* and parsing.
*/
private static final class MessageFormatElement
{
// Argument number.
int argNumber;
// Formatter to be used. This is the format set by setFormat.
Format setFormat;
// Formatter to be used based on the type.
Format format;
// Argument will be checked to make sure it is an instance of this
// class.
Class formatClass;
// Formatter type.
String type;
// Formatter style.
String style;
// Text to follow this element.
String trailer;
// Recompute the locale-based formatter.
void setLocale (Locale loc)
{
if (type == null)
;
else if (type.equals("number"))
{
formatClass = java.lang.Number.class;
if (style == null)
format = NumberFormat.getInstance(loc);
else if (style.equals("currency"))
format = NumberFormat.getCurrencyInstance(loc);
else if (style.equals("percent"))
format = NumberFormat.getPercentInstance(loc);
else if (style.equals("integer"))
{
NumberFormat nf = NumberFormat.getNumberInstance(loc);
nf.setMaximumFractionDigits(0);
nf.setGroupingUsed(false);
format = nf;
}
else
{
format = NumberFormat.getNumberInstance(loc);
DecimalFormat df = (DecimalFormat) format;
df.applyPattern(style);
}
}
else if (type.equals("time") || type.equals("date"))
{
formatClass = java.util.Date.class;
int val = DateFormat.DEFAULT;
boolean styleIsPattern = false;
if (style == null)
;
else if (style.equals("short"))
val = DateFormat.SHORT;
else if (style.equals("medium"))
val = DateFormat.MEDIUM;
else if (style.equals("long"))
val = DateFormat.LONG;
else if (style.equals("full"))
val = DateFormat.FULL;
else
styleIsPattern = true;
if (type.equals("time"))
format = DateFormat.getTimeInstance(val, loc);
else
format = DateFormat.getDateInstance(val, loc);
if (styleIsPattern)
{
SimpleDateFormat sdf = (SimpleDateFormat) format;
sdf.applyPattern(style);
}
}
else if (type.equals("choice"))
{
formatClass = java.lang.Number.class;
if (style == null)
throw new
IllegalArgumentException ("style required for choice format");
format = new ChoiceFormat (style);
}
}
}
private static final long serialVersionUID = 6479157306784022952L;
public static class Field extends Format.Field
{
static final long serialVersionUID = 7899943957617360810L;
/**
* This is the attribute set for all characters produced
* by MessageFormat during a formatting.
*/
public static final MessageFormat.Field ARGUMENT = new MessageFormat.Field("argument");
// For deserialization
private Field()
{
super("");
}
protected Field(String s)
{
super(s);
}
/**
* invoked to resolve the true static constant by
* comparing the deserialized object to know name.
*
* @return object constant
*/
protected Object readResolve() throws InvalidObjectException
{
if (getName().equals(ARGUMENT.getName()))
return ARGUMENT;
throw new InvalidObjectException("no such MessageFormat field called " + getName());
}
}
// Helper that returns the text up to the next format opener. The
// text is put into BUFFER. Returns index of character after end of
// string. Throws IllegalArgumentException on error.
private static int scanString(String pat, int index, StringBuffer buffer)
{
int max = pat.length();
buffer.setLength(0);
boolean quoted = false;
for (; index < max; ++index)
{
char c = pat.charAt(index);
if (quoted)
{
// In a quoted context, a single quote ends the quoting.
if (c == '\'')
quoted = false;
else
buffer.append(c);
}
// Check for '', which is a single quote.
else if (c == '\'' && index + 1 < max && pat.charAt(index + 1) == '\'')
{
buffer.append(c);
++index;
}
else if (c == '\'')
{
// Start quoting.
quoted = true;
}
else if (c == '{')
break;
else
buffer.append(c);
}
// Note that we explicitly allow an unterminated quote. This is
// done for compatibility.
return index;
}
// This helper retrieves a single part of a format element. Returns
// the index of the terminating character.
private static int scanFormatElement(String pat, int index,
StringBuffer buffer, char term)
{
int max = pat.length();
buffer.setLength(0);
int brace_depth = 1;
boolean quoted = false;
for (; index < max; ++index)
{
char c = pat.charAt(index);
// First see if we should turn off quoting.
if (quoted)
{
if (c == '\'')
quoted = false;
// In both cases we fall through to inserting the
// character here.
}
// See if we have just a plain quote to insert.
else if (c == '\'' && index + 1 < max
&& pat.charAt(index + 1) == '\'')
{
buffer.append(c);
++index;
}
// See if quoting should turn on.
else if (c == '\'')
quoted = true;
else if (c == '{')
++brace_depth;
else if (c == '}')
{
if (--brace_depth == 0)
break;
}
// Check for TERM after braces, because TERM might be `}'.
else if (c == term)
break;
// All characters, including opening and closing quotes, are
// inserted here.
buffer.append(c);
}
return index;
}
// This is used to parse a format element and whatever non-format
// text might trail it.
private static int scanFormat(String pat, int index, StringBuffer buffer,
Vector elts, Locale locale)
{
MessageFormatElement mfe = new MessageFormatElement ();
elts.addElement(mfe);
int max = pat.length();
// Skip the opening `{'.
++index;
// Fetch the argument number.
index = scanFormatElement (pat, index, buffer, ',');
try
{
mfe.argNumber = Integer.parseInt(buffer.toString());
}
catch (NumberFormatException nfx)
{
IllegalArgumentException iae = new IllegalArgumentException(pat);
iae.initCause(nfx);
throw iae;
}
// Extract the element format.
if (index < max && pat.charAt(index) == ',')
{
index = scanFormatElement (pat, index + 1, buffer, ',');
mfe.type = buffer.toString();
// Extract the style.
if (index < max && pat.charAt(index) == ',')
{
index = scanFormatElement (pat, index + 1, buffer, '}');
mfe.style = buffer.toString ();
}
}
// Advance past the last terminator.
if (index >= max || pat.charAt(index) != '}')
throw new IllegalArgumentException("Missing '}' at end of message format");
++index;
// Now fetch trailing string.
index = scanString (pat, index, buffer);
mfe.trailer = buffer.toString ();
mfe.setLocale(locale);
return index;
}
/**
* Applies the specified pattern to this MessageFormat.
*
* @param aPattern The Pattern
*/
public void applyPattern (String newPattern)
{
pattern = newPattern;
StringBuffer tempBuffer = new StringBuffer ();
int index = scanString (newPattern, 0, tempBuffer);
leader = tempBuffer.toString();
Vector elts = new Vector ();
while (index < newPattern.length())
index = scanFormat (newPattern, index, tempBuffer, elts, locale);
elements = new MessageFormatElement[elts.size()];
elts.copyInto(elements);
}
/**
* Overrides Format.clone()
*/
public Object clone ()
{
MessageFormat c = (MessageFormat) super.clone ();
c.elements = (MessageFormatElement[]) elements.clone ();
return c;
}
/**
* Overrides Format.equals(Object obj)
*/
public boolean equals (Object obj)
{
if (! (obj instanceof MessageFormat))
return false;
MessageFormat mf = (MessageFormat) obj;
return (pattern.equals(mf.pattern)
&& locale.equals(mf.locale));
}
/**
* A convinience method to format patterns.
*
* @param aPattern The pattern used when formatting.
* @param arguments The array containing the objects to be formatted.
*/
public AttributedCharacterIterator formatToCharacterIterator (Object arguments)
{
Object[] arguments_array = (Object[])arguments;
FormatCharacterIterator iterator = new FormatCharacterIterator();
formatInternal(arguments_array, new StringBuffer(), null, iterator);
return iterator;
}
/**
* A convinience method to format patterns.
*
* @param aPattern The pattern used when formatting.
* @param arguments The array containing the objects to be formatted.
*/
public static String format (String pattern, Object arguments[])
{
MessageFormat mf = new MessageFormat (pattern);
StringBuffer sb = new StringBuffer ();
FieldPosition fp = new FieldPosition (NumberFormat.INTEGER_FIELD);
return mf.formatInternal(arguments, sb, fp, null).toString();
}
/**
* Returns the pattern with the formatted objects.
*
* @param source The array containing the objects to be formatted.
* @param result The StringBuffer where the text is appened.
* @param fp A FieldPosition object (it is ignored).
*/
public final StringBuffer format (Object arguments[], StringBuffer appendBuf,
FieldPosition fp)
{
return formatInternal(arguments, appendBuf, fp, null);
}
private StringBuffer formatInternal (Object arguments[],
StringBuffer appendBuf,
FieldPosition fp,
FormatCharacterIterator output_iterator)
{
appendBuf.append(leader);
if (output_iterator != null)
output_iterator.append(leader);
for (int i = 0; i < elements.length; ++i)
{
Object thisArg = null;
boolean unavailable = false;
if (arguments == null || elements[i].argNumber >= arguments.length)
unavailable = true;
else
thisArg = arguments[elements[i].argNumber];
AttributedCharacterIterator iterator = null;
Format formatter = null;
if (fp != null && i == fp.getField() && fp.getFieldAttribute() == Field.ARGUMENT)
fp.setBeginIndex(appendBuf.length());
if (unavailable)
appendBuf.append("{" + elements[i].argNumber + "}");
else
{
if (elements[i].setFormat != null)
formatter = elements[i].setFormat;
else if (elements[i].format != null)
{
if (elements[i].formatClass != null
&& ! elements[i].formatClass.isInstance(thisArg))
throw new IllegalArgumentException("Wrong format class");
formatter = elements[i].format;
}
else if (thisArg instanceof Number)
formatter = NumberFormat.getInstance(locale);
else if (thisArg instanceof Date)
formatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
else
appendBuf.append(thisArg);
}
if (fp != null && fp.getField() == i && fp.getFieldAttribute() == Field.ARGUMENT)
fp.setEndIndex(appendBuf.length());
if (formatter != null)
{
// Special-case ChoiceFormat.
if (formatter instanceof ChoiceFormat)
{
StringBuffer buf = new StringBuffer ();
formatter.format(thisArg, buf, fp);
MessageFormat mf = new MessageFormat ();
mf.setLocale(locale);
mf.applyPattern(buf.toString());
mf.format(arguments, appendBuf, fp);
}
else
{
if (output_iterator != null)
iterator = formatter.formatToCharacterIterator(thisArg);
else
formatter.format(thisArg, appendBuf, fp);
}
elements[i].format = formatter;
}
if (output_iterator != null)
{
HashMap hash_argument = new HashMap();
int position = output_iterator.getEndIndex();
hash_argument.put (MessageFormat.Field.ARGUMENT,
new Integer(elements[i].argNumber));
if (iterator != null)
{
output_iterator.append(iterator);
output_iterator.addAttributes(hash_argument, position,
output_iterator.getEndIndex());
}
else
output_iterator.append(thisArg.toString(), hash_argument);
output_iterator.append(elements[i].trailer);
}
appendBuf.append(elements[i].trailer);
}
return appendBuf;
}
/**
* Returns the pattern with the formatted objects. The first argument
* must be a array of Objects.
* This is equivalent to format((Object[]) objectArray, appendBuf, fpos)
*
* @param objectArray The object array to be formatted.
* @param appendBuf The StringBuffer where the text is appened.
* @param fpos A FieldPosition object (it is ignored).
*/
public final StringBuffer format (Object objectArray, StringBuffer appendBuf,
FieldPosition fpos)
{
return format ((Object[])objectArray, appendBuf, fpos);
}
/**
* Returns an array with the Formats for
* the arguments.
*/
public Format[] getFormats ()
{
Format[] f = new Format[elements.length];
for (int i = elements.length - 1; i >= 0; --i)
f[i] = elements[i].setFormat;
return f;
}
/**
* Returns the locale.
*/
public Locale getLocale ()
{
return locale;
}
/**
* Overrides Format.hashCode()
*/
public int hashCode ()
{
// FIXME: not a very good hash.
return pattern.hashCode() + locale.hashCode();
}
private MessageFormat ()
{
}
/**
* Creates a new MessageFormat object with
* the specified pattern
*
* @param pattern The Pattern
*/
public MessageFormat(String pattern)
{
this(pattern, Locale.getDefault());
}
/**
* Creates a new MessageFormat object with
* the specified pattern
*
* @param pattern The Pattern
* @param locale The Locale to use
*
* @since 1.4
*/
public MessageFormat(String pattern, Locale locale)
{
this.locale = locale;
applyPattern (pattern);
}
/**
* Parse a string <code>sourceStr</code> against the pattern specified
* to the MessageFormat constructor.
*
* @param sourceStr the string to be parsed.
* @param pos the current parse position (and eventually the error position).
* @return the array of parsed objects sorted according to their argument number
* in the pattern.
*/
public Object[] parse (String sourceStr, ParsePosition pos)
{
// Check initial text.
int index = pos.getIndex();
if (! sourceStr.startsWith(leader, index))
{
pos.setErrorIndex(index);
return null;
}
index += leader.length();
Vector results = new Vector (elements.length, 1);
// Now check each format.
for (int i = 0; i < elements.length; ++i)
{
Format formatter = null;
if (elements[i].setFormat != null)
formatter = elements[i].setFormat;
else if (elements[i].format != null)
formatter = elements[i].format;
Object value = null;
if (formatter instanceof ChoiceFormat)
{
// We must special-case a ChoiceFormat because it might
// have recursive formatting.
ChoiceFormat cf = (ChoiceFormat) formatter;
String[] formats = (String[]) cf.getFormats();
double[] limits = (double[]) cf.getLimits();
MessageFormat subfmt = new MessageFormat ();
subfmt.setLocale(locale);
ParsePosition subpos = new ParsePosition (index);
int j;
for (j = 0; value == null && j < limits.length; ++j)
{
subfmt.applyPattern(formats[j]);
subpos.setIndex(index);
value = subfmt.parse(sourceStr, subpos);
}
if (value != null)
{
index = subpos.getIndex();
value = new Double (limits[j]);
}
}
else if (formatter != null)
{
pos.setIndex(index);
value = formatter.parseObject(sourceStr, pos);
if (value != null)
index = pos.getIndex();
}
else
{
// We have a String format. This can lose in a number
// of ways, but we give it a shot.
int next_index;
if (elements[i].trailer.length() > 0)
next_index = sourceStr.indexOf(elements[i].trailer, index);
else
next_index = sourceStr.length();
if (next_index == -1)
{
pos.setErrorIndex(index);
return null;
}
value = sourceStr.substring(index, next_index);
index = next_index;
}
if (value == null
|| ! sourceStr.startsWith(elements[i].trailer, index))
{
pos.setErrorIndex(index);
return null;
}
if (elements[i].argNumber >= results.size())
results.setSize(elements[i].argNumber + 1);
results.setElementAt(value, elements[i].argNumber);
index += elements[i].trailer.length();
}
Object[] r = new Object[results.size()];
results.copyInto(r);
return r;
}
public Object[] parse (String sourceStr) throws ParseException
{
ParsePosition pp = new ParsePosition (0);
Object[] r = parse (sourceStr, pp);
if (r == null)
throw new ParseException ("couldn't parse string", pp.getErrorIndex());
return r;
}
public Object parseObject (String sourceStr, ParsePosition pos)
{
return parse (sourceStr, pos);
}
/**
* Sets the format for the argument at an specified
* index.
*
* @param index The index.
* @format The Format object.
*/
public void setFormat (int variableNum, Format newFormat)
{
elements[variableNum].setFormat = newFormat;
}
/**
* Sets the formats for the arguments.
*
* @param formats An array of Format objects.
*/
public void setFormats (Format[] newFormats)
{
if (newFormats.length < elements.length)
throw new IllegalArgumentException("Not enough format objects");
int len = Math.min(newFormats.length, elements.length);
for (int i = 0; i < len; ++i)
elements[i].setFormat = newFormats[i];
}
/**
* Sets the locale.
*
* @param locale A Locale
*/
public void setLocale (Locale loc)
{
locale = loc;
if (elements != null)
{
for (int i = 0; i < elements.length; ++i)
elements[i].setLocale(loc);
}
}
/**
* Returns the pattern.
*/
public String toPattern ()
{
return pattern;
}
/**
* Return the formatters used sorted by argument index. It uses the
* internal table to fill in this array: if a format has been
* set using <code>setFormat</code> or <code>setFormatByArgumentIndex</code>
* then it returns it at the right index. If not it uses the detected
* formatters during a <code>format</code> call. If nothing is known
* about that argument index it just puts null at that position.
* To get useful informations you may have to call <code>format</code>
* at least once.
*
* @return an array of formatters sorted by argument index.
*/
public Format[] getFormatsByArgumentIndex()
{
int argNumMax = 0;
// First, find the greatest argument number.
for (int i=0;i<elements.length;i++)
if (elements[i].argNumber > argNumMax)
argNumMax = elements[i].argNumber;
Format[] formats = new Format[argNumMax];
for (int i=0;i<elements.length;i++)
{
if (elements[i].setFormat != null)
formats[elements[i].argNumber] = elements[i].setFormat;
else if (elements[i].format != null)
formats[elements[i].argNumber] = elements[i].format;
}
return formats;
}
/**
* Set the format to used using the argument index number.
*
* @param argumentIndex the argument index.
* @param newFormat the format to use for this argument.
*/
public void setFormatByArgumentIndex(int argumentIndex,
Format newFormat)
{
for (int i=0;i<elements.length;i++)
{
if (elements[i].argNumber == argumentIndex)
elements[i].setFormat = newFormat;
}
}
/**
* Set the format for argument using a specified array of formatters
* which is sorted according to the argument index. If the number of
* elements in the array is fewer than the number of arguments only
* the arguments specified by the array are touched.
*
* @param newFormats array containing the new formats to set.
*
* @throws NullPointerException if newFormats is null
*/
public void setFormatsByArgumentIndex(Format[] newFormats)
{
for (int i=0;i<newFormats.length;i++)
{
// Nothing better than that can exist here.
setFormatByArgumentIndex(i, newFormats[i]);
}
}
// The pattern string.
private String pattern;
// The locale.
private Locale locale;
// Variables.
private MessageFormatElement[] elements;
// Leader text.
private String leader;
}
@@ -0,0 +1,808 @@
/* NumberFormat.java -- Formats and parses numbers
Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Currency;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* This is the abstract superclass of all classes which format and
* parse numeric values such as decimal numbers, integers, currency values,
* and percentages. These classes perform their parsing and formatting
* in a locale specific manner, accounting for such items as differing
* currency symbols and thousands separators.
* <p>
* To create an instance of a concrete subclass of <code>NumberFormat</code>,
* do not call a class constructor directly. Instead, use one of the
* static factory methods in this class such as
* <code>getCurrencyInstance</code>.
*
* @author Tom Tromey (tromey@cygnus.com)
* @author Aaron M. Renn (arenn@urbanophile.com)
* @date March 4, 1999
*/
/* Written using "Java Class Libraries", 2nd edition, plus online
* API docs for JDK 1.2 from http://www.javasoft.com.
* Status: Believed complete and correct to 1.2, except getAvailableLocales.
*/
public abstract class NumberFormat extends Format implements Cloneable
{
/**
* This is a constant used to create a <code>FieldPosition</code> object
* that will return the integer portion of a formatted number.
*/
public static final int INTEGER_FIELD = 0;
/**
* This is a constant used to create a <code>FieldPosition</code> object
* that will return the fractional portion of a formatted number.
*/
public static final int FRACTION_FIELD = 1;
public static class Field extends Format.Field
{
static final long serialVersionUID = 7494728892700160890L;
/**
* Attribute set to all characters containing digits of the integer
* part.
*/
public static final NumberFormat.Field INTEGER
= new Field("integer");
/**
* Attribute set to all characters containing digits of the fractional
* part.
*/
public static final NumberFormat.Field FRACTION
= new Field("fraction");
/**
* Attribute set to all characters containing digits of the exponential
* part.
*/
public static final NumberFormat.Field EXPONENT
= new Field("exponent");
/**
* Attribute set to all characters containing a decimal separator.
*/
public static final NumberFormat.Field DECIMAL_SEPARATOR
= new Field("decimal separator");
/**
* Attribute set to all characters containing a sign (plus or minus).
*/
public static final NumberFormat.Field SIGN
= new Field("sign");
/**
* Attribute set to all characters containing a grouping separator (e.g.
* a comma, a white space,...).
*/
public static final NumberFormat.Field GROUPING_SEPARATOR
= new Field("grouping separator");
/**
* Attribute set to all characters containing an exponential symbol (e.g.
* 'E')
*/
public static final NumberFormat.Field EXPONENT_SYMBOL
= new Field("exponent symbol");
/**
* Attribute set to all characters containing a percent symbol (e.g. '%')
*/
public static final NumberFormat.Field PERCENT
= new Field("percent");
/**
* Attribute set to all characters containing a permille symbol.
*/
public static final NumberFormat.Field PERMILLE
= new Field("permille");
/**
* Attribute set to all characters containing the currency unit.
*/
public static final NumberFormat.Field CURRENCY
= new Field("currency");
/**
* Attribute set to all characters containing the exponent sign.
*/
public static final NumberFormat.Field EXPONENT_SIGN
= new Field("exponent sign");
/**
* Private fields to register all fields contained in this descriptor.
*/
private static final NumberFormat.Field[] allFields =
{
INTEGER, FRACTION, EXPONENT, DECIMAL_SEPARATOR, SIGN,
GROUPING_SEPARATOR, EXPONENT_SYMBOL, PERCENT,
PERMILLE, CURRENCY, EXPONENT_SIGN
};
/**
* This constructor is only used by the deserializer. Without it,
* it would fail to construct a valid object.
*/
private Field()
{
super("");
}
/**
* Create a Field instance with the specified field name.
*
* @param field_name Field name for the new Field instance.
*/
protected Field(String field_name)
{
super (field_name);
}
/**
* This function is used by the deserializer to know which object
* to use when it encounters an encoded NumberFormat.Field in a
* serialization stream. If the stream is valid it should return
* one of the above field. In the other case we throw an exception.
*
* @return a valid official NumberFormat.Field instance.
*
* @throws InvalidObjectException if the field name is invalid.
*/
protected Object readResolve() throws InvalidObjectException
{
String s = getName();
for (int i = 0; i < allFields.length; i++)
if (s.equals(allFields[i].getName()))
return allFields[i];
throw new InvalidObjectException("no such NumberFormat field called "
+ s);
}
}
/**
* This method is a specialization of the format method that performs
* a simple formatting of the specified <code>long</code> number.
*
* @param number The <code>long</code> to format.
*
* @return The formatted number
*/
public final String format (long number)
{
StringBuffer sbuf = new StringBuffer(50);
format (number, sbuf, null);
return sbuf.toString();
}
public final StringBuffer format (Object obj, StringBuffer sbuf,
FieldPosition pos)
{
if (obj instanceof Number)
return format(((Number) obj).doubleValue(), sbuf, pos);
else
throw new IllegalArgumentException
("Cannot format given Object as a Number");
}
/**
* This method formats the specified <code>double</code> and appends it to
* a <code>StringBuffer</code>.
*
* @param number The <code>double</code> to format.
* @param sb The <code>StringBuffer</code> to append the formatted number to.
* @param pos The desired <code>FieldPosition</code>.
*
* @return The <code>StringBuffer</code> with the appended number.
*/
public abstract StringBuffer format (double number,
StringBuffer sbuf, FieldPosition pos);
/**
* This method formats the specified <code>long</code> and appends it to
* a <code>StringBuffer</code>.
*
* @param number The <code>long</code> to format.
* @param sb The <code>StringBuffer</code> to append the formatted number to.
* @param pos The desired <code>FieldPosition</code>.
*
* @return The <code>StringBuffer</code> with the appended number.
*/
public abstract StringBuffer format (long number,
StringBuffer sbuf, FieldPosition pos);
/**
* This method tests the specified object for equality against this object.
* This will be <code>true</code> if the following conditions are met:
* <p>
* <ul>
* <li>The specified object is not <code>null</code>.
* <li>The specified object is an instance of <code>NumberFormat</code>.
* </ul>
* <p>
* Since this method does not test much, it is highly advised that
* concrete subclasses override this method.
*
* @param obj The <code>Object</code> to test against equality with
* this object.
*
* @return <code>true</code> if the specified object is equal to
* this object, <code>false</code> otherwise.
*/
public boolean equals (Object obj)
{
if (! (obj instanceof NumberFormat))
return false;
NumberFormat nf = (NumberFormat) obj;
return (groupingUsed == nf.groupingUsed
&& maximumFractionDigits == nf.maximumFractionDigits
&& maximumIntegerDigits == nf.maximumIntegerDigits
&& minimumFractionDigits == nf.minimumFractionDigits
&& minimumIntegerDigits == nf.minimumIntegerDigits
&& parseIntegerOnly == nf.parseIntegerOnly);
}
/**
* This method returns a list of locales for which concrete instances
* of <code>NumberFormat</code> subclasses may be created.
*
* @return The list of available locales.
*/
public static Locale[] getAvailableLocales ()
{
Locale[] list = new Locale[1];
list[0] = Locale.US;
return list;
}
private static NumberFormat computeInstance(Locale loc, String resource,
String def)
{
ResourceBundle res;
try
{
res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
loc, ClassLoader.getSystemClassLoader());
}
catch (MissingResourceException x)
{
res = null;
}
String fmt;
try
{
fmt = res == null ? def : res.getString(resource);
}
catch (MissingResourceException x)
{
fmt = def;
}
DecimalFormatSymbols dfs = new DecimalFormatSymbols (loc);
return new DecimalFormat (fmt, dfs);
}
/**
* This method returns an instance of <code>NumberFormat</code> suitable
* for formatting and parsing currency values in the default locale.
*
* @return An instance of <code>NumberFormat</code> for handling currencies.
*/
public static final NumberFormat getCurrencyInstance ()
{
return getCurrencyInstance (Locale.getDefault());
}
/**
* This method returns an instance of <code>NumberFormat</code> suitable
* for formatting and parsing currency values in the specified locale.
*
* @return An instance of <code>NumberFormat</code> for handling currencies.
*/
public static NumberFormat getCurrencyInstance (Locale loc)
{
NumberFormat format;
format = computeInstance (loc, "currencyFormat", "$#,##0.00;($#,##0.00)");
format.setMaximumFractionDigits(format.getCurrency().getDefaultFractionDigits());
return format;
}
/**
* This method returns a default instance for the default locale. This
* will be a concrete subclass of <code>NumberFormat</code>, but the
* actual class returned is dependent on the locale.
*
* @return An instance of the default <code>NumberFormat</code> class.
*/
public static final NumberFormat getInstance ()
{
return getInstance (Locale.getDefault());
}
/**
* This method returns a default instance for the specified locale. This
* will be a concrete subclass of <code>NumberFormat</code>, but the
* actual class returned is dependent on the locale.
*
* @param locale The desired locale.
*
* @return An instance of the default <code>NumberFormat</code> class.
*/
public static NumberFormat getInstance (Locale loc)
{
// For now always return a number instance.
return getNumberInstance (loc);
}
/**
* This method returns the maximum number of digits allowed in the fraction
* portion of a number.
*
* @return The maximum number of digits allowed in the fraction
* portion of a number.
*/
public int getMaximumFractionDigits ()
{
return maximumFractionDigits;
}
/**
* This method returns the maximum number of digits allowed in the integer
* portion of a number.
*
* @return The maximum number of digits allowed in the integer
* portion of a number.
*/
public int getMaximumIntegerDigits ()
{
return maximumIntegerDigits;
}
/**
* This method returns the minimum number of digits allowed in the fraction
* portion of a number.
*
* @return The minimum number of digits allowed in the fraction
* portion of a number.
*/
public int getMinimumFractionDigits ()
{
return minimumFractionDigits;
}
/**
* This method returns the minimum number of digits allowed in the integer
* portion of a number.
*
* @return The minimum number of digits allowed in the integer
* portion of a number.
*/
public int getMinimumIntegerDigits ()
{
return minimumIntegerDigits;
}
/**
* This method returns a default instance for the specified locale. This
* will be a concrete subclass of <code>NumberFormat</code>, but the
* actual class returned is dependent on the locale.
*
* @param locale The desired locale.
*
* @return An instance of the default <code>NumberFormat</code> class.
*/
public static final NumberFormat getNumberInstance ()
{
return getNumberInstance (Locale.getDefault());
}
/**
* This method returns a general purpose number formatting and parsing
* class for the default locale. This will be a concrete subclass of
* <code>NumberFormat</code>, but the actual class returned is dependent
* on the locale.
*
* @return An instance of a generic number formatter for the default locale.
*/
public static NumberFormat getNumberInstance (Locale loc)
{
return computeInstance (loc, "numberFormat", "#,##0.###");
}
/**
* This method returns an integer formatting and parsing class for the
* default locale. This will be a concrete subclass of <code>NumberFormat</code>,
* but the actual class returned is dependent on the locale.
*
* @return An instance of an integer number formatter for the default locale.
* @since 1.4
*/
public static final NumberFormat getIntegerInstance()
{
return getIntegerInstance (Locale.getDefault());
}
/**
* This method returns an integer formatting and parsing class for the
* default locale. This will be a concrete subclass of <code>NumberFormat</code>,
* but the actual class returned is dependent on the locale.
*
* @param locale the desired locale.
*
* @return An instance of an integer number formatter for the desired locale.
* @since 1.4
*/
public static NumberFormat getIntegerInstance(Locale locale)
{
NumberFormat format = computeInstance (locale, "numberFormat", "#,##0");
format.setMaximumFractionDigits(0);
format.setParseIntegerOnly (true);
return format;
}
/**
* This method returns an instance of <code>NumberFormat</code> suitable
* for formatting and parsing percentage values in the default locale.
*
* @return An instance of <code>NumberFormat</code> for handling percentages.
*/
public static final NumberFormat getPercentInstance ()
{
return getPercentInstance (Locale.getDefault());
}
/**
* This method returns an instance of <code>NumberFormat</code> suitable
* for formatting and parsing percentage values in the specified locale.
*
* @param locale The desired locale.
*
* @return An instance of <code>NumberFormat</code> for handling percentages.
*/
public static NumberFormat getPercentInstance (Locale loc)
{
return computeInstance (loc, "percentFormat", "#,##0%");
}
/**
* This method returns a hash value for this object.
*
* @return The hash code.
*/
public int hashCode ()
{
int hash = super.hashCode();
hash ^= (maximumFractionDigits + maximumIntegerDigits
+ minimumFractionDigits + minimumIntegerDigits);
if (groupingUsed)
hash ^= 0xf0f0;
if (parseIntegerOnly)
hash ^= 0x0f0f;
return hash;
}
/**
* This method tests whether or not grouping is in use. Grouping is
* a method of marking separations in numbers, such as thousand separators
* in the US English locale. The grouping positions and symbols are all
* locale specific. As an example, with grouping disabled, the number one
* million would appear as "1000000". With grouping enabled, this number
* might appear as "1,000,000". (Both of these assume the US English
* locale).
*
* @return <code>true</code> if grouping is enabled,
* <code>false</code> otherwise.
*/
public boolean isGroupingUsed ()
{
return groupingUsed;
}
/**
* This method tests whether or not only integer values should be parsed.
* If this class is parsing only integers, parsing stops at the decimal
* point.
*
* @return <code>true</code> if only integers are parsed,
* <code>false</code> otherwise.
*/
public boolean isParseIntegerOnly ()
{
return parseIntegerOnly;
}
/**
* This is a default constructor for use by subclasses.
*/
public NumberFormat ()
{
}
/**
* This method parses the specified string into a <code>Number</code>. This
* will be a <code>Long</code> if possible, otherwise it will be a
* <code>Double</code>. If no number can be parsed, no exception is
* thrown. Instead, the parse position remains at its initial index.
*
* @param str The string to parse.
* @param pp The desired <code>ParsePosition</code>.
*
* @return The parsed <code>Number</code>
*/
public abstract Number parse (String sourceStr, ParsePosition pos);
/**
* This method parses the specified string into a <code>Number</code>. This
* will be a <code>Long</code> if possible, otherwise it will be a
* <code>Double</code>. If no number can be parsed, an exception will be
* thrown.
*
* @param str The string to parse.
*
* @return The parsed <code>Number</code>
*
* @exception ParseException If no number can be parsed.
*/
public Number parse (String sourceStr) throws ParseException
{
ParsePosition pp = new ParsePosition (0);
Number r = parse (sourceStr, pp);
if (r == null)
{
int index = pp.getErrorIndex();
if (index < 0)
index = pp.getIndex();
throw new ParseException ("couldn't parse number", index);
}
return r;
}
/**
* This method parses the specified string into an <code>Object</code>. This
* will be a <code>Long</code> if possible, otherwise it will be a
* <code>Double</code>. If no number can be parsed, no exception is
* thrown. Instead, the parse position remains at its initial index.
*
* @param str The string to parse.
* @param pp The desired <code>ParsePosition</code>.
*
* @return The parsed <code>Object</code>
*/
public final Object parseObject (String sourceStr, ParsePosition pos)
{
return parse (sourceStr, pos);
}
/**
* This method sets the grouping behavior of this formatter. Grouping is
* a method of marking separations in numbers, such as thousand separators
* in the US English locale. The grouping positions and symbols are all
* locale specific. As an example, with grouping disabled, the number one
* million would appear as "1000000". With grouping enabled, this number
* might appear as "1,000,000". (Both of these assume the US English
* locale).
*
* @param groupingUsed <code>true</code> to enable grouping,
* <code>false</code> to disable it.
*/
public void setGroupingUsed (boolean newValue)
{
groupingUsed = newValue;
}
/**
* This method sets the maximum number of digits allowed in the fraction
* portion of a number to the specified value. If this is less than the
* current minimum allowed digits, the minimum allowed digits value will
* be lowered to be equal to the new maximum allowed digits value.
*
* @param maximumFractionDigits The new maximum fraction digits value.
*/
public void setMaximumFractionDigits (int newValue)
{
maximumFractionDigits = newValue;
if (getMinimumFractionDigits () > maximumFractionDigits)
setMinimumFractionDigits (maximumFractionDigits);
}
/**
* This method sets the maximum number of digits allowed in the integer
* portion of a number to the specified value. If this is less than the
* current minimum allowed digits, the minimum allowed digits value will
* be lowered to be equal to the new maximum allowed digits value.
*
* @param maximumIntegerDigits The new maximum integer digits value.
*/
public void setMaximumIntegerDigits (int newValue)
{
maximumIntegerDigits = newValue;
if (getMinimumIntegerDigits () > maximumIntegerDigits)
setMinimumIntegerDigits (maximumIntegerDigits);
}
/**
* This method sets the minimum number of digits allowed in the fraction
* portion of a number to the specified value. If this is greater than the
* current maximum allowed digits, the maximum allowed digits value will
* be raised to be equal to the new minimum allowed digits value.
*
* @param minimumFractionDigits The new minimum fraction digits value.
*/
public void setMinimumFractionDigits (int newValue)
{
minimumFractionDigits = newValue;
if (getMaximumFractionDigits () < minimumFractionDigits)
setMaximumFractionDigits (minimumFractionDigits);
}
/**
* This method sets the minimum number of digits allowed in the integer
* portion of a number to the specified value. If this is greater than the
* current maximum allowed digits, the maximum allowed digits value will
* be raised to be equal to the new minimum allowed digits value.
*
* @param minimumIntegerDigits The new minimum integer digits value.
*/
public void setMinimumIntegerDigits (int newValue)
{
minimumIntegerDigits = newValue;
if (getMaximumIntegerDigits () < minimumIntegerDigits)
setMaximumIntegerDigits (minimumIntegerDigits);
}
/**
* This method sets the parsing behavior of this object to parse only
* integers or not.
*
* @param parseIntegerOnly <code>true</code> to parse only integers,
* <code>false</code> otherwise.
*/
public void setParseIntegerOnly (boolean value)
{
parseIntegerOnly = value;
}
/**
* This method is a specialization of the format method that performs
* a simple formatting of the specified <code>double</code> number.
*
* @param number The <code>double</code> to format.
*
* @return The formatted number
*/
public final String format (double number)
{
StringBuffer sbuf = new StringBuffer(50);
format (number, sbuf, null);
return sbuf.toString();
}
// These field names are fixed by the serialization spec.
boolean groupingUsed;
int maximumFractionDigits;
private byte maxFractionDigits;
int maximumIntegerDigits;
private byte maxIntegerDigits;
int minimumFractionDigits;
private byte minFractionDigits;
int minimumIntegerDigits;
private byte minIntegerDigits;
boolean parseIntegerOnly;
private int serialVersionOnStream;
private static final long serialVersionUID = -2308460125733713944L;
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
if (serialVersionOnStream < 1)
{
maximumFractionDigits = maxFractionDigits;
maximumIntegerDigits = maxIntegerDigits;
minimumFractionDigits = minFractionDigits;
minimumIntegerDigits = minIntegerDigits;
serialVersionOnStream = 1;
}
}
private void writeObject(ObjectOutputStream stream) throws IOException
{
maxFractionDigits = maximumFractionDigits < Byte.MAX_VALUE ?
(byte) maximumFractionDigits : Byte.MAX_VALUE;
maxIntegerDigits = maximumIntegerDigits < Byte.MAX_VALUE ?
(byte) maximumIntegerDigits : Byte.MAX_VALUE;
minFractionDigits = minimumFractionDigits < Byte.MAX_VALUE ?
(byte) minimumFractionDigits : Byte.MAX_VALUE;
minIntegerDigits = minimumIntegerDigits < Byte.MAX_VALUE ?
(byte) minimumIntegerDigits : Byte.MAX_VALUE;
serialVersionOnStream = 1;
stream.defaultWriteObject();
}
/**
* Returns the currency used by this number format when formatting currency
* values.
*
* The default implementation throws UnsupportedOperationException.
*
* @return The used currency object, or null.
*
* @throws UnsupportedOperationException If the number format class doesn't
* implement currency formatting.
*
* @since 1.4
*/
public Currency getCurrency()
{
throw new UnsupportedOperationException();
}
/**
* Sets the currency used by this number format when formatting currency
* values.
*
* The default implementation throws UnsupportedOperationException.
*
* @param currency The new currency to be used by this number format.
*
* @throws NullPointerException If currenc is null.
* @throws UnsupportedOperationException If the number format class doesn't
* implement currency formatting.
*
* @since 1.4
*/
public void setCurrency(Currency currency)
{
if (currency == null)
throw new NullPointerException("currency may not be null");
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,86 @@
/* ParseException.java -- an error occurred while parsing
Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
/**
* This exception is thrown when an unexpected error occurs during parsing.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Per Bothner (bothner@cygnus.com)
* @see Format
* @see FieldPosition
* @status updated to 1.4
*/
public class ParseException extends Exception
{
/**
* Compatible with JDK 1.1+.
*/
private static final long serialVersionUID = 2703218443322787634L;
/**
* This is the position where the error was encountered.
*
* @serial the zero-based offset in the string where the error occurred
*/
private final int errorOffset;
/**
* This method initializes a new instance of <code>ParseException</code>
* with a detailed error message and a error position.
*
* @param msg the descriptive message describing the error
* @param offset the position where the error was encountered
*/
public ParseException(String s, int offset)
{
super(s);
errorOffset = offset;
}
/**
* This method returns the position where the error occurred.
*
* @return the position where the error occurred
*/
public int getErrorOffset()
{
return errorOffset;
}
} // class ParseException
@@ -0,0 +1,151 @@
/* ParsePosition.java -- Keep track of position while parsing.
Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
/**
* This class is used to keep track of the current position during parsing
* operations.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Per Bothner (bothner@cygnus.com)
*/
public class ParsePosition
{
/**
* This is the index of the current parse position.
*/
private int index;
/**
* This is the index of the position where an error occurred during parsing.
*/
private int error_index;
/**
* This method initializes a new instance of <code>ParsePosition</code> to
* have the specified initial index value.
*
* @param index The initial parsing index.
*/
public ParsePosition (int index)
{
this.index = index;
error_index = -1;
}
/**
* This method returns the current parsing index.
*
* @return The current parsing index
*/
public int getIndex ()
{
return index;
}
/**
* This method sets the current parsing index to the specified value.
*
* @param index The new parsing index.
*/
public void setIndex (int index)
{
this.index = index;
}
/**
* This method returns the error index value. This value defaults to -1
* unless explicitly set to another value.
*
* @return The error index.
*/
public int getErrorIndex ()
{
return error_index;
}
/**
* This method sets the error index to the specified value.
*
* @param error_index The new error index
*/
public void setErrorIndex (int error_index)
{
this.error_index = error_index;
}
/**
* This method tests the specified object for equality with this
* object. The two objects will be considered equal if and only if
* all of the following conditions are met.
* <p>
* <ul>
* <li>The specified object is not <code>null</code>.</li>
* <li>The specified object is an instance of <code>ParsePosition</code>.</li>
* <li>The specified object has the same index and error index as
* this object.</li>
* </ul>
*
* @param obj The <code>Object</code> to test for equality against
* this object.
*
* @return <code>true</code> if the specified object is equal to
* this object, <code>false</code> otherwise.
*/
public boolean equals (Object obj)
{
if (! (obj instanceof ParsePosition))
return false;
ParsePosition other = (ParsePosition) obj;
return index == other.index && error_index == other.error_index;
}
/**
* This method returns a <code>String</code> representation of this
* object.
*
* @return A <code>String</code> that represents this object.
*/
public String toString ()
{
return (getClass ().getName () + "[index=" + getIndex ()
+ ",errorIndex=" + getErrorIndex () + "]");
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,356 @@
/* StringCharacterIterator.java -- Iterate over a character range in a string
Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package java.text;
/**
* This class iterates over a range of characters in a <code>String</code>.
* For a given range of text, a beginning and ending index,
* as well as a current index are defined. These values can be queried
* by the methods in this interface. Additionally, various methods allow
* the index to be set.
*
* @author Aaron M. Renn (arenn@urbanophile.com)
* @author Tom Tromey (tromey@cygnus.com)
*/
public final class StringCharacterIterator implements CharacterIterator
{
/**
* This is the string to iterate over
*/
private String text;
/**
* This is the value of the start position of the text range.
*/
private int begin;
/**
* This is the value of the ending position of the text range.
*/
private int end;
/**
* This is the current value of the scan index.
*/
private int index;
/**
* This method initializes a new instance of
* <code>StringCharacterIterator</code> to iterate over the entire
* text of the specified <code>String</code>. The initial index
* value will be set to the first character in the string.
*
* @param text The <code>String</code> to iterate through.
*/
public StringCharacterIterator (String text)
{
this (text, 0, text.length (), 0);
}
/*************************************************************************/
/**
* This method initializes a new instance of
* <code>StringCharacterIterator</code> to iterate over the entire
* text of the specified <code>String</code>. The initial index
* value will be set to the specified value.
*
* @param text The <code>String</code> to iterate through.
* @param index The initial index position.
*/
public StringCharacterIterator (String text, int index)
{
this (text, 0, text.length (), index);
}
/*************************************************************************/
/**
* This method initializes a new instance of
* <code>StringCharacterIterator</code> that iterates over the text
* in a subrange of the specified <code>String</code>. The
* beginning and end of the range are specified by the caller, as is
* the initial index position.
*
* @param text The <code>String</code> to iterate through.
* @param begin The beginning position in the character range.
* @param end The ending position in the character range.
* @param index The initial index position.
*
* @param IllegalArgumentException If any of the range values are
* invalid.
*/
public StringCharacterIterator (String text, int begin, int end, int index)
{
int len = text.length ();
if ((begin < 0) || (begin > len))
throw new IllegalArgumentException ("Bad begin position");
if ((end < begin) || (end > len))
throw new IllegalArgumentException ("Bad end position");
if ((index < begin) || (index > end))
throw new IllegalArgumentException ("Bad initial index position");
this.text = text;
this.begin = begin;
this.end = end;
this.index = index;
}
/**
* This is a package level constructor that copies the text out of
* an existing StringCharacterIterator and resets the beginning and
* ending index.
*
* @param scci The StringCharacterIterator to copy the info from
* @param begin The beginning index of the range we are interested in.
* @param end The ending index of the range we are interested in.
*/
StringCharacterIterator (StringCharacterIterator sci, int begin, int end)
{
this (sci.text, begin, end, begin);
}
/**
* This method returns the character at the current index position
*
* @return The character at the current index position.
*/
public char current ()
{
return (index < end) ? text.charAt (index) : DONE;
}
/*************************************************************************/
/**
* This method increments the current index and then returns the
* character at the new index value. If the index is already at
* <code>getEndIndex () - 1</code>, it will not be incremented.
*
* @return The character at the position of the incremented index
* value, or <code>DONE</code> if the index has reached
* getEndIndex () - 1.
*/
public char next ()
{
if (index == end)
return DONE;
++index;
return current ();
}
/*************************************************************************/
/**
* This method decrements the current index and then returns the
* character at the new index value. If the index value is already
* at the beginning index, it will not be decremented.
*
* @return The character at the position of the decremented index
* value, or <code>DONE</code> if index was already equal to the
* beginning index value.
*/
public char previous ()
{
if (index == begin)
return DONE;
--index;
return current ();
}
/*************************************************************************/
/**
* This method sets the index value to the beginning of the range and returns
* the character there.
*
* @return The character at the beginning of the range, or
* <code>DONE</code> if the range is empty.
*/
public char first ()
{
index = begin;
return current ();
}
/*************************************************************************/
/**
* This method sets the index value to <code>getEndIndex () - 1</code> and
* returns the character there. If the range is empty, then the index value
* will be set equal to the beginning index.
*
* @return The character at the end of the range, or
* <code>DONE</code> if the range is empty.
*/
public char last ()
{
if (end == begin)
return DONE;
index = end - 1;
return current ();
}
/*************************************************************************/
/**
* This method returns the current value of the index.
*
* @return The current index value
*/
public int getIndex ()
{
return index;
}
/*************************************************************************/
/**
* This method sets the value of the index to the specified value, then
* returns the character at that position.
*
* @param index The new index value.
*
* @return The character at the new index value or <code>DONE</code>
* if the index value is equal to <code>getEndIndex</code>.
*
* @exception IllegalArgumentException If the specified index is not valid
*/
public char setIndex (int index)
{
if ((index < begin) || (index > end))
throw new IllegalArgumentException ("Bad index specified");
this.index = index;
return current ();
}
/*************************************************************************/
/**
* This method returns the character position of the first character in the
* range.
*
* @return The index of the first character in the range.
*/
public int getBeginIndex ()
{
return begin;
}
/*************************************************************************/
/**
* This method returns the character position of the end of the text range.
* This will actually be the index of the first character following the
* end of the range. In the event the text range is empty, this will be
* equal to the first character in the range.
*
* @return The index of the end of the range.
*/
public int getEndIndex ()
{
return end;
}
/*************************************************************************/
/**
* This method creates a copy of this <code>CharacterIterator</code>.
*
* @return A copy of this <code>CharacterIterator</code>.
*/
public Object clone ()
{
return new StringCharacterIterator (text, begin, end, index);
}
/*************************************************************************/
/**
* This method tests this object for equality againt the specified
* object. This will be true if and only if the specified object:
* <p>
* <ul>
* <li>is not <code>null</code>.</li>
* <li>is an instance of <code>StringCharacterIterator</code></li>
* <li>has the same text as this object</li>
* <li>has the same beginning, ending, and current index as this object.</li>
* </ul>
*
* @param obj The object to test for equality against.
*
* @return <code>true</code> if the specified object is equal to this
* object, <code>false</code> otherwise.
*/
public boolean equals (Object obj)
{
if (! (obj instanceof StringCharacterIterator))
return false;
StringCharacterIterator sci = (StringCharacterIterator) obj;
return (begin == sci.begin
&& end == sci.end
&& index == sci.index
&& text.equals (sci.text));
}
/*************************************************************************/
/**
* This method allows other classes in java.text to change the value
* of the underlying text being iterated through.
*
* @param text The new <code>String</code> to iterate through.
*/
public void setText (String text)
{
this.text = text;
this.begin = 0;
this.end = text.length ();
this.index = 0;
}
}
@@ -0,0 +1,220 @@
# This property file contains dependencies of classes, methods, and
# field on other methods or classes.
#
# Syntax:
#
# <used>: <needed 1> [... <needed N>]
#
# means that when <used> is included, <needed 1> (... <needed N>) must
# be included as well.
#
# <needed X> and <used> are of the form
#
# <class.methodOrField(signature)>
#
# or just
#
# <class>
#
# Within dependencies, variables can be used. A variable is defined as
# follows:
#
# {variable}: value1 value2 ... value<n>
#
# variables can be used on the right side of dependencies as follows:
#
# <used>: com.bla.blu.{variable}.Class.m()V
#
# The use of the variable will expand to <n> dependencies of the form
#
# <used>: com.bla.blu.value1.Class.m()V
# <used>: com.bla.blu.value2.Class.m()V
# ...
# <used>: com.bla.blu.value<n>.Class.m()V
#
# Variables can be redefined when building a system to select the
# required support for features like encodings, protocols, etc.
#
# Hints:
#
# - For methods and fields, the signature is mandatory. For
# specification, please see the Java Virtual Machine Specification by
# SUN. Unlike in the spec, field signatures (types) are in brackets.
#
# - Package names must be separated by '/' (and not '.'). E.g.,
# java/lang/Class (this is necessary, because the '.' is used to
# separate method or field names from classes)
#
# - In case <needed> refers to a class, only the class itself will be
# included in the resulting binary, NOT necessarily all its methods
# and fields. If you want to refer to all methods and fields, you can
# write class.* as an abbreviation.
#
# - Abbreviations for packages are also possible: my/package/* means all
# methods and fields of all classes in my/package.
#
# - A line with a trailing '\' continues in the next line.
# end of file
# All locales supported are loaded via classes from java.text (see below)
# from class gnu/java/locale/LocaleInformation_<locale_id>
#
# This introduces a dependency for all locales. To allow an easy selection
# and addition of locales, the library variable {text_locales} can be set to
# the set of supported locales.
#
{text_locales}: \
af_ZA \
ar_AE \
ar_BH \
ar_DZ \
ar_EG \
ar_IN \
ar_IQ \
ar_JO \
ar_KW \
ar_LB \
ar_LY \
ar_MA \
ar_OM \
ar_QA \
ar_SD \
ar_SY \
ar_TN \
ar_YE \
be_BY \
bn_IN \
br_FR \
bs_BA \
ca_ES \
cs_CZ \
cy_GB \
da_DK \
de \
de_AT \
de_BE \
de_CH \
de_DE \
de_LU \
el_GR \
en \
en_AU \
en_BW \
en_CA \
en_DK \
en_GB \
en_HK \
en_IE \
en_IN \
en_NZ \
en_PH \
en_SG \
en_US \
en_ZA \
en_ZW \
es_AR \
es_BO \
es_CL \
es_CO \
es_CR \
es_DO \
es_EC \
es_ES \
es_GT \
es_HN \
es_MX \
es_NI \
es_PA \
es_PE \
es_PR \
es_PY \
es_SV \
es_US \
es_UY \
es_VE \
et_EE \
eu_ES \
fa_IR \
fi_FI \
fo_FO \
fr_BE \
fr_CA \
fr_CH \
fr_FR \
fr_LU \
ga_IE \
gd_GB \
gl_ES \
gv_GB \
he_IL \
hi_IN \
hr_HR \
hu_HU \
id_ID \
it_CH \
it_IT \
iw_IL \
ja_JP \
ka_GE \
kl_GL \
ko_KR \
kw_GB \
lt_LT \
lv_LV \
mi_NZ \
mk_MK \
mr_IN \
mt_MT \
nl \
nl_BE \
nl_NL \
nn_NO \
no_NO \
oc_FR \
pl_PL \
pt_BR \
pt_PT \
ro_RO \
ru_RU \
ru_UA \
se_NO \
sk_SK \
sl_SI \
sq_AL \
sr_YU \
sv_FI \
sv_SE \
ta_IN \
te_IN \
tg_TJ \
tl_PH \
tr_TR \
uk_UA \
ur_PK \
uz_UZ \
vi_VN \
yi_US \
zh_CN \
zh_HK \
zh_SG \
zh_TW
java/text/Collator.getInstance(Ljava/util/Locale;)Ljava/text/Collator;: \
gnu/java/locale/LocaleInformation_{text_locales}.*
java/text/DateFormatSymbols.<init>(Ljava/util/Locale;)V: \
gnu/java/locale/LocaleInformation_{text_locales}.*
java/text/DecimalFormatSymbols.<init>(Ljava/util/Locale;)V: \
gnu/java/locale/LocaleInformation_{text_locales}.*
java/text/BreakIterator.getInstance(Ljava/lang/String;Ljava/util/Locale;)Ljava/text/BreakIterator;: \
gnu/java/locale/LocaleInformation_{text_locales}.*
java/text/NumberFormat.computeInstance(Ljava/util/Locale;Ljava/lang/String;Ljava/lang/String;)Ljava/text/NumberFormat;: \
gnu/java/locale/LocaleInformation_{text_locales}.*
java/text/DateFormat.computeInstance(IILjava/util/Locale;ZZ)Ljava/text/DateFormat;: \
gnu/java/locale/LocaleInformation_{text_locales}.*
+47
View File
@@ -0,0 +1,47 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!-- package.html - describes classes in java.text package.
Copyright (C) 2002 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. -->
<html>
<head><title>GNU Classpath - java.text</title></head>
<body>
<p>Classes to iterate over strings and to format texts according to a
specific locale.</p>
</body>
</html>