Wicket : ListViewで複製したInputFields全体をチェックするValidator


##目標
不特定数のドロップダウンチョイスを持つFormを作るときに、下記のような結果を出すバリデータを作りたかった。

------
![重複.jpg](https://qiita-image-store.s3.amazonaws.com/0/57201/f49bf787-4c51-dcd4-3c47-26eca6fab33d.jpeg)
------
![選択漏れ.jpg](https://qiita-image-store.s3.amazonaws.com/0/57201/1ec0dee6-d500-9d95-83a8-c6711026c956.jpeg)
------
エラーがない場合
![エラーなし.jpg](https://qiita-image-store.s3.amazonaws.com/0/57201/9090482c-e2dd-db94-c759-b3f625294efb.jpeg)
------

##CustomValidatorの作成
1. AbstractFormValidatorを継承したCustomValidatorクラスを作る
2. CustomValidator内には検査対象のinputFieldを保持するListを作る
3. CustomValidator内のValidatorメソッド中で、inputFieldのListから、入力された値を取得し値のチェックを行う

##使い方
1. ListViewでFormにinputFiledをAddするときに、CustomValidatorのListにもAddするようにする
2. FormにCustomValidtorをセットする

##コード
```html:Page.html
<body>
	
	<p>入力ページ</p>
		<div wicket:id="feedback"></div>
		
		<form wicket:id="form">
			<ul style="list-style-type: none;" wicket:id="listView" >
				
				<li><span wicket:id="order">Number:</span> : <select wicket:id="selector"></select></li>
			</ul>

			<p><input type="submit" value="決定" wicket:id="upload" class="btn" /></p>

		</form>
	
</body>
```

```java:Page.java
//一部抜粋

final Form<?> form = new Form<Void>("form");

//選ばれた内容が正しいか判定するValidator
final SelectionValidator selectionValidator = new SelectionValidator();
form.add(selectionValidator);

//選択肢リスト
final List<String> options = Arrays.asList("","A","B","C");
//選択したobjectが入るリスト
final List<String> selection = Arrays.asList("","","");

//ListViewでFormにDropDownChoiceをAddする
ListView<String> listView = new ListView<String>("listView",selection){

	private static final long serialVersionUID = 6483489885119506981L;

	@Override
	protected void populateItem(ListItem<String> item) {
		DropDownChoice<String> dropDownChoice = new DropDownChoice<String>("selector", item.getModel(),options);
		item.add(dropDownChoice);
		//SelectionValidatorにComponentを預ける
		selectionValidator.addComponents(dropDownChoice);
	}
};

listView.setReuseItems(true);

form.add(listView);
		
AjaxButton upload = new AjaxButton("upload") {

	private static final long serialVersionUID = 606832891534714518L;

	@Override
	protected void onSubmit(AjaxRequestTarget arg0, Form<?> arg1) {
		//buttonを押された時に選ばれた内容を表示する
		info(selection.toString());
		arg0.add(feedbackPanel);
	}
	@Override
	protected void onError(AjaxRequestTarget target, Form<?> form) {
		//エラー時の処理
		target.add(feedbackPanel);
	}
};
	
form.add(upload);

```

``` java:SelectionValidatio.java
/** ドロップダウンチョイスが正しく選ばれているかチェックするValidator
	チェック項目は2点：
	1. 選択漏れはないか
	2. 選択の重複はないか
 */
public class SelectionValidator extends AbstractFormValidator {

	private static final long serialVersionUID = -5475763159946590330L;

	//Validate対象を保持するリスト
	private final List<DropDownChoice<String>> components = new ArrayList<DropDownChoice<String>>();
	
	public void addComponents(final DropDownChoice<String> component) {
		components.add(component);
	}

	@Override
	public FormComponent<?>[] getDependentFormComponents() {
		return components.toArray(new FormComponent[components.size()]);
	}

	@Override
	public void validate(final Form<?> form) {
		//検証に用いるデータをinpuFieldsから取り出す
		List<String> inputs = new ArrayList<String>();
		for(DropDownChoice<String> component : components){
			inputs.add(component.getConvertedInput());
		}
		
		//1.選択漏れはないか
		for(String string : inputs){
			if(string.isEmpty()){
				form.error("選択漏れがあります");
				return;
			}
		}
			
		// 2.選択の重複はないか
		for(int i = 0; i < inputs.size(); i++){
			for(int j = i+1;j < inputs.size(); j++){
				if (inputs.get(i).equals(inputs.get(j))) {
					form.error("選択が重複しています");
					return;
				}
			}
		}
	}		
}
```

##参考サイト
[Subject: Adding Custom validator for Listview having multiple checkboxes - msg#00320](http://osdir.com/ml/users-wicket.apache.org/2013-05/msg00320.html)
[ListViewで生成したコンポーネントに対してバリデータを指定するWicketJava](http://d.hatena.ne.jp/TaRO/20100530/1275219672)