--- /dev/null
+/*\r
+ * Regex pattern\r
+ *\r
+ * Copyright(c) 2008 olyutorskii\r
+ * $Id: RegexPattern.java 904 2009-11-17 11:14:10Z olyutorskii $\r
+ */\r
+\r
+package jp.sourceforge.jindolf;\r
+\r
+import java.util.regex.Pattern;\r
+import java.util.regex.PatternSyntaxException;\r
+import jp.sourceforge.jindolf.json.JsBoolean;\r
+import jp.sourceforge.jindolf.json.JsObject;\r
+import jp.sourceforge.jindolf.json.JsPair;\r
+import jp.sourceforge.jindolf.json.JsString;\r
+import jp.sourceforge.jindolf.json.JsValue;\r
+\r
+/**\r
+ * 正規表現。\r
+ */\r
+public class RegexPattern{\r
+\r
+ /** 英字大小無視指定フラグ。 */\r
+ public static final int IGNORECASEFLAG =\r
+ 0x00000000 | Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE;\r
+ private static final String REGEX_DELIM = "[\\s\u3000]+"; // 空白(全角含)\r
+ private static final String REGEX_CHAR = ".?+*\\$(|)[]{}^-&";\r
+\r
+\r
+ /**\r
+ * 正規表現とまぎらわしい字を含むか判定する。\r
+ * @param seq 文字列\r
+ * @return 紛らわしい字を含むならtrue\r
+ */\r
+ public static boolean hasRegexChar(CharSequence seq){\r
+ int length = seq.length();\r
+ for(int pt = 0; pt < length; pt++){\r
+ char ch = seq.charAt(pt);\r
+ if(REGEX_CHAR.indexOf(ch) >= 0) return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * 任意の文字列を必要に応じて正規表現シーケンス化する。\r
+ * @param text 文字列\r
+ * @return 引数と同じ内容の正規表現。必要がなければ引数そのまま\r
+ */\r
+ public static String quote(String text){\r
+ if(hasRegexChar(text)){\r
+ return Pattern.quote(text);\r
+ }\r
+ return text;\r
+ }\r
+\r
+ /**\r
+ * JSON形式に変換する。\r
+ * @param regex 正規表現\r
+ * @return JSON Object\r
+ */\r
+ public static JsObject encodeJson(RegexPattern regex){\r
+ JsObject result = new JsObject();\r
+\r
+ int regexFlag = regex.getRegexFlag();\r
+ boolean flagDotall = (regexFlag & Pattern.DOTALL) != 0;\r
+ boolean flagMultiline = (regexFlag & Pattern.MULTILINE) != 0;\r
+ boolean flagIgnoreCase = (regexFlag & IGNORECASEFLAG) != 0;\r
+\r
+ JsPair source = new JsPair("source", regex.getEditSource());\r
+ JsPair isRegex = new JsPair("isRegex", regex.isRegex());\r
+ JsPair dotall = new JsPair("dotall", flagDotall);\r
+ JsPair multiline = new JsPair("multiline", flagMultiline);\r
+ JsPair ignorecase = new JsPair("ignorecase", flagIgnoreCase);\r
+ JsPair comment = new JsPair("comment", regex.getComment());\r
+\r
+ result.putPair(source);\r
+ result.putPair(isRegex);\r
+ result.putPair(dotall);\r
+ result.putPair(multiline);\r
+ result.putPair(ignorecase);\r
+ result.putPair(comment);\r
+\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ * JSON形式から復元する。\r
+ * @param object JSON Object\r
+ * @return 正規表現\r
+ */\r
+ public static RegexPattern decodeJson(JsObject object){\r
+ JsValue value;\r
+\r
+ String source;\r
+ value = object.getValue("source");\r
+ if(value instanceof JsString){\r
+ source = ((JsString)value).toRawString();\r
+ }else{\r
+ source = "";\r
+ }\r
+\r
+ boolean isRegex;\r
+ value = object.getValue("isRegex");\r
+ if(value instanceof JsBoolean){\r
+ isRegex = ((JsBoolean)value).booleanValue();\r
+ }else{\r
+ isRegex = false;\r
+ }\r
+\r
+ int regexFlag = 0x00000000;\r
+ value = object.getValue("dotall");\r
+ if(value instanceof JsBoolean){\r
+ if(((JsBoolean)value).isTrue()){\r
+ regexFlag |= Pattern.DOTALL;\r
+ }\r
+ }\r
+ value = object.getValue("multiline");\r
+ if(value instanceof JsBoolean){\r
+ if(((JsBoolean)value).isTrue()){\r
+ regexFlag |= Pattern.MULTILINE;\r
+ }\r
+ }\r
+ value = object.getValue("ignorecase");\r
+ if(value instanceof JsBoolean){\r
+ if(((JsBoolean)value).isTrue()){\r
+ regexFlag |= IGNORECASEFLAG;\r
+ }\r
+ }\r
+\r
+ String comment;\r
+ value = object.getValue("comment");\r
+ if(value instanceof JsString){\r
+ comment = ((JsString)value).toRawString();\r
+ }else{\r
+ comment = "";\r
+ }\r
+\r
+ RegexPattern result =\r
+ new RegexPattern(source, isRegex, regexFlag, comment);\r
+\r
+ return result;\r
+ }\r
+\r
+\r
+ private final String editSource;\r
+ private final boolean isRegex;\r
+ private final Pattern pattern;\r
+ private final String comment;\r
+\r
+ /**\r
+ * コンストラクタ。\r
+ *\r
+ * @param editSource リテラル文字列または正規表現\r
+ * @param isRegex 指定文字列が正規表現ならtrue。リテラルならfalse\r
+ * @param flag 正規表現フラグ\r
+ * @param comment コメント\r
+ * @throws java.util.regex.PatternSyntaxException 正規表現がおかしい\r
+ */\r
+ public RegexPattern(String editSource,\r
+ boolean isRegex,\r
+ int flag,\r
+ String comment)\r
+ throws PatternSyntaxException{\r
+ super();\r
+ if(editSource == null) throw new NullPointerException();\r
+\r
+ this.isRegex = isRegex;\r
+ if(comment != null) this.comment = comment;\r
+ else this.comment = "";\r
+\r
+ String regexExpr;\r
+ if(this.isRegex){\r
+ this.editSource = editSource;\r
+ regexExpr = this.editSource;\r
+ }else{\r
+ String newSource = "";\r
+ regexExpr = "";\r
+\r
+ String[] tokens = editSource.split(REGEX_DELIM);\r
+ for(String token : tokens){\r
+ if(token == null || token.length() <= 0) continue;\r
+\r
+ if(newSource.length() <= 0) newSource = token;\r
+ else newSource += " " + token;\r
+\r
+ String quoted = "(?:" + quote(token) + ")";\r
+ if(regexExpr.length() <= 0) regexExpr = quoted;\r
+ else regexExpr += "|" + quoted;\r
+ }\r
+\r
+ this.editSource = newSource;\r
+ }\r
+\r
+ this.pattern = Pattern.compile(regexExpr, flag);\r
+\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * コンストラクタ。\r
+ *\r
+ * @param editSource リテラル文字列または正規表現\r
+ * @param isRegex 指定文字列が正規表現ならtrue。リテラルならfalse\r
+ * @param flag 正規表現フラグ\r
+ * @throws java.util.regex.PatternSyntaxException 正規表現がおかしい\r
+ */\r
+ public RegexPattern(String editSource,\r
+ boolean isRegex,\r
+ int flag )\r
+ throws PatternSyntaxException{\r
+ this(editSource, isRegex, flag, " ");\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * 元の入力文字列を返す。\r
+ * @return 入力文字列\r
+ */\r
+ public String getEditSource(){\r
+ return this.editSource;\r
+ }\r
+\r
+ /**\r
+ * コメントを返す。\r
+ * @return コメント\r
+ */\r
+ public String getComment(){\r
+ return this.comment;\r
+ }\r
+\r
+ /**\r
+ * 元の入力文字列が正規表現か否か返す。\r
+ * @return 正規表現ならtrue\r
+ */\r
+ public boolean isRegex(){\r
+ return this.isRegex;\r
+ }\r
+\r
+ /**\r
+ * 正規表現フラグを返す。\r
+ * @return 正規表現フラグ。\r
+ * @see java.util.regex.Pattern#flags()\r
+ */\r
+ public int getRegexFlag(){\r
+ return this.pattern.flags();\r
+ }\r
+\r
+ /**\r
+ * コンパイルされた正規表現形式を返す。\r
+ * @return コンパイルされた正規表現形式\r
+ */\r
+ public Pattern getPattern(){\r
+ return this.pattern;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ * @return {@inheritDoc}\r
+ */\r
+ @Override\r
+ public String toString(){\r
+ return this.editSource;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ * @param obj {@inheritDoc}\r
+ * @return {@inheritDoc}\r
+ */\r
+ @Override\r
+ public boolean equals(Object obj){\r
+ if(obj == null){\r
+ return false;\r
+ }\r
+ if( ! (obj instanceof RegexPattern) ){\r
+ return false;\r
+ }\r
+ RegexPattern other = (RegexPattern) obj;\r
+\r
+ String thisPattern = this.pattern.pattern();\r
+ String otherPattern = other.pattern.pattern();\r
+\r
+ if( ! thisPattern.equals(otherPattern) ) return false;\r
+\r
+ if(this.pattern.flags() != other.pattern.flags()) return false;\r
+\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ * @return {@inheritDoc}\r
+ */\r
+ @Override\r
+ public int hashCode(){\r
+ int hash = this.pattern.pattern().hashCode();\r
+ hash ^= this.pattern.flags();\r
+ return hash;\r
+ }\r
+\r
+}\r