2006-11-02 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Protocols / PatternMatcher.cs
1 // \r
2 // System.Web.Services.Protocols.PatternMatcher.cs\r
3 //\r
4 // Author:\r
5 //   Tim Coleman (tim@timcoleman.com)\r
6 //\r
7 // Copyright (C) Tim Coleman, 2002\r
8 //\r
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 \r
31 using System.Web.Services;\r
32 using System.Reflection;\r
33 using System.Text.RegularExpressions;\r
34 using System.Collections;\r
35 \r
36 namespace System.Web.Services.Protocols \r
37 {\r
38         public sealed class PatternMatcher \r
39         {\r
40                 Type _returnType;\r
41                 MatchInfo[] _matchInfos;\r
42                 \r
43                 public PatternMatcher (Type type) \r
44                 {\r
45                         _returnType = type;\r
46                         \r
47                         FieldInfo[] fields = type.GetFields ();\r
48                         ArrayList matchInfos = new ArrayList ();\r
49                         \r
50                         foreach (FieldInfo field in fields)\r
51                         {\r
52                                 object[] ats = field.GetCustomAttributes (typeof(MatchAttribute), true);\r
53                                 if (ats.Length == 0) continue;\r
54                                 \r
55                                 MatchInfo mi = new MatchInfo ();\r
56                                 mi.Field = field;\r
57                                 mi.Match = (MatchAttribute) ats[0];\r
58                                 \r
59                                 RegexOptions opts = RegexOptions.Multiline;\r
60                                 if (mi.Match.IgnoreCase) opts |= RegexOptions.IgnoreCase;\r
61                                 mi.Regex = new Regex (mi.Match.Pattern, opts);\r
62                                 \r
63                                 matchInfos.Add (mi);\r
64                         }\r
65                         _matchInfos = (MatchInfo[]) matchInfos.ToArray (typeof(MatchInfo));\r
66                 }\r
67                 \r
68                 public object Match (string text)\r
69                 {\r
70                         object ob = Activator.CreateInstance (_returnType);\r
71                         \r
72                         foreach (MatchInfo mi in _matchInfos)\r
73                         {\r
74                                 MatchCollection matches = mi.Regex.Matches (text);\r
75                                 \r
76                                 object res = null;\r
77                                 \r
78                                 if (mi.Field.FieldType.IsArray)\r
79                                 {\r
80                                         int max = mi.Match.MaxRepeats;\r
81                                         if (max == -1) max = matches.Count;\r
82                                         \r
83                                         Type elemType = mi.Field.FieldType.GetElementType();\r
84                                         Array array = Array.CreateInstance (elemType, max);\r
85                                         for (int n=0; n<max; n++)\r
86                                                 array.SetValue (mi.GetMatchValue (matches[n], elemType), n);\r
87                                         res = array;\r
88                                 }\r
89                                 else if (matches.Count > 0)\r
90                                         res = mi.GetMatchValue (matches[0], mi.Field.FieldType);\r
91                                         \r
92                                 mi.Field.SetValue (ob, res);\r
93                         }\r
94                         return ob;\r
95                 }\r
96 \r
97         }\r
98 \r
99         class MatchInfo\r
100         {\r
101                 public FieldInfo Field;\r
102                 public MatchAttribute Match;\r
103                 public Regex Regex;\r
104                 \r
105                 const string GroupError = "{0} is not a valid group index for match '{1}'. The highest valid group index for this match is {2}";\r
106                 const string CaptureError = "{0} is not a valid capture index for match '{1}'. The highest valid capture index for this match is {2}";\r
107                 \r
108                 public object GetMatchValue (Match match, Type castType)\r
109                 {\r
110                         if (Match.Group >= match.Groups.Count)\r
111                                 throw new Exception (string.Format (GroupError, Match.Group, Field.Name, match.Groups.Count-1));\r
112                                 \r
113                         Group group = match.Groups [Match.Group];\r
114                         if (Match.Capture >= group.Captures.Count)\r
115                                 throw new Exception (string.Format (CaptureError, Match.Capture, Field.Name, group.Captures.Count-1));\r
116                                 \r
117                         string val = group.Captures [Match.Capture].Value;\r
118                         return Convert.ChangeType (val, castType);\r
119                 }\r
120         }\r
121 \r
122 }\r