= JAutoRegexerの使い方 =
== はじめに ==
JAutoRegexerの実行エンジンの実態は「org.dyndns.nuda.tools.regex.RegexProcessor」です。[[BR]]
RegexProcessorクラスのprocessメソッドで正規表現の解析を行います。
processメソッドのシグニチャは以下の通りです。[[BR]]
{{{ code java
public List<T> process(String source, Class<T> regexBeanClass)
}}}
型Tはsource引数に指定された文字列(正規表現で解析を行う文字列)の解析結果が格納されるクラスです。[[BR]]
解析結果は上記シグニチャの通り、型Tのリスト型で帰ります。[[BR]]
== RegexBean ==
JAutoRegexerで正規表現解析結果のマッピングに用いられるJavaBeansは厳密な意味でのJavaBeansではありません。[[BR]]
本来のJavaBeansは...
* private なプロパティを
* public なgetter/setter を用いてカプセル化したものであり
* getter/setterのメソッド名はプロパティ名のキャメルケース記法を用いる
ですが、JAutoRegexerのそれは...
* publicなプロパティをもつ
この一点です。
これを「RegexBean」と呼んでいます。
以下は、RegexBeanのサンプルです。
{{{ code java
package org.dyndns.nuda.tools.regex;
import org.dyndns.nuda.tools.regex.annotation.Regex;
import org.dyndns.nuda.tools.regex.annotation.RegexItem;
@Regex(pattern = "(.+?):(.+?)://(.+?):(.+?)/(.+)")
public class ConStrRegexBean {
@RegexItem(groupIndex = 1)
public String coreName;
@RegexItem(groupIndex = 2)
public String subProtocol;
@RegexItem(groupIndex = 3)
public String host;
@RegexItem(groupIndex = 4)
public String port;
@RegexItem(groupIndex = 5)
public String schemeName;
@Override
public String toString() {
return "ConStrRegexBean [coreName=" + this.coreName + ", subProtocol="
+ this.subProtocol + ", host=" + this.host + ", port="
+ this.port + ", schemeName=" + this.schemeName + "]";
}
}
}}}
上記RegexBeanは
* クラスアノテーションとして「@Regex」
* フィールドアノテーションとして「@RegexItem」
が付加されています。
@RegexアノテーションはJAutoRegexerエンジンに対して「どのようにテキストコンテンツを解析するのか」の指示を出すために用いられます。
通常は「pattern要素」に正規表現文字列を指定して用います。
@RegexItemアノテーションは@Regexアノテーションで指定した正規表現の解析結果をどのように展開(マッピング)するのかを指定します。
「groupIndex要素」がそのまま正規表現グループのインデックスとなります。
例えば、上記RegexBeanを用いて
{{{ code java
/**
* 再帰的正規表現解析なしの場合に解析が成功することを確認する
*/
@Test
public void testProcess() {
String testSource = "jdbc:mysql://192.168.0.1:3306/testdb";
RegexProcessor p = new RegexProcessor();
List<ConStrRegexBean> resultList = p.process(testSource,
ConStrRegexBean.class);
if (resultList.size() == 0) {
Assert.fail();
}
ConStrRegexBean bean = resultList.get(0);
Assert.assertEquals(bean.toString(), "jdbc", bean.coreName);
Assert.assertEquals(bean.toString(), "mysql", bean.subProtocol);
Assert.assertEquals(bean.toString(), "192.168.0.1", bean.host);
Assert.assertEquals(bean.toString(), "3306", bean.port);
Assert.assertEquals(bean.toString(), "testdb", bean.schemeName);
}
}}}
とすれば、リストの0番目のRegexBean(ConStrRegexBean)に「jdbc:mysql://192.168.0.1:3306/testdb」が分解されて格納されます。
※上のサンプルコードはJAutoRegexerのテストケースから一部を抜き出したものです。
== 再帰展開(Recursive Mappings) ==
JAutoRegexerの特徴は、RegexBeanのプロパティとしてRegexBeanを指定できる点です。
以下のサンプルコードをご覧ください。
ConStrRegexBean02.java
{{{ code java
package org.dyndns.nuda.tools.regex;
import java.util.List;
import org.dyndns.nuda.tools.regex.annotation.Regex;
import org.dyndns.nuda.tools.regex.annotation.RegexItem;
@Regex(pattern = "(.+?):(.+?)://(.+?):(.+?)/(.+)")
public class ConStrRegexBean02 {
@RegexItem(groupIndex = 1)
public String coreName;
@RegexItem(groupIndex = 2)
public String subProtocol;
@RegexItem(groupIndex = 3)
public List<HostRegexBean> host;
@RegexItem(groupIndex = 4)
public String port;
@RegexItem(groupIndex = 5)
public String schemeName;
@Override
public String toString() {
return "ConStrRegexBean02 [coreName=" + this.coreName
+ ", subProtocol=" + this.subProtocol + ", host=" + this.host
+ ", port=" + this.port + ", schemeName=" + this.schemeName
+ "]";
}
}
}}}
HostRegexBean.java
{{{ code java
package org.dyndns.nuda.tools.regex;
import org.dyndns.nuda.tools.regex.annotation.Regex;
import org.dyndns.nuda.tools.regex.annotation.RegexItem;
@Regex(pattern = "(.+?)\\.(.+?)\\.(.+?)\\.(.+?)")
public class HostRegexBean {
@RegexItem(groupIndex = 1)
public String segment01;
@RegexItem(groupIndex = 2)
public String segment02;
@RegexItem(groupIndex = 3)
public String segment03;
@RegexItem(groupIndex = 4)
public String segment04;
@Override
public String toString() {
return "HostRegexBean [segment01=" + this.segment01 + ", segment02="
+ this.segment02 + ", segment03=" + this.segment03
+ ", segment04=" + this.segment04 + "]";
}
}
}}}
ConStrRegexBean02クラスのhostフィールドがHostRegexBean型のリストで指定されています。
このRegexBeanを用いたサンプルコードを以下に示します。
{{{ code java
/**
* 再帰的正規表現解析ありの場合に解析が成功することを確認する
*/
@Test
public void testProcess02() {
String testSource = "jdbc:mysql://192.168.0.1:3306/testdb";
RegexProcessor p = new RegexProcessor();
List<ConStrRegexBean02> resultList = p.process(testSource,
ConStrRegexBean02.class);
if (resultList.size() == 0) {
Assert.fail();
}
ConStrRegexBean02 bean = resultList.get(0);
Assert.assertEquals(bean.toString(), "jdbc", bean.coreName);
Assert.assertEquals(bean.toString(), "mysql", bean.subProtocol);
Assert.assertEquals(bean.toString(), "3306", bean.port);
Assert.assertEquals(bean.toString(), "testdb", bean.schemeName);
List<HostRegexBean> host = bean.host;
if (host.size() == 0) {
Assert.fail();
}
HostRegexBean hostRegexBean = host.get(0);
Assert.assertEquals(host.toString(), "192", hostRegexBean.segment01);
Assert.assertEquals(host.toString(), "168", hostRegexBean.segment02);
Assert.assertEquals(host.toString(), "0", hostRegexBean.segment03);
Assert.assertEquals(host.toString(), "1", hostRegexBean.segment04);
}
}}}
最初のサンプルコード(ConStrRegexBeanを用いたもの)では、単に解析結果をRegexBeanに展開して終わりでしたが、今回のサンプルコードは少々違います。
もうお気づきかと思われますが、RegexBeanのプロパティにRegexBeanのリストが指定された場合は、再帰的に正規表現を解析します。
上記コードの場合はhostフィールドに展開されるはずだった"192.168.0.1"という文字列がHostRegexBeanによって解析され展開されます。
具体的には「192, 168, 0, 1」の文字列が「segment01, segment02, segment03, segment04」にそれぞれ展開されます。
この再帰の回数に制限はありません。
JAutoRegexerは、現在のコンテキストで「解析する必要がある限り」根こそぎRegexBeanへの展開を行います。