SeasarDI Container with AOP
 

Golf Validorの説明

GolfのValidationは次の3階層で管理されています。
  • FormValidation Manager - 画面毎にあり、すべてのComponent ValidatorをHashtable に持っていて、順番に実行して、最後にValidationの結果を表示する Eventを発する
  • Component Validator - FormBindingManagerおよびGolfTableModelがこのIntefaceを 実装しておりFormValidation Managerから呼ばれる事により、自分で管理しているValidator に実行させる
  • Validator - 個々の Field単位のValidationを行う。原則的には、S2Containerで管理されるが Programで作成したり、S2Conteinerからインスタンスを取得後、パラメーターの変更をダイナミック に行うことも可能。
当面、Component Validatorを作成する機会は少ないとおもいますので、今回はValidatorについて説明します。
それでは、比較的簡単な LongValidatorを見てみましょう。プログラムは、以下の通りです。
public class LongValidator extends AbstractValidator{
    
    private Long minValue = null;
    private Long maxValue = null;
    public LongValidator() {
        messageKey = new String[] { "org.seasar.golf.validator.LongValidator.MINIMUM",
        "org.seasar.golf.validator.LongValidator.MAXIMUM",
        "org.seasar.golf.validator.LongValidator.INVALID"};        
    }

    public ValidationMessage validate(Object data, String label, 
					Object key, ValueModel valueModel, 
            FormManager formManager, boolean requiredCheck) {
        Long lValue  = null;
     
        String dataS = getDataString(data);
        if (dataS.length() == 0) {
            return null;
        }
        String displayLabel = getDisplayLabel(label);
        try {
            lValue = Long.parseLong(dataS);
        } catch (NumberFormatException ex) {
              return new SimpleValidationMessage(displayLabel 
					+ getMessage(2, dataS), Severity.ERROR, key );
        }
        if ((minValue != null) &&  (lValue < minValue)) {
            return new SimpleValidationMessage(displayLabel 
					+ getMessage(0, minValue, dataS), Severity.ERROR, key );
        }
        if ((maxValue !=null ) && (lValue > maxValue))  {
            return new SimpleValidationMessage(displayLabel 
					+ getMessage(1, maxValue, dataS), Severity.ERROR, key );          
        }        
        return null;
    }

    public Long getMinValue() {
        return minValue;
    }

    public void setMinValue(Long minValue) {
        this.minValue = minValue;
    }

    public Long getMaxValue() {
        return maxValue;
    }

    public void setMaxValue(Long maxValue) {
        this.maxValue = maxValue;
    }
}

見て分かる通り、非常に簡単に実装できます。Messageは、resouces\org\seasar\golf\validator\Messages.propetiesと
Messages_ja.propetiesにあります。 Netbeansでは、この編集も日本語と英語を一度に見ながら出来るので大変楽ですね。
次に、Validator機能だけでなく、Formatterの機能も兼ね備えた、DateValidatorを見てみましょう。
public class DateValidator extends AbstractValidator{
    
    private Integer minRelativeDate = null;
    private Integer maxRelativeDate = null;
    private DateFormat formatShort = DateFormat.getDateInstance(DateFormat.SHORT);
    private DateFormat formatLong  = DateFormat.getDateInstance(DateFormat.LONG);
    public DateValidator() {
        messageKey = new String[] { 
            "org.seasar.golf.validator.DateValidator.INVALID",
            "org.seasar.golf.validator.DateValidator.MINIMUM",
            "org.seasar.golf.validator.DateValidator.MAXIMUM"};        
    }
    private DateFormat parseFormat = formatShort; 
    private DateFormat displayFormat =formatShort; 

