/*
 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package javax.swing;

import java.awt.*;
import java.awt.event.*;
import java.awt.im.InputContext;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.swing.UIManager;
import javax.swing.event.*;
import javax.swing.plaf.UIResource;
import javax.swing.text.*;

/**
 * <code>JFormattedTextField</code> extends <code>JTextField</code> adding
 * support for formatting arbitrary values, as well as retrieving a particular
 * object once the user has edited the text. The following illustrates
 * configuring a <code>JFormattedTextField</code> to edit dates:
 * <pre>
 *   JFormattedTextField ftf = new JFormattedTextField();
 *   ftf.setValue(new Date());
 * </pre>
 * <p>
 * Once a <code>JFormattedTextField</code> has been created, you can
 * listen for editing changes by way of adding
 * a <code>PropertyChangeListener</code> and listening for
 * <code>PropertyChangeEvent</code>s with the property name <code>value</code>.
 * <p>
 * <code>JFormattedTextField</code> allows
 * configuring what action should be taken when focus is lost. The possible
 * configurations are:
 * <table summary="Possible JFormattedTextField configurations and their descriptions">
 * <tr><th><p align="left">Value</p></th><th><p align="left">Description</p></th></tr>
 * <tr><td>JFormattedTextField.REVERT
 *            <td>Revert the display to match that of <code>getValue</code>,
 *                possibly losing the current edit.
 *        <tr><td>JFormattedTextField.COMMIT
 *            <td>Commits the current value. If the value being edited
 *                isn't considered a legal value by the
 *                <code>AbstractFormatter</code> that is, a
 *                <code>ParseException</code> is thrown, then the value
 *                will not change, and then edited value will persist.
 *        <tr><td>JFormattedTextField.COMMIT_OR_REVERT
 *            <td>Similar to <code>COMMIT</code>, but if the value isn't
 *                legal, behave like <code>REVERT</code>.
 *        <tr><td>JFormattedTextField.PERSIST
 *            <td>Do nothing, don't obtain a new
 *                <code>AbstractFormatter</code>, and don't update the value.
 * </table>
 * The default is <code>JFormattedTextField.COMMIT_OR_REVERT</code>,
 * refer to {@link #setFocusLostBehavior} for more information on this.
 * <p>
 * <code>JFormattedTextField</code> allows the focus to leave, even if
 * the currently edited value is invalid. To lock the focus down while the
 * <code>JFormattedTextField</code> is an invalid edit state
 * you can attach an <code>InputVerifier</code>. The following code snippet
 * shows a potential implementation of such an <code>InputVerifier</code>:
 * <pre>
 * public class FormattedTextFieldVerifier extends InputVerifier {
 *     public boolean verify(JComponent input) {
 *         if (input instanceof JFormattedTextField) {
 *             JFormattedTextField ftf = (JFormattedTextField)input;
 *             AbstractFormatter formatter = ftf.getFormatter();
 *             if (formatter != null) {
 *                 String text = ftf.getText();
 *                 try {
 *                      formatter.stringToValue(text);
 *                      return true;
 *                  } catch (ParseException pe) {
 *                      return false;
 *                  }
 *              }
 *          }
 *          return true;
 *      }
 *      public boolean shouldYieldFocus(JComponent input) {
 *          return verify(input);
 *      }
 *  }
 * </pre>
 * <p>
 * Alternatively, you could invoke <code>commitEdit</code>, which would also
 * commit the value.
 * <p>
 * <code>JFormattedTextField</code> does not do the formatting it self,
 * rather formatting is done through an instance of
 * <code>JFormattedTextField.AbstractFormatter</code> which is obtained from
 * an instance of <code>JFormattedTextField.AbstractFormatterFactory</code>.
 * Instances of <code>JFormattedTextField.AbstractFormatter</code> are
 * notified when they become active by way of the
 * <code>install</code> method, at which point the
 * <code>JFormattedTextField.AbstractFormatter</code> can install whatever
 * it needs to, typically a <code>DocumentFilter</code>. Similarly when
 * <code>JFormattedTextField</code> no longer
 * needs the <code>AbstractFormatter</code>, it will invoke
 * <code>uninstall</code>.
 * <p>
 * <code>JFormattedTextField</code> typically
 * queries the <code>AbstractFormatterFactory</code> for an
 * <code>AbstractFormat</code> when it gains or loses focus. Although this
 * can change based on the focus lost policy. If the focus lost
 * policy is <code>JFormattedTextField.PERSIST</code>
 * and the <code>JFormattedTextField</code> has been edited, the
 * <code>AbstractFormatterFactory</code> will not be queried until the
 * value has been commited. Similarly if the focus lost policy is
 * <code>JFormattedTextField.COMMIT</code> and an exception
 * is thrown from <code>stringToValue</code>, the
 * <code>AbstractFormatterFactory</code> will not be querired when focus is
 * lost or gained.
 * <p>
 * <code>JFormattedTextField.AbstractFormatter</code>
 * is also responsible for determining when values are commited to
 * the <code>JFormattedTextField</code>. Some
 * <code>JFormattedTextField.AbstractFormatter</code>s will make new values
 * available on every edit, and others will never commit the value. You can
 * force the current value to be obtained
 * from the current <code>JFormattedTextField.AbstractFormatter</code>
 * by way of invoking <code>commitEdit</code>. <code>commitEdit</code> will
 * be invoked whenever return is pressed in the
 * <code>JFormattedTextField</code>.
 * <p>
 * If an <code>AbstractFormatterFactory</code> has not been explicitly
 * set, one will be set based on the <code>Class</code> of the value type after
 * <code>setValue</code> has been invoked (assuming value is non-null).
 * For example, in the following code an appropriate
 * <code>AbstractFormatterFactory</code> and <code>AbstractFormatter</code>
 * will be created to handle formatting of numbers:
 * <pre>
 *   JFormattedTextField tf = new JFormattedTextField();
 *   tf.setValue(new Number(100));
 * </pre>
 * <p>
 * <strong>Warning:</strong> As the <code>AbstractFormatter</code> will
 * typically install a <code>DocumentFilter</code> on the
 * <code>Document</code>, and a <code>NavigationFilter</code> on the
 * <code>JFormattedTextField</code> you should not install your own. If you do,
 * you are likely to see odd behavior in that the editing policy of the
 * <code>AbstractFormatter</code> will not be enforced.
 * <p>
 * <strong>Warning:</strong> Swing is not thread safe. For more
 * information see <a
 * href="package-summary.html#threading">Swing's Threading
 * Policy</a>.
 * <p>
 * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases. The current serialization support is
 * appropriate for short term storage or RMI between applications running
 * the same version of Swing.  As of 1.4, support for long term storage
 * of all JavaBeans<sup><font size="-2">TM</font></sup>
 * has been added to the <code>java.beans</code> package.
 * Please see {@link java.beans.XMLEncoder}.
 *
 * @since 1.4
 */
