-XML Pull Parser(1)
まず、午前中一発目のお出かけから帰還。納品はいつもながら気持ちがよいです。
ひがさんのBLOGでSeasar設定XMLの検証について、Pull Parserを使ってはどうかとの示唆がありました。私、XML Pull Parserは名前だけ知っていて使ったことがありませんでした。その名前も、Xerces2のXNIでPalmデータベースを読んでSAXイベントを発火(そしてCocoon2と連動)するという変わったパーサーを作ったときに、XNIのインターフェイス中にPull Parserの存在を知らしめるコンフィギュレーションがあったので知っただけです。
指摘にあったようにDOCTYPE有る無しを判定するのにいいかもしれないと移動で歩きながら考えていました。SAXだとXML文書に書かれているものにしたがってSAXイベントが発火するけど、PullだとXML文書に書かれていないということが能動的にとれるかもしれないですね、なるほど。ということで、ドキュメントをちょっとさらって、隙間時間でチビチビ読んでみます。
と、今ひらめきましたが、FilterInputStreamで、いま何バイト目かだけを取れるようにしておけば、OKかも。
public class CounterFilterInputStream extends FilterInputStream { private long counter; public CounterFilterInputStream(InputStream inStream) { super(inStream); } public int read() throws IOException { int ret = super.read(); if(ret != -1) { counter++; } return ret; } public long getCounter() { return counter; } }
こういうのを作っておいて、
S2Contaienr container = new S2ContainerImpl(); CounterFilterInputStream counter = new CounterFilterInputStream(inStream); XMLPullParser xpp = ...(counter); for (int eventType = xpp.next(), int start = counter.getCounter(), int end = UNKNOWN; eventType != XMLPullParser.END_DOCUMENT; start = counter.getCounter(), eventType = xpp.next(), end = counter.getCounter()) { switch (eventType) { ... ComponentDef compDef = new PositionComponentDef(start, end, ...); container.regist(compDef); }
これでやれそう?
PullParserのサンプルはひがさんところからコピペなので想像ですけど、xpp.next()でホワイトスペースも取れれば(たぶん取れるでしょう)正確に位置を取れそうです。要は、
public interface PositionGettable { public static final int UNKNOWN = -1; public int getDefStart(); public int getDefEnd(); public void setDefEnd(int end); }
で、
public PositionComponentDef extends ComponentDefImpl implements PositionGettable { public int getDefStart() { return start; } public int getDefEnd() { return end; } // おまけに line と columnも取れたほうがよいかも。 }
が、AspectDefImpl、ArgDefImpl、InitMethodImpl、DestroyMethodDefImpl、ComponentDefImpl、PropertyDefImpl、おまけにIncludeDefとComponentsDefも作っておけばいいわけですね。あと平行して検討しなければならないのは、ここまでやらなくてもいいかもしれませんので、SpringUIがこういう情報取れていないのにOK出ている理由を調べないといけません。