    public ValidationMessage validate(Object data, String label, 
					Object key, ValueModel valueModel, 
            FormManager formManager, boolean requiredCheck) {
        String newDataS = null;
        String dataS = getDataString(data);
        if (dataS.length() == 0) {
            return null;
        }
        String displayLabel = getDisplayLabel(label);

        Date dd = null;
        try {
           dd = parseFormat.parse(dataS);
           newDataS = displayFormat.format(dd);

           if (!dataS.equals(newDataS)) {
               ValidationUtil.updateValueModelWithoutValidation(
			   		formManager, valueModel, key, newDataS);
           }

        } catch (ParseException ex) {
            return new SimpleValidationMessage(displayLabel 
						+ getMessage(0, dataS), Severity.ERROR, key );
        }
        int rdate = ValidationUtil.getRelativeToToday(dd);
        if (minRelativeDate != null) {
            if (rdate < minRelativeDate) {
                 return new SimpleValidationMessage(displayLabel + 
                        getMessage(1, displayFormat.format(
									ValidationUtil.getRelativeToToday(minRelativeDate)) ,
                         newDataS), Severity.ERROR, key );
            }
        }
        if (maxRelativeDate != null) {
            if (rdate > maxRelativeDate) {
                 return new SimpleValidationMessage(displayLabel + 
                        getMessage(2, displayFormat.format(
									ValidationUtil.getRelativeToToday(maxRelativeDate)) ,
                         newDataS), Severity.ERROR, key );
            }
        }        
        
        return null;
    }

    public DateFormat getFormatShort() {
        return formatShort;
    }

    public void setFormatShort(DateFormat formatShort) {
        this.formatShort = formatShort;
    }

    public DateFormat getFormatLong() {
        return formatLong;
    }

    public void setFormatLong(DateFormat formatLong) {
        this.formatLong = formatLong;
    }

    public String getParseFormat() {
        return getFormatSub(parseFormat);
    }
    
    public String getFormatSub(DateFormat df) {
          if (df == formatShort) {
            return "S";
        }   else {
           return "L";
        }      
    }

    public void setParseFormat(String type) {
         if (type.toUpperCase().equals("L")) {
             parseFormat = formatLong;
        } else if (type.toUpperCase().equals("S")) {
             parseFormat = formatShort;
        } else {
            throw (new IllegalArgumentException("parse Format should be L or S"));
        }  
    }
    
    public String getDisplayFormat() {
         return getFormatSub(displayFormat);
    }

    public void setDisplayFormat(String type) {
         if (type.toUpperCase().equals("L")) {
             displayFormat = formatLong;
        } else if (type.toUpperCase().equals("S")) {  
             displayFormat =  formatShort;
        } else {
            throw (new IllegalArgumentException("display Format should be L or S"));
        } 
    }

    public Integer getMinRelativeDate() {
        return minRelativeDate;
    }

    public void setMinRelativeDate(Integer minRelativeDate) {
        this.minRelativeDate = minRelativeDate;
    }

    public Integer getMaxRelativeDate() {
        return maxRelativeDate;
    }

    public void setMaxRelativeDate(Integer maxRelativeDate) {
        this.maxRelativeDate = maxRelativeDate;
    }
    
}

少し、長くなりましたが、ポイントは、赤字の部分で、Formatした結果をValue Modelに戻しています。
画面のFieldでもTableでもUtility が自動的に判断して、戻す様にしていますので、非常に簡単です。
今後は、エラーとなった Fieldの色を変えるとか、その他の機能追加も要望があればやって行きたいと思います。
また Call Paremeterの requiredCheckは、HostにSubmit時などを想定していますので、ここで、単一項目の内容
だけでなく、他の項目との関連 チェックなども行える様配慮してあります。
Hostでプロセス時のエラーも同じ様なFormatで戻って来ることを考えており、自動的にシームレスに処理する予定です。
Version 0.1.1より、複数Validatorに対応しました。CSVのValidator欄に 「、(カンマ)」区切りで、複数書けます。
この場合、CSVファイルは、文字列を「”(ダブルクオート)」で囲ったものになります。
また、Servirityも「ERROR]「WARNING」に加え「INFO」も使用できます。
 

リンク

Golf 概要
GOLF HOMEへのリンク