public class JFormattedTextField extends JTextField {
    private static final String uiClassID = "FormattedTextFieldUI";
    private static final Action[] defaultActions =
            { new CommitAction(), new CancelAction() };

    /**
     * Constant identifying that when focus is lost,
     * <code>commitEdit</code> should be invoked. If in commiting the
     * new value a <code>ParseException</code> is thrown, the invalid
     * value will remain.
     *
     * @see #setFocusLostBehavior
     */
    public static final int COMMIT = 0;

    /**
     * Constant identifying that when focus is lost,
     * <code>commitEdit</code> should be invoked. If in commiting the new
     * value a <code>ParseException</code> is thrown, the value will be
     * reverted.
     *
     * @see #setFocusLostBehavior
     */
    public static final int COMMIT_OR_REVERT = 1;

    /**
     * Constant identifying that when focus is lost, editing value should
     * be reverted to current value set on the
     * <code>JFormattedTextField</code>.
     *
     * @see #setFocusLostBehavior
     */
    public static final int REVERT = 2;

    /**
     * Constant identifying that when focus is lost, the edited value
     * should be left.
     *
     * @see #setFocusLostBehavior
     */
    public static final int PERSIST = 3;


    /**
     * Factory used to obtain an instance of AbstractFormatter.
     */
    private AbstractFormatterFactory factory;
    /**
     * Object responsible for formatting the current value.
     */
    private AbstractFormatter format;
    /**
     * Last valid value.
     */
    private Object value;
    /**
     * True while the value being edited is valid.
     */
    private boolean editValid;
    /**
     * Behavior when focus is lost.
     */
    private int focusLostBehavior;
    /**
     * Indicates the current value has been edited.
     */
    private boolean edited;
    /**
     * Used to set the dirty state.
     */
    private DocumentListener documentListener;
    /**
     * Masked used to set the AbstractFormatterFactory.
     */
    private Object mask;
    /**
     * ActionMap that the TextFormatter Actions are added to.
     */
    private ActionMap textFormatterActionMap;
    /**
     * Indicates the input method composed text is in the document
     */
    private boolean composedTextExists = false;
    /**
     * A handler for FOCUS_LOST event
     */
    private FocusLostHandler focusLostHandler;


    /**
     * Creates a <code>JFormattedTextField</code> with no
     * <code>AbstractFormatterFactory</code>. Use <code>setMask</code> or
     * <code>setFormatterFactory</code> to configure the
     * <code>JFormattedTextField</code> to edit a particular type of
     * value.
     */
    public JFormattedTextField() {
        super();
        enableEvents(AWTEvent.FOCUS_EVENT_MASK);
        setFocusLostBehavior(COMMIT_OR_REVERT);
    }

    /**
     * Creates a JFormattedTextField with the specified value. This will
     * create an <code>AbstractFormatterFactory</code> based on the
     * type of <code>value</code>.
     *
     * @param value Initial value for the JFormattedTextField
     */
    public JFormattedTextField(Object value) {
        this();
        setValue(value);
    }

    /**
     * Creates a <code>JFormattedTextField</code>. <code>format</code> is
     * wrapped in an appropriate <code>AbstractFormatter</code> which is
     * then wrapped in an <code>AbstractFormatterFactory</code>.
     *
     * @param format Format used to look up an AbstractFormatter
     */
    public JFormattedTextField(java.text.Format format) {
        this();
        setFormatterFactory(getDefaultFormatterFactory(format));
    }

    /**
     * Creates a <code>JFormattedTextField</code> with the specified
     * <code>AbstractFormatter</code>. The <code>AbstractFormatter</code>
     * is placed in an <code>AbstractFormatterFactory</code>.
     *
     * @param formatter AbstractFormatter to use for formatting.
     */
    public JFormattedTextField(AbstractFormatter formatter) {
        this(new DefaultFormatterFactory(formatter));
    }

    /**
     * Creates a <code>JFormattedTextField</code> with the specified
     * <code>AbstractFormatterFactory</code>.
     *
     * @param factory AbstractFormatterFactory used for formatting.
     */
    public JFormattedTextField(AbstractFormatterFactory factory) {
        this();
        setFormatterFactory(factory);
    }

    /**
     * Creates a <code>JFormattedTextField</code> with the specified
     * <code>AbstractFormatterFactory</code> and initial value.
     *
     * @param factory <code>AbstractFormatterFactory</code> used for
     *        formatting.
     * @param currentValue Initial value to use
     */
    public JFormattedTextField(AbstractFormatterFactory factory,
                               Object currentValue) {
        this(currentValue);
        setFormatterFactory(factory);
    }

    /**
     * Sets the behavior when focus is lost. This will be one of
     * <code>JFormattedTextField.COMMIT_OR_REVERT</code>,
     * <code>JFormattedTextField.REVERT</code>,
     * <code>JFormattedTextField.COMMIT</code> or
     * <code>JFormattedTextField.PERSIST</code>
     * Note that some <code>AbstractFormatter</code>s may push changes as
     * they occur, so that the value of this will have no effect.
     * <p>
     * This will throw an <code>IllegalArgumentException</code> if the object
     * passed in is not one of the afore mentioned values.
     * <p>
     * The default value of this property is
     * <code>JFormattedTextField.COMMIT_OR_REVERT</code>.
     *
     * @param behavior Identifies behavior when focus is lost
     * @throws IllegalArgumentException if behavior is not one of the known
     *         values
     * @beaninfo
     *  enum: COMMIT         JFormattedTextField.COMMIT
     *        COMMIT_OR_REVERT JFormattedTextField.COMMIT_OR_REVERT
     *        REVERT         JFormattedTextField.REVERT
     *        PERSIST        JFormattedTextField.PERSIST
     *  description: Behavior when component loses focus
     */
    public void setFocusLostBehavior(int behavior) {
        if (behavior != COMMIT && behavior != COMMIT_OR_REVERT &&
            behavior != PERSIST && behavior != REVERT) {
            throw new IllegalArgumentException("setFocusLostBehavior must be one of: JFormattedTextField.COMMIT, JFormattedTextField.COMMIT_OR_REVERT, JFormattedTextField.PERSIST or JFormattedTextField.REVERT");
        }
        focusLostBehavior = behavior;
    }

    /**
     * Returns the behavior when focus is lost. This will be one of
     * <code>COMMIT_OR_REVERT</code>,
     * <code>COMMIT</code>,
     * <code>REVERT</code> or
     * <code>PERSIST</code>
     * Note that some <code>AbstractFormatter</code>s may push changes as
     * they occur, so that the value of this will have no effect.
     *
     * @return returns behavior when focus is lost
     */
    public int getFocusLostBehavior() {
        return focusLostBehavior;
    }

