OSDN Git Service

Merge commit '2458eff3aea04f67893bc824b5cf896fbb767332'
[jindolf/Jindolf.git] / src / main / java / jp / sourceforge / jindolf / RegexPattern.java
diff --git a/src/main/java/jp/sourceforge/jindolf/RegexPattern.java b/src/main/java/jp/sourceforge/jindolf/RegexPattern.java
new file mode 100644 (file)
index 0000000..60de2b1
--- /dev/null
@@ -0,0 +1,301 @@
+/*\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