/*


    ========== licence begin GPL
    Copyright (C) 2002-2003 SAP AG

    This program 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
    of the License, or (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


*/

package com.sap.dbtech.util.printf;

import com.sap.dbtech.util.*;
/**
 *
 */
abstract class DataFormatter extends Formatter {
    protected char kind;
    protected int width = defaultValue_C;
    protected int precision = defaultValue_C;
    protected boolean alignRight = false;
    protected char padChar = ' ';
    protected static final int defaultValue_C = -1;
    protected static final int dynamicValue_C = -2;
/**
 *
 * @param format java.lang.String
 * @exception com.sap.dbtech.util.printf.FormatException The exception description.
 */
protected DataFormatter(String format) throws FormatException {
    this.parseFormatString (format);
}
/**
 *
 * @return java.lang.String
 * @param objects com.sap.dbtech.util.printf.OArrayEnumeration
 * @exception com.sap.dbtech.util.printf.PrintfArgumentMismatch The exception description.
 */
String format (OArrayEnumeration objects) throws PrintfArgumentMismatch {
    int actualWidth = this.width;
    int actualPrecision = this.precision;
    Number argValue;
    Object obj;
    String result;

    try {
        if (this.width == dynamicValue_C) {
            argValue = (Number) objects.nextElement();
            actualWidth = argValue.intValue ();
        }
        if (this.precision == dynamicValue_C) {
            argValue = (Number) objects.nextElement();
            actualPrecision = argValue.intValue ();
        }
        obj = objects.nextElement();
    }
    catch (ArrayIndexOutOfBoundsException exc) {
        throw new PrintfArgumentMismatch(MessageTranslator.translate(MessageKey.ERROR_FORMAT_TOFEWARGS));
    }
    result = this.formatObject (obj, this.kind, actualWidth,
        actualPrecision, this.alignRight, this.padChar);
    return result;
}
/**
 *
 * @return java.lang.String
 * @param obj java.lang.Object
 * @param kind int
 * @param width int
 * @param prexision int
 * @param alignRight boolean
 * @param padChar char
 */
protected abstract String formatObject (Object obj, int kind, int width, int precision, boolean alignRight, char padChar)
        throws PrintfArgumentMismatch;
/**
 *
 * @return java.lang.String
 * @param obj java.lang.Object
 * @param kind int
 * @param width int
 * @param prexision int
 * @param alignRight boolean
 * @param padChar char
 */
protected String formatString (String str, int kind, int width, int precision, boolean alignRight, char padChar)
{
    if (width > str.length ()) {
        if (alignRight) {
            str = StringUtil.padLeft (str, width, padChar);
        }
        else {
            str = StringUtil.padRight (str, width, padChar);
        }
    }
    else if ((precision >= 0) && (precision < str.length ())) {
        str = str.substring (0, precision);
    }
    return str;
}
/**
 *
 * @param format java.lang.String
 * @exception com.sap.dbtech.util.printf.FormatException The exception description.
 */
private void parseFormatString (String format) throws FormatException {
    boolean inFlags = true;
    char current = 1;
    int pos = 0;    // skip over %
    int intval;

    if (format.charAt (0) != '%') {
        throw new FormatException (MessageTranslator.translate(MessageKey.ERROR_FORMAT_PERCENT));
    }
    /*
     * parse flags
     */
    while (inFlags) {
        ++pos;
        current = format.charAt (pos);
        switch (current) {
            case '-':
                this.alignRight = true;
                break;
            case '+':
                // not implemented: always a sign character
                break;
            case ' ':
                // not implemented: blank instead of '+'
                break;
            case '#':
                // not implemented: alternate form
                break;
            case '0':
                this.padChar = '0';
                break;
            default:
                inFlags = false;
                break;
        }
    }
    /*
     * width
     */
    if (current == '*') {
        this.width = dynamicValue_C;
        ++pos;
        current = format.charAt (pos);
    }
    else {
        intval = 0;
        while (('0' <= current) && (current <= '9')) {
            intval *= 10;
            intval += current - '0';
            ++pos;
            current = format.charAt (pos);
        }
        if (intval != 0) {
            this.width = intval;
        }
    }
    /*
     * precision
     */
    if (current == '.') {
        ++pos;
        current = format.charAt (pos);
        if (current == '*') {
            this.width = dynamicValue_C;
            ++pos;
            current = format.charAt (pos);
        }
        else {
            intval = 0;
            while (('0' <= current) && (current <= '9')) {
                intval *= 10;
                intval += current - '0';
                ++pos;
                current = format.charAt (pos);
            }
            if (intval != 0) {
                this.precision = intval;
            }
        }
    }
    /*
     * kind
     */
    this.kind = current;
}
}