    /**
     * Sets the <code>AbstractFormatterFactory</code>.
     * <code>AbstractFormatterFactory</code> is
     * able to return an instance of <code>AbstractFormatter</code> that is
     * used to format a value for display, as well an enforcing an editing
     * policy.
     * <p>
     * If you have not explicitly set an <code>AbstractFormatterFactory</code>
     * by way of this method (or a constructor) an
     * <code>AbstractFormatterFactory</code> and consequently an
     * <code>AbstractFormatter</code> will be used based on the
     * <code>Class</code> of the value. <code>NumberFormatter</code> will
     * be used for <code>Number</code>s, <code>DateFormatter</code> will
     * be used for <code>Dates</code>, otherwise <code>DefaultFormatter</code>
     * will be used.
     * <p>
     * This is a JavaBeans bound property.
     *
     * @param tf <code>AbstractFormatterFactory</code> used to lookup
     *          instances of <code>AbstractFormatter</code>
     * @beaninfo
     *       bound: true
     *   attribute: visualUpdate true
     * description: AbstractFormatterFactory, responsible for returning an
     *              AbstractFormatter that can format the current value.
     */
    public void setFormatterFactory(AbstractFormatterFactory tf) {
        AbstractFormatterFactory oldFactory = factory;

        factory = tf;
        firePropertyChange("formatterFactory", oldFactory, tf);
        setValue(getValue(), true, false);
    }

    /**
     * Returns the current <code>AbstractFormatterFactory</code>.
     *
     * @see #setFormatterFactory
     * @return <code>AbstractFormatterFactory</code> used to determine
     *         <code>AbstractFormatter</code>s
     */
    public AbstractFormatterFactory getFormatterFactory() {
        return factory;
    }

    /**
     * Sets the current <code>AbstractFormatter</code>.
     * <p>
     * You should not normally invoke this, instead set the
     * <code>AbstractFormatterFactory</code> or set the value.
     * <code>JFormattedTextField</code> will
     * invoke this as the state of the <code>JFormattedTextField</code>
     * changes and requires the value to be reset.
     * <code>JFormattedTextField</code> passes in the
     * <code>AbstractFormatter</code> obtained from the
     * <code>AbstractFormatterFactory</code>.
     * <p>
     * This is a JavaBeans bound property.
     *
     * @see #setFormatterFactory
     * @param format AbstractFormatter to use for formatting
     * @beaninfo
     *       bound: true
     *   attribute: visualUpdate true
     * description: TextFormatter, responsible for formatting the current value
     */
    protected void setFormatter(AbstractFormatter format) {
        AbstractFormatter oldFormat = this.format;

        if (oldFormat != null) {
            oldFormat.uninstall();
        }
        setEditValid(true);
        this.format = format;
        if (format != null) {
            format.install(this);
        }
        setEdited(false);
        firePropertyChange("textFormatter", oldFormat, format);
    }

    /**
     * Returns the <code>AbstractFormatter</code> that is used to format and
     * parse the current value.
     *
     * @return AbstractFormatter used for formatting
     */
    public AbstractFormatter getFormatter() {
        return format;
    }

    /**
     * Sets the value that will be formatted by an
     * <code>AbstractFormatter</code> obtained from the current
     * <code>AbstractFormatterFactory</code>. If no
     * <code>AbstractFormatterFactory</code> has been specified, this will
     * attempt to create one based on the type of <code>value</code>.
     * <p>
     * The default value of this property is null.
     * <p>
     * This is a JavaBeans bound property.
     *
     * @param value Current value to display
     * @beaninfo
     *       bound: true
     *   attribute: visualUpdate true
     * description: The value to be formatted.
     */
    public void setValue(Object value) {
        if (value != null && getFormatterFactory() == null) {
            setFormatterFactory(getDefaultFormatterFactory(value));
        }
        setValue(value, true, true);
    }

    /**
     * Returns the last valid value. Based on the editing policy of
     * the <code>AbstractFormatter</code> this may not return the current
     * value. The currently edited value can be obtained by invoking
     * <code>commitEdit</code> followed by <code>getValue</code>.
     *
     * @return Last valid value
     */
    public Object getValue() {
        return value;
    }

    /**
     * Forces the current value to be taken from the
     * <code>AbstractFormatter</code> and set as the current value.
     * This has no effect if there is no current
     * <code>AbstractFormatter</code> installed.
     *
     * @throws ParseException if the <code>AbstractFormatter</code> is not able
     *         to format the current value
     */
    public void commitEdit() throws ParseException {
        AbstractFormatter format = getFormatter();

        if (format != null) {
            setValue(format.stringToValue(getText()), false, true);
        }
    }

    /**
     * Sets the validity of the edit on the receiver. You should not normally
     * invoke this. This will be invoked by the
     * <code>AbstractFormatter</code> as the user edits the value.
     * <p>
     * Not all formatters will allow the component to get into an invalid
     * state, and thus this may never be invoked.
     * <p>
     * Based on the look and feel this may visually change the state of
     * the receiver.
     *
     * @param isValid boolean indicating if the currently edited value is
     *        valid.
     * @beaninfo
     *       bound: true
     *   attribute: visualUpdate true
     * description: True indicates the edited value is valid
     */
    private void setEditValid(boolean isValid) {
        if (isValid != editValid) {
            editValid = isValid;
            firePropertyChange("editValid", Boolean.valueOf(!isValid),
                               Boolean.valueOf(isValid));
        }
    }

