/* 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package java.text;

import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
// BEGIN android-added
import java.util.Locale;
import java.util.ResourceBundle;
// END android-added

import org.apache.harmony.text.internal.nls.Messages;

/**
 * The base class for all formats.
 * <p>
 * This is an abstract base class which specifies the protocol for classes which
 * convert other objects or values, such as numeric values and dates, and their
 * string representations. In some cases these representations may be localized
 * or contain localized characters or strings. For example, a numeric formatter
 * such as {@code DecimalFormat} may convert a numeric value such as 12345 to
 * the string "$12,345". It may also parse the string back into a numeric value.
 * A date and time formatter like {@code SimpleDateFormat} may represent a
 * specific date, encoded numerically, as a string such as "Wednesday, February
 * 26, 1997 AD".
 * <p>
 * Many of the concrete subclasses of {@code Format} employ the notion of a
 * pattern. A pattern is a string representation of the rules which govern the
 * conversion between values and strings. For example, a {@code DecimalFormat}
 * object may be associated with the pattern "$#,##0.00;($#,##0.00)", which is a
 * common US English format for currency values, yielding strings such as
 * "$1,234.45" for 1234.45, and "($987.65)" for -987.6543. The specific syntax
 * of a pattern is defined by each subclass. Even though many subclasses use
 * patterns, the notion of a pattern is not inherent to {@code Format} classes
 * in general, and is not part of the explicit base class protocol.
 * <p>
 * Two complex formatting classes are worth mentioning: {@code MessageFormat}
 * and {@code ChoiceFormat}. {@code ChoiceFormat} is a subclass of
 * {@code NumberFormat} which allows the user to format different number ranges
 * as strings. For instance, 0 may be represented as "no files", 1 as "one
 * file", and any number greater than 1 as "many files". {@code MessageFormat}
 * is a formatter which utilizes other {@code Format} objects to format a string
 * containing multiple values. For instance, a {@code MessageFormat} object
 * might produce the string "There are no files on the disk MyDisk on February
 * 27, 1997." given the arguments 0, "MyDisk", and the date value of 2/27/97.
 * See the {@link ChoiceFormat} and {@link MessageFormat} descriptions for
 * further information.
 */
public abstract class Format implements Serializable, Cloneable {

    private static final long serialVersionUID = -299282585814624189L;

    /**
     * Constructs a new {@code Format} instance.
     */
    public Format() {
    }

    /**
     * Returns a copy of this {@code Format} instance.
     * 
     * @return a shallow copy of this format.
     * 
     * @see java.lang.Cloneable
     */
    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }

    // BEGIN android-added
    static ResourceBundle getBundle(final Locale locale) {
        return AccessController
                .doPrivileged(new PrivilegedAction<ResourceBundle>() {
                    public ResourceBundle run() {
                        return ResourceBundle
                                .getBundle(
                                        "org.apache.harmony.luni.internal.locale.Locale", locale); //$NON-NLS-1$
                    }
                });
    }
    // END android-added

    String convertPattern(String template, String fromChars, String toChars,
            boolean check) {
        if (!check && fromChars.equals(toChars)) {
            return template;
        }
        boolean quote = false;
        StringBuilder output = new StringBuilder();
        int length = template.length();
        for (int i = 0; i < length; i++) {
            int index;
            char next = template.charAt(i);
            if (next == '\'') {
                quote = !quote;
            }
            if (!quote && (index = fromChars.indexOf(next)) != -1) {
                output.append(toChars.charAt(index));
            } else if (check
                    && !quote
                    && ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
                // text.05=Invalid pattern char {0} in {1}
                throw new IllegalArgumentException(Messages.getString(
                        "text.05", String.valueOf(next), template)); //$NON-NLS-1$
            } else {
                output.append(next);
            }
        }
        if (quote) {
            // text.04=Unterminated quote
            throw new IllegalArgumentException(Messages.getString("text.04")); //$NON-NLS-1$
        }
        return output.toString();
    }

    /**
     * Formats the specified object using the rules of this format.
     * 
     * @param object
     *            the object to format.
     * @return the formatted string.
     * @throws IllegalArgumentException
     *         if the object cannot be formatted by this format.
     */
    public final String format(Object object) {
        return format(object, new StringBuffer(), new FieldPosition(0))
                .toString();
    }

    /**
     * Appends the specified object to the specified string buffer using the
     * rules of this format.
     * <p>
     * {@code field} is an input/output parameter. If its {@code field}
     * member contains an enum value specifying a field on input, then its
     * {@code beginIndex} and {@code endIndex} members will be updated with the
     * text offset of the first occurrence of this field in the formatted text.
     *
     * @param object
     *            the object to format.
     * @param buffer
     *            the string buffer where the formatted string is appended to.
     * @param field
     *            on input: an optional alignment field; on output: the offsets
     *            of the alignment field in the formatted text.
     * @return the string buffer.
     * @throws IllegalArgumentException
     *            if the object cannot be formatted by this format.
     */
    public abstract StringBuffer format(Object object, StringBuffer buffer,
            FieldPosition field);

    /**
     * Formats the specified object using the rules of this format and returns
     * an {@code AttributedCharacterIterator} with the formatted string and no
     * attributes.
     * <p>
     * Subclasses should return an {@code AttributedCharacterIterator} with the
     * appropriate attributes.
     *
     * @param object
     *            the object to format.
     * @return an {@code AttributedCharacterIterator} with the formatted object
     *         and attributes.
     * @throws IllegalArgumentException
     *            if the object cannot be formatted by this format.
     */
    public AttributedCharacterIterator formatToCharacterIterator(Object object) {
        return new AttributedString(format(object)).getIterator();
    }

    /**
     * Parses the specified string using the rules of this format.
     * 
     * @param string
     *            the string to parse.
     * @return the object resulting from the parse.
     * @throws ParseException
     *            if an error occurs during parsing.
     */
    public Object parseObject(String string) throws ParseException {
        ParsePosition position = new ParsePosition(0);
        Object result = parseObject(string, position);
        if (position.getErrorIndex() != -1 || position.getIndex() == 0) {
            throw new ParseException(null, position.getErrorIndex());
        }
        return result;
    }

    /**
     * Parses the specified string starting at the index specified by
     * {@code position}. If the string is successfully parsed then the index of
     * the {@code ParsePosition} is updated to the index following the parsed
     * text. On error, the index is unchanged and the error index of
     * {@code ParsePosition} is set to the index where the error occurred.
     * 
     * @param string
     *            the string to parse.
     * @param position
     *            input/output parameter, specifies the start index in
     *            {@code string} from where to start parsing. If parsing is
     *            successful, it is updated with the index following the parsed
     *            text; on error, the index is unchanged and the error index is
     *            set to the index where the error occurred.
     * @return the object resulting from the parse or {@code null} if there is
     *         an error.
     */
    public abstract Object parseObject(String string, ParsePosition position);

    /*
     * Gets private field value by reflection.
     * 
     * @param fieldName the field name to be set @param target the object which
     * field to be gotten
     */
    static Object getInternalField(final String fieldName, final Object target) {
        Object value = AccessController
                .doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        Object result = null;
                        java.lang.reflect.Field field = null;
                        try {
                            field = target.getClass().getDeclaredField(
                                    fieldName);
                            field.setAccessible(true);
                            result = field.get(target);
                        } catch (Exception e1) {
                            return null;
                        }
                        return result;
                    }
                });
        return value;
    }

    static boolean upTo(String string, ParsePosition position,
            StringBuffer buffer, char stop) {
        int index = position.getIndex(), length = string.length();
        boolean lastQuote = false, quote = false;
        while (index < length) {
            char ch = string.charAt(index++);
            if (ch == '\'') {
                if (lastQuote) {
                    buffer.append('\'');
                }
                quote = !quote;
                lastQuote = true;
            } else if (ch == stop && !quote) {
                position.setIndex(index);
                return true;
            } else {
                lastQuote = false;
                buffer.append(ch);
            }
        }
        position.setIndex(index);
        return false;
    }

    static boolean upToWithQuotes(String string, ParsePosition position,
            StringBuffer buffer, char stop, char start) {
        int index = position.getIndex(), length = string.length(), count = 1;
        boolean quote = false;
        while (index < length) {
            char ch = string.charAt(index++);
            if (ch == '\'') {
                quote = !quote;
            }
            if (!quote) {
                if (ch == stop) {
                    count--;
                }
                if (count == 0) {
                    position.setIndex(index);
                    return true;
                }
                if (ch == start) {
                    count++;
                }
            }
            buffer.append(ch);
        }
        // text.07=Unmatched braces in the pattern
        throw new IllegalArgumentException(Messages.getString("text.07")); //$NON-NLS-1$
    }

    /**
     * Inner class used to represent {@code Format} attributes in the
     * {@code AttributedCharacterIterator} that the
     * {@code formatToCharacterIterator()} method returns in {@code Format}
     * subclasses.
     */
    public static class Field extends AttributedCharacterIterator.Attribute {

        private static final long serialVersionUID = 276966692217360283L;

        /**
         * Constructs a new instance of {@code Field} with the given field name.
         *
         * @param fieldName
         *            the field name.
         */
        protected Field(String fieldName) {
            super(fieldName);
        }
    }
}
