CustomFormatter.java

package com.github.mygreen.cellformatter;

import java.util.List;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList;

import com.github.mygreen.cellformatter.lang.ArgUtils;
import com.github.mygreen.cellformatter.number.NumberFactory;
import com.github.mygreen.cellformatter.term.NumberTerm;
import com.github.mygreen.cellformatter.term.TextTerm;
import com.github.mygreen.cellformatter.tokenizer.Token;



/**
 * ユーザ定義の書式を表現するフォーマッタ。
 * <p>{@link CustomFormatterFactory}からインスタンスを作成する。
 *
 * @version 0.10
 * @author T.TSUCHIE
 *
 */
public class CustomFormatter extends CellFormatter {

    /**
     * 書式がない、標準フォーマッター
     */
    public static final CustomFormatter DEFAULT_FORMATTER;
    static {
        // 数値の場合
        final ConditionNumberFormatter numberFormatter = new ConditionNumberFormatter("General");
        numberFormatter.addTerm(NumberTerm.general());
        numberFormatter.setOperator(ConditionOperator.ALL);
        numberFormatter.setNumberFactory(NumberFactory.decimalNumber(0, false, 0));

        // 文字列の場合
        final ConditionTextFormatter textFormatter = new ConditionTextFormatter("General");
        textFormatter.addTerm(TextTerm.atMark(Token.SYMBOL_AT_MARK));
        textFormatter.setOperator(ConditionOperator.ALL);

        final CustomFormatter formatter = new CustomFormatter("");
        formatter.addConditionFormatter(numberFormatter);
        formatter.addConditionFormatter(textFormatter);

        DEFAULT_FORMATTER = formatter;
    }

    /**
     * 書式のパターン
     */
    private final String pattern;

    /**
     * 条件付きのフォーマッタ
     */
    private List<ConditionFormatter> conditionFormatters = new CopyOnWriteArrayList<>();

    /**
     * 書式を指定してインスタンスを作成する。
     * @param pattern ユーザ定義の書式。
     */
    public CustomFormatter(final String pattern) {
        this.pattern = pattern;
    }

    @Override
    public CellFormatResult format(final CommonCell cell, final Locale runtimeLocale) {

        ArgUtils.notNull(cell, "cell");

        for(ConditionFormatter formatter : conditionFormatters) {
            if(formatter.isMatch(cell)) {
                return formatter.format(cell, runtimeLocale);
            }
        }

        /*
         * 一致するものがない場合は、デフォルトのフォーマッタで処理する。
         * ・セクションとセルの属性が一致していない場合に発生する。
         * ・数値が設定されているのに、文字列用のセクションしかない場合。
         */
        if(cell.isText()) {
            return DEFAULT_FORMATTER.format(cell, runtimeLocale);

        } else if(cell.isNumber()) {
            return DEFAULT_FORMATTER.format(cell, runtimeLocale);
        }

        throw new NoMatchConditionFormatterException(cell, String.format(
                "not match format for cell : '%s'", cell.getCellAddress()));

    }

    @Override
    public String getPattern(Locale locale) {
        return pattern;
    }

    /**
     * 文字列の書式を持つかどうか。
     * @return
     */
    public boolean hasTextFormatter() {
        for(ConditionFormatter formatter : conditionFormatters) {
            if(formatter.isTextFormatter()) {
                return true;
            }
        }

        return false;
    }

    /**
     * 日時のフォーマッタを持つかどうか。
     * <p>ただし、';'で区切り数値と日時の書式を同時に持つ可能性がある。
     * @return
     */
    public boolean hasDateFormatter() {
        for(ConditionFormatter formatter : conditionFormatters) {
            if(formatter.isDateFormatter()) {
                return true;
            }
        }

        return false;
    }

    /**
     * 数値のフォーマッタを持つかどうか。
     * <p>ただし、';'で区切り数値と日時の書式を同時に持つ可能性がある。
     * @return
     */
    public boolean hasNumberFormatter() {
        for(ConditionFormatter formatter : conditionFormatters) {
            if(formatter.isNumberFormatter()) {
                return true;
            }
        }

        return false;
    }

    /**
     * 条件付きのフォーマッタを追加する。
     * @param formatter
     */
    public void addConditionFormatter(ConditionFormatter formatter) {
        this.conditionFormatters.add(formatter);
    }

    /**
     * 条件付きのフォーマッタを取得する。
     * @return
     */
    public List<ConditionFormatter> getConditionFormatters() {
        return conditionFormatters;
    }

}