    /**
     * Returns true if the current value being edited is valid. The value of
     * this is managed by the current <code>AbstractFormatter</code>, as such
     * there is no public setter for it.
     *
     * @return true if the current value being edited is valid.
     */
    public boolean isEditValid() {
        return editValid;
    }

    /**
     * Invoked when the user inputs an invalid value. This gives the
     * component a chance to provide feedback. The default
     * implementation beeps.
     */
    protected void invalidEdit() {
        UIManager.getLookAndFeel().provideErrorFeedback(JFormattedTextField.this);
    }

    /**
     * Processes any input method events, such as
     * <code>InputMethodEvent.INPUT_METHOD_TEXT_CHANGED</code> or
     * <code>InputMethodEvent.CARET_POSITION_CHANGED</code>.
     *
     * @param e the <code>InputMethodEvent</code>
     * @see InputMethodEvent
     */
    protected void processInputMethodEvent(InputMethodEvent e) {
        AttributedCharacterIterator text = e.getText();
        int commitCount = e.getCommittedCharacterCount();

        // Keep track of the composed text
        if (text != null) {
            int begin = text.getBeginIndex();
            int end = text.getEndIndex();
            composedTextExists = ((end - begin) > commitCount);
        } else {
            composedTextExists = false;
        }

        super.processInputMethodEvent(e);
    }

    /**
     * Processes any focus events, such as
     * <code>FocusEvent.FOCUS_GAINED</code> or
     * <code>FocusEvent.FOCUS_LOST</code>.
     *
     * @param e the <code>FocusEvent</code>
     * @see FocusEvent
     */
    protected void processFocusEvent(FocusEvent e) {
        super.processFocusEvent(e);

        // ignore temporary focus event
        if (e.isTemporary()) {
            return;
        }

        if (isEdited() && e.getID() == FocusEvent.FOCUS_LOST) {
            InputContext ic = getInputContext();
            if (focusLostHandler == null) {
                focusLostHandler = new FocusLostHandler();
            }

            // if there is a composed text, process it first
            if ((ic != null) && composedTextExists) {
                ic.endComposition();
                EventQueue.invokeLater(focusLostHandler);
            } else {
                focusLostHandler.run();
            }
        }
        else if (!isEdited()) {
            // reformat
            setValue(getValue(), true, true);
        }
    }

    /**
     * FOCUS_LOST behavior implementation
     */
    private class FocusLostHandler implements Runnable, Serializable {
        public void run() {
            int fb = JFormattedTextField.this.getFocusLostBehavior();
            if (fb == JFormattedTextField.COMMIT ||
                fb == JFormattedTextField.COMMIT_OR_REVERT) {
                try {
                    JFormattedTextField.this.commitEdit();
                    // Give it a chance to reformat.
                    JFormattedTextField.this.setValue(
                        JFormattedTextField.this.getValue(), true, true);
                } catch (ParseException pe) {
                    if (fb == JFormattedTextField.this.COMMIT_OR_REVERT) {
                        JFormattedTextField.this.setValue(
                            JFormattedTextField.this.getValue(), true, true);
                    }
                }
            }
            else if (fb == JFormattedTextField.REVERT) {
                JFormattedTextField.this.setValue(
                    JFormattedTextField.this.getValue(), true, true);
            }
        }
    }

    /**
     * Fetches the command list for the editor.  This is
     * the list of commands supported by the plugged-in UI
     * augmented by the collection of commands that the
     * editor itself supports.  These are useful for binding
     * to events, such as in a keymap.
     *
     * @return the command list
     */
    public Action[] getActions() {
        return TextAction.augmentList(super.getActions(), defaultActions);
    }

    /**
     * Gets the class ID for a UI.
     *
     * @return the string "FormattedTextFieldUI"
     * @see JComponent#getUIClassID
     */
    public String getUIClassID() {
        return uiClassID;
    }

    /**
     * Associates the editor with a text document.
     * The currently registered factory is used to build a view for
     * the document, which gets displayed by the editor after revalidation.
     * A PropertyChange event ("document") is propagated to each listener.
     *
     * @param doc  the document to display/edit
     * @see #getDocument
     * @beaninfo
     *  description: the text document model
     *        bound: true
     *       expert: true
     */
    public void setDocument(Document doc) {
        if (documentListener != null && getDocument() != null) {
            getDocument().removeDocumentListener(documentListener);
        }
        super.setDocument(doc);
        if (documentListener == null) {
            documentListener = new DocumentHandler();
        }
        doc.addDocumentListener(documentListener);
    }

