谷本 心 in せろ部屋

はてなダイアリーから引っ越してきました

S2JSFでWebParts その12

どうやら、出来た模様。

  • m:srcに文字列を指定 → 今まで通り、srcで指定したファイルを読み込む
  • m:srcにVB式で文字列を指定 → 解釈後の文字列を、srcとしてファイルを読み込む
  • m:srcにVB式でCollection/配列を指定 → 解釈後の配列を、すべてsrcとしてファイルを読み込む


例えば、

<span m:inject="s:insert" m:src="#{hogeList}"/>

こんな風に記述した時に、hogeListの中身が
{ "hoge1.html", "hoge2.html", "hoge3.html" } だと、すべて画面上に表示するというもの。


変更点は以下の通り。


まず、InsertProcessorに、m:srcを解釈して配列として返すメソッドを追加。

public Object[] getSrcs() {
	String src = getSrc();

	if (src == null) {
		return null;
	} else if (!BindingUtil.isValueReference(src)) {
		return new Object[] { (String) src };
	}

	Object value = BindingUtil.resolveBinding(src);
	if (value == null) {
		return null;
	} else if (value instanceof String) {
		return new Object[] { (String) value };
	} else if (value instanceof Collection) {
		return (Object[]) new ArrayList((Collection) value).toArray();
	} else if (value.getClass().isArray()) {
		return (Object[]) value;
	} else {
		throw new IllegalStateException(JsfConstants.SRC_ATTR);
	}
}


次に、InsertProcessor#processで、上で追加したメソッドを呼ぶように変更。

public void process(JsfContext jsfContext, Tag parentTag)
		throws JspException {

	Map insertProcessorMap = getInsertProcessorMap(jsfContext
			.getPageContext());
	String name = getName();
	if (name != null && insertProcessorMap.containsKey(name)) {
		InsertProcessor ip = (InsertProcessor) insertProcessorMap.get(name);
		if (ip != this) {
			ip.process(jsfContext, parentTag);
			return;
		}
	}

	// -- 変更 BEGIN
	/*
	String src = getSrc();
	if (src != null) {
		processInclude(jsfContext, parentTag, src);
	} else {
		processChildren(jsfContext, parentTag);
	}
	 */
	Object[] srcs = getSrcs();
	if (srcs != null) {
		for (int i = 0; i < srcs.length; i++) {
			processInclude(jsfContext, parentTag, (String) srcs[i]);
		}
	} else {
		processChildren(jsfContext, parentTag);
	}
	// -- 変更 END
}


ViewProcessor#addIncludesも、同じように修正。

protected void addIncludes(Set includes) {
	for (int i = 0; i < insertProcessors.size(); ++i) {
		InsertProcessor ip = (InsertProcessor) insertProcessors.get(i);
		// -- 変更 BEGIN
		/*
		if (src != null) {
			includes.add(src);
		}
		 */
		Object[] srcs = ip.getSrcs();
		if (srcs != null) {
			for (int j = 0; j < srcs.length; j++) {
				includes.add((String) srcs[j]);
			}
		}
		// -- 変更 END
	}
	ViewProcessor extendsViewProcessor = getExtendsViewProcessor();
	if (extendsViewProcessor != null) {
		includes.add(extendsPath);
		extendsViewProcessor.addIncludes(includes);
	}
}


ちょっと迷ったのが、
APIが変わることを気にせず、ViewProcessorからgetSrcs()を呼ぶべきか、
APIが変わらないよう、getSrc()してからViewProcessor内で式を解釈するべきか。


設計方針次第だろうけど、同じソースを重複して書きたくなかったので、前者の方法にした。
とりあえず、これで先に進めます (^^