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内で式を解釈するべきか。
設計方針次第だろうけど、同じソースを重複して書きたくなかったので、前者の方法にした。
とりあえず、これで先に進めます (^^