    /*
     * See readObject and writeObject in JComponent for more
     * information about serialization in Swing.
     *
     * @param s Stream to write to
     */
    private void writeObject(ObjectOutputStream s) throws IOException {
        s.defaultWriteObject();
        if (getUIClassID().equals(uiClassID)) {
            byte count = JComponent.getWriteObjCounter(this);
            JComponent.setWriteObjCounter(this, --count);
            if (count == 0 && ui != null) {
                ui.installUI(this);
            }
        }
    }

    /**
     * Resets the Actions that come from the TextFormatter to
     * <code>actions</code>.
     */
    private void setFormatterActions(Action[] actions) {
        if (actions == null) {
            if (textFormatterActionMap != null) {
                textFormatterActionMap.clear();
            }
        }
        else {
            if (textFormatterActionMap == null) {
                ActionMap map = getActionMap();

                textFormatterActionMap = new ActionMap();
                while (map != null) {
                    ActionMap parent = map.getParent();

                    if (parent instanceof UIResource || parent == null) {
                        map.setParent(textFormatterActionMap);
                        textFormatterActionMap.setParent(parent);
                        break;
                    }
                    map = parent;
                }
            }
            for (int counter = actions.length - 1; counter >= 0;
                 counter--) {
                Object key = actions[counter].getValue(Action.NAME);

                if (key != null) {
                    textFormatterActionMap.put(key, actions[counter]);
                }
            }
        }
    }

    /**
     * Does the setting of the value. If <code>createFormat</code> is true,
     * this will also obtain a new <code>AbstractFormatter</code> from the
     * current factory. The property change event will be fired if
     * <code>firePC</code> is true.
     */
    private void setValue(Object value, boolean createFormat, boolean firePC) {
        Object oldValue = this.value;

        this.value = value;

        if (createFormat) {
            AbstractFormatterFactory factory = getFormatterFactory();
            AbstractFormatter atf;

            if (factory != null) {
                atf = factory.getFormatter(this);
            }
            else {
                atf = null;
            }
            setFormatter(atf);
        }
        else {
            // Assumed to be valid
            setEditValid(true);
        }

        setEdited(false);

        if (firePC) {
            firePropertyChange("value", oldValue, value);
        }
    }

    /**
     * Sets the edited state of the receiver.
     */
    private void setEdited(boolean edited) {
        this.edited = edited;
    }

    /**
     * Returns true if the receiver has been edited.
     */
    private boolean isEdited() {
        return edited;
    }

    /**
     * Returns an AbstractFormatterFactory suitable for the passed in
     * Object type.
     */
    private AbstractFormatterFactory getDefaultFormatterFactory(Object type) {
        if (type instanceof DateFormat) {
            return new DefaultFormatterFactory(new DateFormatter
                                               ((DateFormat)type));
        }
        if (type instanceof NumberFormat) {
            return new DefaultFormatterFactory(new NumberFormatter(
                                               (NumberFormat)type));
        }
        if (type instanceof Format) {
            return new DefaultFormatterFactory(new InternationalFormatter(
                                               (Format)type));
        }
        if (type instanceof Date) {
            return new DefaultFormatterFactory(new DateFormatter());
        }
        if (type instanceof Number) {
            AbstractFormatter displayFormatter = new NumberFormatter();
            ((NumberFormatter)displayFormatter).setValueClass(type.getClass());
            AbstractFormatter editFormatter = new NumberFormatter(
                                  new DecimalFormat("#.#"));
            ((NumberFormatter)editFormatter).setValueClass(type.getClass());

            return new DefaultFormatterFactory(displayFormatter,
                                               displayFormatter,editFormatter);
        }
        return new DefaultFormatterFactory(new DefaultFormatter());
    }


    /**
     * Instances of <code>AbstractFormatterFactory</code> are used by
     * <code>JFormattedTextField</code> to obtain instances of
     * <code>AbstractFormatter</code> which in turn are used to format values.
     * <code>AbstractFormatterFactory</code> can return different
     * <code>AbstractFormatter</code>s based on the state of the
     * <code>JFormattedTextField</code>, perhaps returning different
     * <code>AbstractFormatter</code>s when the
     * <code>JFormattedTextField</code> has focus vs when it
     * doesn't have focus.
     * @since 1.4
     */
    public static abstract class AbstractFormatterFactory {
        /**
         * Returns an <code>AbstractFormatter</code> that can handle formatting
         * of the passed in <code>JFormattedTextField</code>.
         *
         * @param tf JFormattedTextField requesting AbstractFormatter
         * @return AbstractFormatter to handle formatting duties, a null
         *         return value implies the JFormattedTextField should behave
         *         like a normal JTextField
         */
        public abstract AbstractFormatter getFormatter(JFormattedTextField tf);
    }


    /**
     * Instances of <code>AbstractFormatter</code> are used by
     * <code>JFormattedTextField</code> to handle the conversion both
     * from an Object to a String, and back from a String to an Object.
     * <code>AbstractFormatter</code>s can also enfore editing policies,
     * or navigation policies, or manipulate the
     * <code>JFormattedTextField</code> in any way it sees fit to
     * enforce the desired policy.
     * <p>
     * An <code>AbstractFormatter</code> can only be active in
     * one <code>JFormattedTextField</code> at a time.
     * <code>JFormattedTextField</code> invokes
     * <code>install</code> when it is ready to use it followed
     * by <code>uninstall</code> when done. Subclasses
     * that wish to install additional state should override
     * <code>install</code> and message super appropriately.
     * <p>
     * Subclasses must override the conversion methods
     * <code>stringToValue</code> and <code>valueToString</code>. Optionally
     * they can override <code>getActions</code>,
     * <code>getNavigationFilter</code> and <code>getDocumentFilter</code>
     * to restrict the <code>JFormattedTextField</code> in a particular
     * way.
     * <p>
     * Subclasses that allow the <code>JFormattedTextField</code> to be in
     * a temporarily invalid state should invoke <code>setEditValid</code>
     * at the appropriate times.
     * @since 1.4
     */
    public static abstract class AbstractFormatter implements Serializable {
        private JFormattedTextField ftf;

        /**
         * Installs the <code>AbstractFormatter</code> onto a particular
         * <code>JFormattedTextField</code>.
         * This will invoke <code>valueToString</code> to convert the
         * current value from the <code>JFormattedTextField</code> to
         * a String. This will then install the <code>Action</code>s from
         * <code>getActions</code>, the <code>DocumentFilter</code>
         * returned from <code>getDocumentFilter</code> and the
         * <code>NavigationFilter</code> returned from
         * <code>getNavigationFilter</code> onto the
         * <code>JFormattedTextField</code>.
         * <p>
         * Subclasses will typically only need to override this if they
         * wish to install additional listeners on the
         * <code>JFormattedTextField</code>.
         * <p>
         * If there is a <code>ParseException</code> in converting the
         * current value to a String, this will set the text to an empty
         * String, and mark the <code>JFormattedTextField</code> as being
         * in an invalid state.
         * <p>
         * While this is a public method, this is typically only useful
         * for subclassers of <code>JFormattedTextField</code>.
         * <code>JFormattedTextField</code> will invoke this method at
         * the appropriate times when the value changes, or its internal
         * state changes.  You will only need to invoke this yourself if
         * you are subclassing <code>JFormattedTextField</code> and
         * installing/uninstalling <code>AbstractFormatter</code> at a
         * different time than <code>JFormattedTextField</code> does.
         *
         * @param ftf JFormattedTextField to format for, may be null indicating
         *            uninstall from current JFormattedTextField.
         */
        public void install(JFormattedTextField ftf) {
            if (this.ftf != null) {
                uninstall();
            }
            this.ftf = ftf;
            if (ftf != null) {
                try {
                    ftf.setText(valueToString(ftf.getValue()));
                } catch (ParseException pe) {
                    ftf.setText("");
                    setEditValid(false);
                }
                installDocumentFilter(getDocumentFilter());
                ftf.setNavigationFilter(getNavigationFilter());
                ftf.setFormatterActions(getActions());
            }
        }

        /**
         * Uninstalls any state the <code>AbstractFormatter</code> may have
         * installed on the <code>JFormattedTextField</code>. This resets the
         * <code>DocumentFilter</code>, <code>NavigationFilter</code>
         * and additional <code>Action</code>s installed on the
         * <code>JFormattedTextField</code>.
         */
        public void uninstall() {
            if (this.ftf != null) {
                installDocumentFilter(null);
                this.ftf.setNavigationFilter(null);
                this.ftf.setFormatterActions(null);
            }
        }

        /**
         * Parses <code>text</code> returning an arbitrary Object. Some
         * formatters may return null.
         *
         * @throws ParseException if there is an error in the conversion
         * @param text String to convert
         * @return Object representation of text
         */
        public abstract Object stringToValue(String text) throws
                                     ParseException;

        /**
         * Returns the string value to display for <code>value</code>.
         *
         * @throws ParseException if there is an error in the conversion
         * @param value Value to convert
         * @return String representation of value
         */
        public abstract String valueToString(Object value) throws
                        ParseException;

        /**
         * Returns the current <code>JFormattedTextField</code> the
         * <code>AbstractFormatter</code> is installed on.
         *
         * @return JFormattedTextField formatting for.
         */
        protected JFormattedTextField getFormattedTextField() {
            return ftf;
        }

        /**
         * This should be invoked when the user types an invalid character.
         * This forwards the call to the current JFormattedTextField.
         */
        protected void invalidEdit() {
            JFormattedTextField ftf = getFormattedTextField();

            if (ftf != null) {
                ftf.invalidEdit();
            }
        }

