Commons Digesterの仕組みを読む
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#contents
*はじめに [#m4b5e765]
[[Commons Digester:http://jakarta.apache.org/commons/dige...
d.addObjectCreate("address-book/person", Person.class);
d.addSetProperties("address-book/person");
d.addSetNext("address-book/person", "addPerson");
d.addCallMethod("address-book/person/email", "addEmail",...
d.addCallParam("address-book/person/email", 0, "type");
d.addCallParam("address-book/person/email", 1);
d.addSetNestedProperties("address-book/person/address");
のようにどのタグに行き当たったら何をするかのルールを設定...
AddressBook book = new AddressBook();
d.push(book);
File srcfile = new File(filename);
d.parse(srcfile);
とするとオブジェクトが構築されます(上記のコードはDigester...
なお、今回読んだDigesterのバージョンは1.8です。
*Digester.addXXXXXXXX() [#n0d87e84]
まず、ルールの追加部分を見てみましょう。
public void addObjectCreate(String pattern, Class clazz) {
addRule(pattern,
new ObjectCreateRule(clazz));
}
public void addSetProperties(String pattern) {
addRule(pattern,
new SetPropertiesRule());
}
ということで各メソッドは個別のRule実装クラスを構築しルー...
public void addRule(String pattern, Rule rule) {
rule.setDigester(this);
getRules().add(pattern, rule);
}
getRules()はRulesインターフェースを実装しているRulesBase...
public void add(String pattern, Rule rule) {
...略...
List list = (List) cache.get(pattern);
if (list == null) {
list = new ArrayList();
cache.put(pattern, list);
}
list.add(rule);
rules.add(rule);
...略...
}
cacheはHashMap、rulesはArrayListのインスタンス変数です。c...
*Digester.parse() [#cc758b6c]
それでは次にparse()を見ていきましょう。parse()はいろいろ...
getXMLReader().parse(is);
としています。XMLRedaerはjavax.xml.sax.XMLReaderです。ど...
というわけでSAXのイベントハンドラメソッドを見てみましょう...
public void startElement(String namespaceURI, String loc...
String qName, Attributes list)
throws SAXException {
...略...
// Save the body text accumulated for our surroundin...
bodyTexts.push(bodyText);
...略...
bodyText = new StringBuffer();
// the actual element name is either in localName or...
// on whether the parser is namespace aware
String name = localName;
...略...
// Compute the current matching rule
StringBuffer sb = new StringBuffer(match);
if (match.length() > 0) {
sb.append('/');
}
sb.append(name);
match = sb.toString();
...略...
// Fire "begin" events for all relevant rules
List rules = getRules().match(namespaceURI, match);
matches.push(rules);
if ((rules != null) && (rules.size() > 0)) {
...略...
for (int i = 0; i < rules.size(); i++) {
try {
Rule rule = (Rule) rules.get(i);
...略...
rule.begin(namespaceURI, name, list);
} catch (Exception e) {
...略...
}
}
} else {
...略...
}
}
startElement()では、
+現在のパスを構築し、
+パスに対するルールを検索し、
+各ルールのbegin()メソッドを呼び出す
ということをしているようです。
次に、タグ内部のテキストを読み込むと呼ばれるdharacters()...
public void characters(char buffer[], int start, int len...
throws SAXException {
...略...
bodyText.append(buffer, start, length);
}
なんの変哲もありません。ところで、bodyTextはStringBuffer...
最後に、終了タグを読み込むと呼ばれるendElement()です。
public void endElement(String namespaceURI, String local...
String qName) throws SAXException {
...略...
// the actual element name is either in localName or...
// on whether the parser is namespace aware
String name = localName;
...略...
// Fire "body" events for all relevant rules
List rules = (List) matches.pop();
if ((rules != null) && (rules.size() > 0)) {
String bodyText = this.bodyText.toString();
...略...
for (int i = 0; i < rules.size(); i++) {
try {
Rule rule = (Rule) rules.get(i);
...略...
rule.body(namespaceURI, name, bodyText);
} catch (Exception e) {
...略...
}
}
} else {
...略...
}
// Recover the body text from the surrounding element
bodyText = (StringBuffer) bodyTexts.pop();
...略...
// Fire "end" events for all relevant rules in rever...
if (rules != null) {
for (int i = 0; i < rules.size(); i++) {
int j = (rules.size() - i) - 1;
try {
Rule rule = (Rule) rules.get(j);
...略...
rule.end(namespaceURI, name);
} catch (Exception e) {
...略...
}
}
}
// Recover the previous match expression
int slash = match.lastIndexOf('/');
if (slash >= 0) {
match = match.substring(0, slash);
} else {
match = "";
}
}
というわけで、endDocument()が呼ばれるまで内部テキストが確...
以上がDigester.parse()の中身です。parse()は枠を用意してい...
*SetNestedPropertiesRule [#h200ef29]
各ルールはリフレクションを使ってオブジェクトを作成したり...
public void begin(String namespace, String name, Attribu...
throws Exception {
Rules oldRules = digester.getRules();
AnyChildRule anyChildRule = new AnyChildRule();
anyChildRule.setDigester(digester);
AnyChildRules newRules = new AnyChildRules(anyChildR...
newRules.init(digester.getMatch()+"/", oldRules);
digester.setRules(newRules);
}
public void body(String bodyText) throws Exception {
AnyChildRules newRules = (AnyChildRules) digester.ge...
digester.setRules(newRules.getOldRules());
}
というわけで、begin()メソッドが呼ばれるとルール一覧をすり...
次に、AddAnyChildRulesのmatch()メソッドを見てみましょう。
public List match(String namespaceURI, String matchPath) {
List match = decoratedRules.match(namespaceURI, matc...
if ((matchPath.startsWith(matchPrefix)) &&
(matchPath.indexOf('/', matchPrefix.length()) ==...
// The current element is a direct child of the ...
// specified in the init method, so we want to e...
// the rule passed to this object's constructor ...
// in the returned list of matching rules.
if ((match == null || match.size()==0)) {
// The "real" rules class doesn't have any m...
// the specified path, so we return a list c...
// just one rule: the one passed to this obj...
// constructor.
return rules;
}
else {
// The "real" rules class has rules that mat...
// node, so we return this list *plus* the r...
// this object's constructor.
//
// It might not be safe to modify the return...
// so clone it first.
LinkedList newMatch = new LinkedList(match);
newMatch.addLast(rule);
return newMatch;
}
}
else {
return match;
}
}
というわけで、指定パス直下の子要素の場合はAnyChildRuleが...
*おわりに [#v98801e1]
今回はCommons Digesterのオブジェクト構築方法を学びました...
-フレームワークはシンプルに。個別の処理は個別のクラスで
-されど拡張性(ルールのすり替えとか)をちゃんと用意
といったところです。それではみなさんもよいコードリーディ...
終了行:
#contents
*はじめに [#m4b5e765]
[[Commons Digester:http://jakarta.apache.org/commons/dige...
d.addObjectCreate("address-book/person", Person.class);
d.addSetProperties("address-book/person");
d.addSetNext("address-book/person", "addPerson");
d.addCallMethod("address-book/person/email", "addEmail",...
d.addCallParam("address-book/person/email", 0, "type");
d.addCallParam("address-book/person/email", 1);
d.addSetNestedProperties("address-book/person/address");
のようにどのタグに行き当たったら何をするかのルールを設定...
AddressBook book = new AddressBook();
d.push(book);
File srcfile = new File(filename);
d.parse(srcfile);
とするとオブジェクトが構築されます(上記のコードはDigester...
なお、今回読んだDigesterのバージョンは1.8です。
*Digester.addXXXXXXXX() [#n0d87e84]
まず、ルールの追加部分を見てみましょう。
public void addObjectCreate(String pattern, Class clazz) {
addRule(pattern,
new ObjectCreateRule(clazz));
}
public void addSetProperties(String pattern) {
addRule(pattern,
new SetPropertiesRule());
}
ということで各メソッドは個別のRule実装クラスを構築しルー...
public void addRule(String pattern, Rule rule) {
rule.setDigester(this);
getRules().add(pattern, rule);
}
getRules()はRulesインターフェースを実装しているRulesBase...
public void add(String pattern, Rule rule) {
...略...
List list = (List) cache.get(pattern);
if (list == null) {
list = new ArrayList();
cache.put(pattern, list);
}
list.add(rule);
rules.add(rule);
...略...
}
cacheはHashMap、rulesはArrayListのインスタンス変数です。c...
*Digester.parse() [#cc758b6c]
それでは次にparse()を見ていきましょう。parse()はいろいろ...
getXMLReader().parse(is);
としています。XMLRedaerはjavax.xml.sax.XMLReaderです。ど...
というわけでSAXのイベントハンドラメソッドを見てみましょう...
public void startElement(String namespaceURI, String loc...
String qName, Attributes list)
throws SAXException {
...略...
// Save the body text accumulated for our surroundin...
bodyTexts.push(bodyText);
...略...
bodyText = new StringBuffer();
// the actual element name is either in localName or...
// on whether the parser is namespace aware
String name = localName;
...略...
// Compute the current matching rule
StringBuffer sb = new StringBuffer(match);
if (match.length() > 0) {
sb.append('/');
}
sb.append(name);
match = sb.toString();
...略...
// Fire "begin" events for all relevant rules
List rules = getRules().match(namespaceURI, match);
matches.push(rules);
if ((rules != null) && (rules.size() > 0)) {
...略...
for (int i = 0; i < rules.size(); i++) {
try {
Rule rule = (Rule) rules.get(i);
...略...
rule.begin(namespaceURI, name, list);
} catch (Exception e) {
...略...
}
}
} else {
...略...
}
}
startElement()では、
+現在のパスを構築し、
+パスに対するルールを検索し、
+各ルールのbegin()メソッドを呼び出す
ということをしているようです。
次に、タグ内部のテキストを読み込むと呼ばれるdharacters()...
public void characters(char buffer[], int start, int len...
throws SAXException {
...略...
bodyText.append(buffer, start, length);
}
なんの変哲もありません。ところで、bodyTextはStringBuffer...
最後に、終了タグを読み込むと呼ばれるendElement()です。
public void endElement(String namespaceURI, String local...
String qName) throws SAXException {
...略...
// the actual element name is either in localName or...
// on whether the parser is namespace aware
String name = localName;
...略...
// Fire "body" events for all relevant rules
List rules = (List) matches.pop();
if ((rules != null) && (rules.size() > 0)) {
String bodyText = this.bodyText.toString();
...略...
for (int i = 0; i < rules.size(); i++) {
try {
Rule rule = (Rule) rules.get(i);
...略...
rule.body(namespaceURI, name, bodyText);
} catch (Exception e) {
...略...
}
}
} else {
...略...
}
// Recover the body text from the surrounding element
bodyText = (StringBuffer) bodyTexts.pop();
...略...
// Fire "end" events for all relevant rules in rever...
if (rules != null) {
for (int i = 0; i < rules.size(); i++) {
int j = (rules.size() - i) - 1;
try {
Rule rule = (Rule) rules.get(j);
...略...
rule.end(namespaceURI, name);
} catch (Exception e) {
...略...
}
}
}
// Recover the previous match expression
int slash = match.lastIndexOf('/');
if (slash >= 0) {
match = match.substring(0, slash);
} else {
match = "";
}
}
というわけで、endDocument()が呼ばれるまで内部テキストが確...
以上がDigester.parse()の中身です。parse()は枠を用意してい...
*SetNestedPropertiesRule [#h200ef29]
各ルールはリフレクションを使ってオブジェクトを作成したり...
public void begin(String namespace, String name, Attribu...
throws Exception {
Rules oldRules = digester.getRules();
AnyChildRule anyChildRule = new AnyChildRule();
anyChildRule.setDigester(digester);
AnyChildRules newRules = new AnyChildRules(anyChildR...
newRules.init(digester.getMatch()+"/", oldRules);
digester.setRules(newRules);
}
public void body(String bodyText) throws Exception {
AnyChildRules newRules = (AnyChildRules) digester.ge...
digester.setRules(newRules.getOldRules());
}
というわけで、begin()メソッドが呼ばれるとルール一覧をすり...
次に、AddAnyChildRulesのmatch()メソッドを見てみましょう。
public List match(String namespaceURI, String matchPath) {
List match = decoratedRules.match(namespaceURI, matc...
if ((matchPath.startsWith(matchPrefix)) &&
(matchPath.indexOf('/', matchPrefix.length()) ==...
// The current element is a direct child of the ...
// specified in the init method, so we want to e...
// the rule passed to this object's constructor ...
// in the returned list of matching rules.
if ((match == null || match.size()==0)) {
// The "real" rules class doesn't have any m...
// the specified path, so we return a list c...
// just one rule: the one passed to this obj...
// constructor.
return rules;
}
else {
// The "real" rules class has rules that mat...
// node, so we return this list *plus* the r...
// this object's constructor.
//
// It might not be safe to modify the return...
// so clone it first.
LinkedList newMatch = new LinkedList(match);
newMatch.addLast(rule);
return newMatch;
}
}
else {
return match;
}
}
というわけで、指定パス直下の子要素の場合はAnyChildRuleが...
*おわりに [#v98801e1]
今回はCommons Digesterのオブジェクト構築方法を学びました...
-フレームワークはシンプルに。個別の処理は個別のクラスで
-されど拡張性(ルールのすり替えとか)をちゃんと用意
といったところです。それではみなさんもよいコードリーディ...
ページ名: