OSDN Git Service

クラスメンバ定義順統一
[jindolf/Jindolf.git] / src / main / java / jp / sourceforge / jindolf / RegexPattern.java
1 /*\r
2  * Regex pattern\r
3  *\r
4  * License : The MIT License\r
5  * Copyright(c) 2008 olyutorskii\r
6  */\r
7 \r
8 package jp.sourceforge.jindolf;\r
9 \r
10 import java.util.regex.Pattern;\r
11 import java.util.regex.PatternSyntaxException;\r
12 import jp.sourceforge.jindolf.json.JsBoolean;\r
13 import jp.sourceforge.jindolf.json.JsObject;\r
14 import jp.sourceforge.jindolf.json.JsPair;\r
15 import jp.sourceforge.jindolf.json.JsString;\r
16 import jp.sourceforge.jindolf.json.JsValue;\r
17 \r
18 /**\r
19  * 正規表現。\r
20  */\r
21 public class RegexPattern{\r
22 \r
23     /** 英字大小無視指定フラグ。 */\r
24     public static final int IGNORECASEFLAG =\r
25             0x00000000 | Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE;\r
26     private static final String REGEX_DELIM = "[\\s\u3000]+"; // 空白(全角含)\r
27     private static final String REGEX_CHAR = ".?+*\\$(|)[]{}^-&";\r
28 \r
29 \r
30     private final String editSource;\r
31     private final boolean isRegex;\r
32     private final Pattern pattern;\r
33     private final String comment;\r
34 \r
35 \r
36     /**\r
37      * コンストラクタ。\r
38      *\r
39      * @param editSource リテラル文字列または正規表現\r
40      * @param isRegex 指定文字列が正規表現ならtrue。リテラルならfalse\r
41      * @param flag 正規表現フラグ\r
42      * @param comment コメント\r
43      * @throws java.util.regex.PatternSyntaxException 正規表現がおかしい\r
44      */\r
45     public RegexPattern(String editSource,\r
46                         boolean isRegex,\r
47                         int flag,\r
48                         String comment)\r
49             throws PatternSyntaxException{\r
50         super();\r
51         if(editSource == null) throw new NullPointerException();\r
52 \r
53         this.isRegex    = isRegex;\r
54         if(comment != null) this.comment = comment;\r
55         else                this.comment = "";\r
56 \r
57         String regexExpr;\r
58         if(this.isRegex){\r
59             this.editSource = editSource;\r
60             regexExpr = this.editSource;\r
61         }else{\r
62             String newSource = "";\r
63             regexExpr = "";\r
64 \r
65             String[] tokens = editSource.split(REGEX_DELIM);\r
66             for(String token : tokens){\r
67                 if(token == null || token.length() <= 0) continue;\r
68 \r
69                 if(newSource.length() <= 0) newSource  =       token;\r
70                 else                        newSource += " " + token;\r
71 \r
72                 String quoted = "(?:" + quote(token) + ")";\r
73                 if(regexExpr.length() <= 0) regexExpr  =       quoted;\r
74                 else                        regexExpr += "|" + quoted;\r
75             }\r
76 \r
77             this.editSource = newSource;\r
78         }\r
79 \r
80         this.pattern = Pattern.compile(regexExpr, flag);\r
81 \r
82         return;\r
83     }\r
84 \r
85     /**\r
86      * コンストラクタ。\r
87      *\r
88      * @param editSource リテラル文字列または正規表現\r
89      * @param isRegex 指定文字列が正規表現ならtrue。リテラルならfalse\r
90      * @param flag 正規表現フラグ\r
91      * @throws java.util.regex.PatternSyntaxException 正規表現がおかしい\r
92      */\r
93     public RegexPattern(String editSource,\r
94                         boolean isRegex,\r
95                         int flag )\r
96             throws PatternSyntaxException{\r
97         this(editSource, isRegex, flag, " ");\r
98         return;\r
99     }\r
100 \r
101 \r
102     /**\r
103      * 正規表現とまぎらわしい字を含むか判定する。\r
104      * @param seq 文字列\r
105      * @return 紛らわしい字を含むならtrue\r
106      */\r
107     public static boolean hasRegexChar(CharSequence seq){\r
108         int length = seq.length();\r
109         for(int pt = 0; pt < length; pt++){\r
110             char ch = seq.charAt(pt);\r
111             if(REGEX_CHAR.indexOf(ch) >= 0) return true;\r
112         }\r
113         return false;\r
114     }\r
115 \r
116     /**\r
117      * 任意の文字列を必要に応じて正規表現シーケンス化する。\r
118      * @param text 文字列\r
119      * @return 引数と同じ内容の正規表現。必要がなければ引数そのまま\r
120      */\r
121     public static String quote(String text){\r
122         if(hasRegexChar(text)){\r
123             return Pattern.quote(text);\r
124         }\r
125         return text;\r
126     }\r
127 \r
128     /**\r
129      * JSON形式に変換する。\r
130      * @param regex 正規表現\r
131      * @return JSON Object\r
132      */\r
133     public static JsObject encodeJson(RegexPattern regex){\r
134         JsObject result = new JsObject();\r
135 \r
136         int regexFlag = regex.getRegexFlag();\r
137         boolean flagDotall     = (regexFlag & Pattern.DOTALL)           != 0;\r
138         boolean flagMultiline  = (regexFlag & Pattern.MULTILINE)        != 0;\r
139         boolean flagIgnoreCase = (regexFlag & IGNORECASEFLAG) != 0;\r
140 \r
141         JsPair source     = new JsPair("source",     regex.getEditSource());\r
142         JsPair isRegex    = new JsPair("isRegex",    regex.isRegex());\r
143         JsPair dotall     = new JsPair("dotall",     flagDotall);\r
144         JsPair multiline  = new JsPair("multiline",  flagMultiline);\r
145         JsPair ignorecase = new JsPair("ignorecase", flagIgnoreCase);\r
146         JsPair comment    = new JsPair("comment",    regex.getComment());\r
147 \r
148         result.putPair(source);\r
149         result.putPair(isRegex);\r
150         result.putPair(dotall);\r
151         result.putPair(multiline);\r
152         result.putPair(ignorecase);\r
153         result.putPair(comment);\r
154 \r
155         return result;\r
156     }\r
157 \r
158     /**\r
159      * JSON形式から復元する。\r
160      * @param object JSON Object\r
161      * @return 正規表現\r
162      */\r
163     public static RegexPattern decodeJson(JsObject object){\r
164         JsValue value;\r
165 \r
166         String source;\r
167         value = object.getValue("source");\r
168         if(value instanceof JsString){\r
169             source = ((JsString)value).toRawString();\r
170         }else{\r
171             source = "";\r
172         }\r
173 \r
174         boolean isRegex;\r
175         value = object.getValue("isRegex");\r
176         if(value instanceof JsBoolean){\r
177             isRegex = ((JsBoolean)value).booleanValue();\r
178         }else{\r
179             isRegex = false;\r
180         }\r
181 \r
182         int regexFlag = 0x00000000;\r
183         value = object.getValue("dotall");\r
184         if(value instanceof JsBoolean){\r
185             if(((JsBoolean)value).isTrue()){\r
186                 regexFlag |= Pattern.DOTALL;\r
187             }\r
188         }\r
189         value = object.getValue("multiline");\r
190         if(value instanceof JsBoolean){\r
191             if(((JsBoolean)value).isTrue()){\r
192                 regexFlag |= Pattern.MULTILINE;\r
193             }\r
194         }\r
195         value = object.getValue("ignorecase");\r
196         if(value instanceof JsBoolean){\r
197             if(((JsBoolean)value).isTrue()){\r
198                 regexFlag |= IGNORECASEFLAG;\r
199             }\r
200         }\r
201 \r
202         String comment;\r
203         value = object.getValue("comment");\r
204         if(value instanceof JsString){\r
205             comment = ((JsString)value).toRawString();\r
206         }else{\r
207             comment = "";\r
208         }\r
209 \r
210         RegexPattern result =\r
211                 new RegexPattern(source, isRegex, regexFlag, comment);\r
212 \r
213         return result;\r
214     }\r
215 \r
216 \r
217     /**\r
218      * 元の入力文字列を返す。\r
219      * @return 入力文字列\r
220      */\r
221     public String getEditSource(){\r
222         return this.editSource;\r
223     }\r
224 \r
225     /**\r
226      * コメントを返す。\r
227      * @return コメント\r
228      */\r
229     public String getComment(){\r
230         return this.comment;\r
231     }\r
232 \r
233     /**\r
234      * 元の入力文字列が正規表現か否か返す。\r
235      * @return 正規表現ならtrue\r
236      */\r
237     public boolean isRegex(){\r
238         return this.isRegex;\r
239     }\r
240 \r
241     /**\r
242      * 正規表現フラグを返す。\r
243      * @return 正規表現フラグ。\r
244      * @see java.util.regex.Pattern#flags()\r
245      */\r
246     public int getRegexFlag(){\r
247         return this.pattern.flags();\r
248     }\r
249 \r
250     /**\r
251      * コンパイルされた正規表現形式を返す。\r
252      * @return コンパイルされた正規表現形式\r
253      */\r
254     public Pattern getPattern(){\r
255         return this.pattern;\r
256     }\r
257 \r
258     /**\r
259      * {@inheritDoc}\r
260      * @return {@inheritDoc}\r
261      */\r
262     @Override\r
263     public String toString(){\r
264         return this.editSource;\r
265     }\r
266 \r
267     /**\r
268      * {@inheritDoc}\r
269      * @param obj {@inheritDoc}\r
270      * @return {@inheritDoc}\r
271      */\r
272     @Override\r
273     public boolean equals(Object obj){\r
274         if(obj == null){\r
275             return false;\r
276         }\r
277         if( ! (obj instanceof RegexPattern) ){\r
278             return false;\r
279         }\r
280         RegexPattern other = (RegexPattern) obj;\r
281 \r
282         String thisPattern = this.pattern.pattern();\r
283         String otherPattern = other.pattern.pattern();\r
284 \r
285         if( ! thisPattern.equals(otherPattern) ) return false;\r
286 \r
287         if(this.pattern.flags() != other.pattern.flags()) return false;\r
288 \r
289         return true;\r
290     }\r
291 \r
292     /**\r
293      * {@inheritDoc}\r
294      * @return {@inheritDoc}\r
295      */\r
296     @Override\r
297     public int hashCode(){\r
298         int hash = this.pattern.pattern().hashCode();\r
299         hash ^= this.pattern.flags();\r
300         return hash;\r
301     }\r
302 \r
303 }\r