        /**
         * Invoke this to update the <code>editValid</code> property of the
         * <code>JFormattedTextField</code>. If you an enforce a policy
         * such that the <code>JFormattedTextField</code> is always in a
         * valid state, you will never need to invoke this.
         *
         * @param valid Valid state of the JFormattedTextField
         */
        protected void setEditValid(boolean valid) {
            JFormattedTextField ftf = getFormattedTextField();

            if (ftf != null) {
                ftf.setEditValid(valid);
            }
        }

        /**
         * Subclass and override if you wish to provide a custom set of
         * <code>Action</code>s. <code>install</code> will install these
         * on the <code>JFormattedTextField</code>'s <code>ActionMap</code>.
         *
         * @return Array of Actions to install on JFormattedTextField
         */
        protected Action[] getActions() {
            return null;
        }

        /**
         * Subclass and override if you wish to provide a
         * <code>DocumentFilter</code> to restrict what can be input.
         * <code>install</code> will install the returned value onto
         * the <code>JFormattedTextField</code>.
         *
         * @return DocumentFilter to restrict edits
         */
        protected DocumentFilter getDocumentFilter() {
            return null;
        }

        /**
         * Subclass and override if you wish to provide a filter to restrict
         * where the user can navigate to.
         * <code>install</code> will install the returned value onto
         * the <code>JFormattedTextField</code>.
         *
         * @return NavigationFilter to restrict navigation
         */
        protected NavigationFilter getNavigationFilter() {
            return null;
        }

        /**
         * Clones the <code>AbstractFormatter</code>. The returned instance
         * is not associated with a <code>JFormattedTextField</code>.
         *
         * @return Copy of the AbstractFormatter
         */
        protected Object clone() throws CloneNotSupportedException {
            AbstractFormatter formatter = (AbstractFormatter)super.clone();

            formatter.ftf = null;
            return formatter;
        }

        /**
         * Installs the <code>DocumentFilter</code> <code>filter</code>
         * onto the current <code>JFormattedTextField</code>.
         *
         * @param filter DocumentFilter to install on the Document.
         */
        private void installDocumentFilter(DocumentFilter filter) {
            JFormattedTextField ftf = getFormattedTextField();

            if (ftf != null) {
                Document doc = ftf.getDocument();

                if (doc instanceof AbstractDocument) {
                    ((AbstractDocument)doc).setDocumentFilter(filter);
                }
                doc.putProperty(DocumentFilter.class, null);
            }
        }
    }


    /**
     * Used to commit the edit. This extends JTextField.NotifyAction
     * so that <code>isEnabled</code> is true while a JFormattedTextField
     * has focus, and extends <code>actionPerformed</code> to invoke
     * commitEdit.
     */
    static class CommitAction extends JTextField.NotifyAction {
        public void actionPerformed(ActionEvent e) {
            JTextComponent target = getFocusedComponent();

            if (target instanceof JFormattedTextField) {
                // Attempt to commit the value
                try {
                    ((JFormattedTextField)target).commitEdit();
                } catch (ParseException pe) {
                    ((JFormattedTextField)target).invalidEdit();
                    // value not commited, don't notify ActionListeners
                    return;
                }
            }
            // Super behavior.
            super.actionPerformed(e);
        }

        public boolean isEnabled() {
            JTextComponent target = getFocusedComponent();
            if (target instanceof JFormattedTextField) {
                JFormattedTextField ftf = (JFormattedTextField)target;
                if (!ftf.isEdited()) {
                    return false;
                }
                return true;
            }
            return super.isEnabled();
        }
    }


    /**
     * CancelAction will reset the value in the JFormattedTextField when
     * <code>actionPerformed</code> is invoked. It will only be
     * enabled if the focused component is an instance of
     * JFormattedTextField.
     */
    private static class CancelAction extends TextAction {
        public CancelAction() {
            super("reset-field-edit");
        }

        public void actionPerformed(ActionEvent e) {
            JTextComponent target = getFocusedComponent();

            if (target instanceof JFormattedTextField) {
                JFormattedTextField ftf = (JFormattedTextField)target;
                ftf.setValue(ftf.getValue());
            }
        }

        public boolean isEnabled() {
            JTextComponent target = getFocusedComponent();
            if (target instanceof JFormattedTextField) {
                JFormattedTextField ftf = (JFormattedTextField)target;
                if (!ftf.isEdited()) {
                    return false;
                }
                return true;
            }
            return super.isEnabled();
        }
    }


    /**
     * Sets the dirty state as the document changes.
     */
    private class DocumentHandler implements DocumentListener, Serializable {
        public void insertUpdate(DocumentEvent e) {
            setEdited(true);
        }
        public void removeUpdate(DocumentEvent e) {
            setEdited(true);
        }
        public void changedUpdate(DocumentEvent e) {}
    }
}
