/* InternationalFormatter.java --
Copyright (C) 2005, 2006  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 javax.swing.text;

import java.text.AttributedCharacterIterator;
import java.text.Format;
import java.text.ParseException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.swing.Action;
import javax.swing.JFormattedTextField;

/**
 * This extends {@link DefaultFormatter} so that the value to string
 * conversion is done via a {@link Format} object. This allows
 * various additional formats to be handled by JFormattedField.
 *
 * @author Roman Kennke (roman@kennke.org)
 */
public class InternationalFormatter
  extends DefaultFormatter
{
  /** The serialization UID (compatible with JDK1.5). */
  private static final long serialVersionUID = 2436068675711756856L;

  /** The format that handles value to string conversion. */
  Format format;

  /** The minimal permissable value. */
  Comparable minimum;

  /** The maximal permissable value. */
  Comparable maximum;

  /**
   * Creates a new InternationalFormatter with no Format specified.
   */
  public InternationalFormatter()
  {
    super();
    minimum = null;
    maximum = null;
    format = null;
    setCommitsOnValidEdit(false);
    setOverwriteMode(false);
  }

  /**
   * Creates a new InternationalFormatter that uses the specified
   * Format object for value to string conversion.
   *
   * @param format the Format object to use for value to string conversion
   */
  public InternationalFormatter(Format format)
  {
    this();
    setFormat(format);
  }

  /**
   * Sets the Format object that is used to convert values to strings.
   *
   * @param format the Format to use for value to string conversion
   *
   * @see Format
   */
  public void setFormat(Format format)
  {
    this.format = format;
  }

  /**
   * Returns the currently used Format object that is used to format
   * the JFormattedField.
   *
   * @return the current Format
   */
  public Format getFormat()
  {
    return format;
  }

  /**
   * Sets the minimum value that is allowed by this Formatter. The minimum
   * value is given as an object that implements the {@link Comparable}
   * interface.
   *
   * If <code>minValue</code> is null, then the Formatter has no restrictions
   * at the lower end.
   *
   * If value class is not yet specified and <code>minValue</code> is not
   * null, then <code>valueClass</code> is set to the class of the minimum
   * value.
   *
   * @param minValue the minimum permissable value
   *
   * @see Comparable
   */
  public void setMinimum(Comparable minValue)
  {
    minimum = minValue;
    if (valueClass == null && minValue != null)
      valueClass = minValue.getClass();
  }

  /**
   * Returns the minimal value that is allowed by this Formatter.
   *
   * A <code>null</code> value means that there is no restriction.
   *
   * @return the minimal value that is allowed by this Formatter or
   *     <code>null</code> if there is no restriction
   */
  public Comparable getMinimum()
  {
    return minimum;
  }

  /**
   * Sets the maximum value that is allowed by this Formatter. The maximum
   * value is given as an object that implements the {@link Comparable}
   * interface.
   *
   * If <code>maxValue</code> is null, then the Formatter has no restrictions
   * at the upper end.
   *
   * If value class is not yet specified and <code>maxValue</code> is not
   * null, then <code>valueClass</code> is set to the class of the maximum
   * value.
   *
   * @param maxValue the maximum permissable value
   *
   * @see Comparable
   */
  public void setMaximum(Comparable maxValue)
  {
    maximum = maxValue;
    if (valueClass == null && maxValue != null)
      valueClass = maxValue.getClass();
  }

  /**
   * Returns the maximal value that is allowed by this Formatter.
   *
   * A <code>null</code> value means that there is no restriction.
   *
   * @return the maximal value that is allowed by this Formatter or
   *     <code>null</code> if there is no restriction
   */
  public Comparable getMaximum()
  {
    return maximum;
  }

  /**
   * Installs the formatter on the specified {@link JFormattedTextField}.
   *
   * This method does the following things:
   * <ul>
   * <li>Display the value of #valueToString in the
   *  <code>JFormattedTextField</code></li>
   * <li>Install the Actions from #getActions on the <code>JTextField</code>
   * </li>
   * <li>Install the DocumentFilter returned by #getDocumentFilter</li>
   * <li>Install the NavigationFilter returned by #getNavigationFilter</li>
   * </ul>
   *
   * This method is typically not overridden by subclasses. Instead override
   * one of the mentioned methods in order to customize behaviour.
   *
   * @param ftf the {@link JFormattedTextField} in which this formatter
   *     is installed
   */
  public void install(JFormattedTextField ftf)
  {
    super.install(ftf);
  }

  /**
   * Converts a value object into a String. This is done by invoking
   * {@link Format#format(Object)} on the specified <code>Format</code> object.
   * If no format is set, then {@link DefaultFormatter#valueToString(Object)}
   * is called as a fallback.
   *
   * @param value the value to be converted
   *
   * @return the string representation of the value
   *
   * @throws ParseException if the value cannot be converted
   */
  public String valueToString(Object value)
    throws ParseException
  {
    if (value == null)
      return "";
    if (format != null)
      return format.format(value);
    else
      return super.valueToString(value);
  }

  /**
   * Converts a String (from the JFormattedTextField input) to a value.
   * This is achieved by invoking {@link Format#parseObject(String)} on
   * the specified <code>Format</code> object.
   *
   * This implementation differs slightly from {@link DefaultFormatter},
   * it does:
   * <ol>
   * <li>Convert the string to an <code>Object</code> using the
   *   <code>Formatter</code>.</li>
   * <li>If a <code>valueClass</code> has been set, this object is passed to
   *   {@link DefaultFormatter#stringToValue(String)} so that the value
   *   has the correct type. This may or may not work correctly, depending on
   *   the implementation of toString() in the value class and if the class
   *   implements a constructor that takes one String as argument.</li>
   * <li>If no {@link ParseException} has been thrown so far, we check if the
   *   value exceeds either <code>minimum</code> or <code>maximum</code> if
   *   one of those has been specified and throw a <code>ParseException</code>
   *   if it does.</li>
   * <li>Return the value.</li>
   * </ol>
   *
   * If no format has been specified, then
   * {@link DefaultFormatter#stringToValue(String)} is invoked as fallback.
   *
   * @param string the string to convert
   *
   * @return the value for the string
   *
   * @throws ParseException if the string cannot be converted into
   *     a value object (e.g. invalid input)
   */
  public Object stringToValue(String string)
    throws ParseException
  {
    if (format != null)
      {
        Object o = format.parseObject(string);

        // If a value class has been set, call super in order to get
        // the class right. That is what the JDK API docs suggest, so we do
        // it that way.
        if (valueClass != null)
          o = super.stringToValue(o.toString());

        // Check for minimum and maximum bounds
        if (minimum != null && minimum.compareTo(o) > 0)
          throw new ParseException("The value may not be less than the"
                                    + " specified minimum", 0);
        if (maximum != null && maximum.compareTo(o) < 0)
          throw new ParseException("The value may not be greater than the"
                                    + " specified maximum", 0);
        return o;
      }
    else
      return super.stringToValue(string);
  }

  /**
   * Returns the {@link Format.Field} constants that are associated with
   * the specified position in the text.
   *
   * If <code>offset</code> is not a valid location in the input field,
   * an empty array of fields is returned.
   *
   * @param offset the position in the text from which we want to fetch
   *     the fields constants
   *
   * @return the field values associated with the specified position in
   *     the text
   */
  public Format.Field[] getFields(int offset)
  {
    // TODO: don't know if this is correct
    AttributedCharacterIterator aci = format.formatToCharacterIterator
                                         (getFormattedTextField().getValue());
    aci.setIndex(offset);
    Map atts = aci.getAttributes();
    Set keys = atts.keySet();
    Format.Field[] fields = new Format.Field[keys.size()];
    int index = 0;
    for (Iterator i = keys.iterator(); i.hasNext(); index++)
      fields[index] = (Format.Field) i.next();
    return fields;
  }

  /**
   * This creates and returns a clone of this Formatter.
   *
   * @return a clone of this formatter
   *
   * @throws CloneNotSupportedException not thrown here, since cloning is
   *     supported
   */
  public Object clone()
    throws CloneNotSupportedException
  {
    // TODO: it has to be considered, if we should return a deep or shallow
    // clone here. for now we return a shallow clone
    Object clone = super.clone();
    return clone;
  }

  /**
   * Returns the Actions that are supported by this Formatter.
   *
   * @specnote the JDK API docs say here: <cite>If
   *     <code>getSupportsIncrement</code> returns true, this returns two
   *     Actions suitable for incrementing/decrementing the value.</cite>
   *     The questsion is, which method <code>getSupportsIncrement</code>?
   *     There is no such method in the whole API! So we just call
   *     super.getActions here.
   */
  protected Action[] getActions()
  {
    return super.getActions();
  }
}
