2004-05-05 Gonzalo Paniagua Javier <gonzalo@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 \r
10 using System.Web.Services;\r
11 using System.Reflection;\r
12 using System.Text.RegularExpressions;\r
13 using System.Collections;\r
14 \r
15 namespace System.Web.Services.Protocols \r
16 {\r
17         public sealed class PatternMatcher \r
18         {\r
19                 Type _returnType;\r
20                 MatchInfo[] _matchInfos;\r
21                 \r
22                 public PatternMatcher (Type type) \r
23                 {\r
24                         _returnType = type;\r
25                         \r
26                         FieldInfo[] fields = type.GetFields ();\r
27                         ArrayList matchInfos = new ArrayList ();\r
28                         \r
29                         foreach (FieldInfo field in fields)\r
30                         {\r
31                                 object[] ats = field.GetCustomAttributes (typeof(MatchAttribute), true);\r
32                                 if (ats.Length == 0) continue;\r
33                                 \r
34                                 MatchInfo mi = new MatchInfo ();\r
35                                 mi.Field = field;\r
36                                 mi.Match = (MatchAttribute) ats[0];\r
37                                 \r
38                                 RegexOptions opts = RegexOptions.Multiline;\r
39                                 if (mi.Match.IgnoreCase) opts |= RegexOptions.IgnoreCase;\r
40                                 mi.Regex = new Regex (mi.Match.Pattern, opts);\r
41                                 \r
42                                 matchInfos.Add (mi);\r
43                         }\r
44                         _matchInfos = (MatchInfo[]) matchInfos.ToArray (typeof(MatchInfo));\r
45                 }\r
46                 \r
47                 public object Match (string text)\r
48                 {\r
49                         object ob = Activator.CreateInstance (_returnType);\r
50                         \r
51                         foreach (MatchInfo mi in _matchInfos)\r
52                         {\r
53                                 MatchCollection matches = mi.Regex.Matches (text);\r
54                                 \r
55                                 object res = null;\r
56                                 \r
57                                 if (mi.Field.FieldType.IsArray)\r
58                                 {\r
59                                         int max = mi.Match.MaxRepeats;\r
60                                         if (max == -1) max = matches.Count;\r
61                                         \r
62                                         Type elemType = mi.Field.FieldType.GetElementType();\r
63                                         Array array = Array.CreateInstance (elemType, max);\r
64                                         for (int n=0; n<max; n++)\r
65                                                 array.SetValue (mi.GetMatchValue (matches[n], elemType), n);\r
66                                         res = array;\r
67                                 }\r
68                                 else if (matches.Count > 0)\r
69                                         res = mi.GetMatchValue (matches[0], mi.Field.FieldType);\r
70                                         \r
71                                 mi.Field.SetValue (ob, res);\r
72                         }\r
73                         return ob;\r
74                 }\r
75 \r
76         }\r
77 \r
78         class MatchInfo\r
79         {\r
80                 public FieldInfo Field;\r
81                 public MatchAttribute Match;\r
82                 public Regex Regex;\r
83                 \r
84                 const string GroupError = "{0} is not a valid group index for match '{1}'. The highest valid group index for this match is {2}";\r
85                 const string CaptureError = "{0} is not a valid capture index for match '{1}'. The highest valid capture index for this match is {2}";\r
86                 \r
87                 public object GetMatchValue (Match match, Type castType)\r
88                 {\r
89                         if (Match.Group >= match.Groups.Count)\r
90                                 throw new Exception (string.Format (GroupError, Match.Group, Field.Name, match.Groups.Count-1));\r
91                                 \r
92                         Group group = match.Groups [Match.Group];\r
93                         if (Match.Capture >= group.Captures.Count)\r
94                                 throw new Exception (string.Format (CaptureError, Match.Capture, Field.Name, group.Captures.Count-1));\r
95                                 \r
96                         string val = group.Captures [Match.Capture].Value;\r
97                         return Convert.ChangeType (val, castType);\r
98                 }\r
99         }\r
100 \r
101 }\r