2002-11-28 DennisHayes <dennish@raytek.com>
[mono.git] / mcs / class / Mono.GetOptions / OptionDetails.cs
1 //
2 // OptionDetails.cs
3 //
4 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
5 //
6 // (C) 2002 Rafael Teixeira
7 //
8
9 using System;
10 using System.Collections;
11 using System.IO;
12 using System.Reflection;
13
14 namespace Mono.GetOptions
15 {
16         public enum WhatToDoNext
17         {
18                 AbandonProgram,
19                 GoAhead
20         }
21
22         internal class OptionDetails : IComparable 
23         {
24                 public char ShortForm;
25                 public string LongForm;
26                 public string ShortDescription;
27                 public bool NeedsParameter;
28                 public int MaxOccurs; // negative means there is no limit
29                 public int Occurs;
30                 public Options OptionBundle;
31                 public MemberInfo MemberInfo;
32                 public ArrayList Values;
33                 public System.Type ParameterType;
34                 
35                 public override string ToString()
36                 {
37                         string optionHelp;
38                         // TODO: Yet not that good
39                         optionHelp = "  ";
40                         optionHelp += (this.ShortForm != ' ') ? "-"+this.ShortForm+" " : "   ";
41                         optionHelp += (this.LongForm != string.Empty && this.LongForm != null) ? "--"+this.LongForm : "";
42                         if (NeedsParameter)
43                         {
44                                 if (this.LongForm != string.Empty && this.LongForm != null)
45                                         optionHelp += "=PARAM"; 
46                                 else
47                                         optionHelp += "PARAM"; 
48                         }
49                         optionHelp = optionHelp.PadRight(23) + " ";
50                         optionHelp += this.ShortDescription;
51                         return optionHelp; 
52                 }
53
54                 private static System.Type TypeOfMember(MemberInfo memberInfo)
55                 {
56                         if ((memberInfo.MemberType == MemberTypes.Field && memberInfo is FieldInfo))
57                                 return ((FieldInfo)memberInfo).FieldType;
58
59                         if ((memberInfo.MemberType == MemberTypes.Property && memberInfo is PropertyInfo))
60                                 return ((PropertyInfo)memberInfo).PropertyType;
61
62                         if ((memberInfo.MemberType == MemberTypes.Method && memberInfo is MethodInfo))
63                         {
64                                 if (((MethodInfo)memberInfo).ReturnType.FullName != typeof(WhatToDoNext).FullName)
65                                         throw new NotSupportedException("Option method must return '" + typeof(WhatToDoNext).FullName + "'");
66
67                                 ParameterInfo[] parameters = ((MethodInfo)memberInfo).GetParameters();
68                                 if ((parameters == null) || (parameters.Length == 0))
69                                         return null;
70                                 else
71                                         return parameters[0].ParameterType;
72                         }
73
74                         throw new NotSupportedException("'" + memberInfo.MemberType + "' memberType is not supportted");
75                 }
76
77                 public OptionDetails(MemberInfo memberInfo, OptionAttribute option, Options optionBundle)
78                 {
79                         this.ShortForm = option.ShortForm;
80                         this.LongForm = (option.LongForm == string.Empty)? memberInfo.Name:option.LongForm;
81                         this.ShortDescription = option.ShortDescription;
82                         this.Occurs = 0;
83                         this.OptionBundle = optionBundle; 
84                         this.MemberInfo = memberInfo;
85                         this.NeedsParameter = false;
86                         this.Values = null;
87                         this.MaxOccurs = 1;
88                         this.ParameterType = TypeOfMember(memberInfo);
89
90                         if (this.ParameterType != null && this.ParameterType.FullName != "System.Boolean")
91                         {
92                                 this.NeedsParameter = true;
93                                 if (this.ParameterType.IsArray)
94                                 {
95                                         this.Values = new ArrayList();
96                                         this.MaxOccurs = option.MaxOccurs;
97                                 }
98                                 else
99                                 {
100                                         if (this.MemberInfo is MethodInfo)
101                                                 this.MaxOccurs = option.MaxOccurs;
102                                 }
103                         }
104                 }
105
106                 internal string Key
107                 {
108                         get { return ((this.ShortForm != ' ') ? this.ShortForm + "" : "") + this.LongForm; }
109                 }
110
111                 int IComparable.CompareTo(object other)
112                 {
113                         return Key.CompareTo(((OptionDetails)other).Key);
114                 }
115
116                 public void TransferValues()
117                 {
118                         if (Values != null)
119                         {
120                                 if (MemberInfo is FieldInfo)
121                                 {
122                                         ((FieldInfo)MemberInfo).SetValue(OptionBundle, Values.ToArray(ParameterType.GetElementType()));
123                                         return;
124                                 }
125
126                                 if (MemberInfo is PropertyInfo) 
127                                 {
128                                         ((PropertyInfo)MemberInfo).SetValue(OptionBundle, Values.ToArray(ParameterType.GetElementType()), null);
129                                         return;
130                                 }
131
132                                 if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, new object[] { Values.ToArray(ParameterType.GetElementType()) }) == WhatToDoNext.AbandonProgram)
133                                         System.Environment.Exit(1);
134                         }
135                 }
136
137                 private void DoIt(string parameter)
138                 {
139                         Occurs++;
140
141                         if (MaxOccurs > 0 && Occurs > MaxOccurs)
142                                 throw new IndexOutOfRangeException("Option " + ShortForm + " can be used at most " + MaxOccurs + " times");
143                         
144                         if (!NeedsParameter)
145                         {
146                                 if (MemberInfo is FieldInfo)
147                                 {
148                                         ((FieldInfo)MemberInfo).SetValue(OptionBundle, true);
149                                         return;
150                                 }
151                                 if (MemberInfo is PropertyInfo) 
152                                 {
153                                         ((PropertyInfo)MemberInfo).SetValue(OptionBundle, true, null);
154                                         return;
155                                 }
156                                 if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, null) == WhatToDoNext.AbandonProgram)
157                                         System.Environment.Exit(1);
158
159                                 return;
160                         }
161
162                         object convertedParameter = null;
163
164                         if (Values != null && parameter != null)
165                         {
166                                 convertedParameter = Convert.ChangeType(parameter, ParameterType.GetElementType());
167                                 Values.Add(convertedParameter);
168                                 return;
169                         }
170
171                         if (parameter != null)
172                                 convertedParameter = Convert.ChangeType(parameter, ParameterType);
173
174                         if (MemberInfo is FieldInfo)
175                         {
176                                 ((FieldInfo)MemberInfo).SetValue(OptionBundle, convertedParameter);
177                                 return;
178                         }
179
180                         if (MemberInfo is PropertyInfo) 
181                         {
182                                 ((PropertyInfo)MemberInfo).SetValue(OptionBundle, convertedParameter, null);
183                                 return;
184                         }
185
186                         if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, new object[] { convertedParameter }) == WhatToDoNext.AbandonProgram)
187                                 System.Environment.Exit(1);
188                 }
189
190                 public bool ProcessArgument(string arg, string nextArg)
191                 {
192                         if (arg == ("-" + ShortForm) || arg == ("--" + LongForm))
193                         {
194                                 DoIt(nextArg);
195                                 return true;
196                         }
197                         return false;
198                 }
199         }
200 }