/* * ---------- * OPTIONS * ---------- */ private static void FillField(object instance, FieldInfo f, string value) { //--Verbose if (verbose) { ArgumentParser.Option opt = f.GetAnnotation <ArgumentParser.Option>(); StringBuilder b = new StringBuilder("setting ").Append(f.DeclaringType.FullName).Append('#').Append(f.Name).Append(' '); if (opt != null) { b.Append('[').Append(opt.Name()).Append("] "); } b.Append("to: ").Append(value); Redwood.Util.Log(b.ToString()); } try { //--Permissions bool accessState = true; if (Modifier.IsFinal(f.GetModifiers())) { Redwood.Util.RuntimeException("Option cannot be final: " + f); } if (!f.IsAccessible()) { accessState = false; f.SetAccessible(true); } //--Set Value object objVal = MetaClass.Cast(value, f.GetGenericType()); if (objVal != null) { if (objVal.GetType().IsArray) { //(case: array) object[] array = (object[])objVal; // error check if (!f.GetType().IsArray) { Redwood.Util.RuntimeException("Setting an array to a non-array field. field: " + f + " value: " + Arrays.ToString(array) + " src: " + value); } // create specific array object toSet = System.Array.CreateInstance(f.GetType().GetElementType(), array.Length); for (int i = 0; i < array.Length; i++) { Sharpen.Runtime.SetArrayValue(toSet, i, array[i]); } // set value f.SetValue(instance, toSet); } else { //case: not array f.SetValue(instance, objVal); } } else { Redwood.Util.RuntimeException("Cannot assign option field: " + f + " value: " + value + "; invalid type"); } //--Permissions if (!accessState) { f.SetAccessible(false); } } catch (ArgumentException e) { Redwood.Util.Err(e); Redwood.Util.RuntimeException("Cannot assign option field: " + f.DeclaringType.GetCanonicalName() + '.' + f.Name + " value: " + value + " cause: " + e.Message); } catch (MemberAccessException e) { Redwood.Util.Err(e); Redwood.Util.RuntimeException("Cannot access option field: " + f.DeclaringType.GetCanonicalName() + '.' + f.Name); } catch (Exception e) { Redwood.Util.Err(e); Redwood.Util.RuntimeException("Cannot assign option field: " + f.DeclaringType.GetCanonicalName() + '.' + f.Name + " value: " + value + " cause: " + e.Message); } }
private static IDictionary <string, FieldInfo> FillOptionsImpl(object[] instances, Type[] classes, Properties options, bool ensureAllOptions, bool isBootstrap) { // Print usage, if applicable if (!isBootstrap) { if (Sharpen.Runtime.EqualsIgnoreCase("true", options.GetProperty("usage", "false")) || Sharpen.Runtime.EqualsIgnoreCase("true", options.GetProperty("help", "false"))) { ICollection <Type> allClasses = new HashSet <Type>(); Java.Util.Collections.AddAll(allClasses, classes); if (instances != null) { foreach (object o in instances) { allClasses.Add(o.GetType()); } } System.Console.Error.WriteLine(Usage(Sharpen.Collections.ToArray(allClasses, new Type[0]))); System.Environment.Exit(0); } } //--Create Class->Object Mapping IDictionary <Type, object> class2object = new Dictionary <Type, object>(); if (instances != null) { for (int i = 0; i < classes.Length; ++i) { System.Diagnostics.Debug.Assert(instances[i].GetType() == classes[i]); class2object[classes[i]] = instances[i]; Type mySuper = instances[i].GetType().BaseType; while (mySuper != null && !mySuper.Equals(typeof(object))) { if (!class2object.Contains(mySuper)) { class2object[mySuper] = instances[i]; } mySuper = mySuper.BaseType; } } } //--Get Fillable Options IDictionary <string, FieldInfo> canFill = new Dictionary <string, FieldInfo>(); IDictionary <string, Pair <bool, bool> > required = new Dictionary <string, Pair <bool, bool> >(); /* <exists, is_set> */ IDictionary <string, string> interner = new Dictionary <string, string>(); foreach (Type c in classes) { FieldInfo[] fields; try { fields = ScrapeFields(c); } catch (Exception e) { Redwood.Util.Debug("Could not check fields for class: " + c.FullName + " (caused by " + e.GetType() + ": " + e.Message + ')'); continue; } bool someOptionFilled = false; bool someOptionFound = false; foreach (FieldInfo f in fields) { ArgumentParser.Option o = f.GetAnnotation <ArgumentParser.Option>(); if (o != null) { someOptionFound = true; //(check if field is static) if ((f.GetModifiers() & Modifier.Static) == 0 && instances == null) { continue; } someOptionFilled = true; //(required marker) Pair <bool, bool> mark = Pair.MakePair(false, false); if (o.Required()) { mark = Pair.MakePair(true, false); } //(add main name) string name = o.Name().ToLower(); if (name.IsEmpty()) { name = f.Name.ToLower(); } if (canFill.Contains(name)) { string name1 = canFill[name].DeclaringType.GetCanonicalName() + '.' + canFill[name].Name; string name2 = f.DeclaringType.GetCanonicalName() + '.' + f.Name; if (!name1.Equals(name2)) { Redwood.Util.RuntimeException("Multiple declarations of option " + name + ": " + name1 + " and " + name2); } else { Redwood.Util.Err("Class is in classpath multiple times: " + canFill[name].DeclaringType.GetCanonicalName()); } } canFill[name] = f; required[name] = mark; interner[name] = name; //(add alternate names) if (!o.Alt().IsEmpty()) { foreach (string alt in o.Alt().Split(" *, *")) { alt = alt.ToLower(); if (canFill.Contains(alt) && !alt.Equals(name)) { throw new ArgumentException("Multiple declarations of option " + alt + ": " + canFill[alt] + " and " + f); } canFill[alt] = f; if (mark.first) { required[alt] = mark; } interner[alt] = name; } } } } //(check to ensure that something got filled, if any @Option annotation was found) if (someOptionFound && !someOptionFilled) { Redwood.Util.Warn("found @Option annotations in class " + c + ", but didn't set any of them (all options were instance variables and no instance given?)"); } } //--Fill Options foreach (KeyValuePair <object, object> entry in options) { string rawKeyStr = entry.Key.ToString(); string key = rawKeyStr.ToLower(); // (get values) string value = entry.Value.ToString(); System.Diagnostics.Debug.Assert(value != null); FieldInfo target = canFill[key]; // (mark required option as fulfilled) Pair <bool, bool> mark = required[key]; if (mark != null && mark.first) { required[key] = Pair.MakePair(true, true); } // (fill the field) if (target != null) { // (case: declared option) FillField(class2object[target.DeclaringType], target, value); } else { if (ensureAllOptions) { // (case: undeclared option) // split the key int lastDotIndex = rawKeyStr.LastIndexOf('.'); if (lastDotIndex < 0) { Redwood.Util.Err("Unrecognized option: " + key); continue; } if (!rawKeyStr.StartsWith("log.")) { // ignore Redwood options string className = Sharpen.Runtime.Substring(rawKeyStr, 0, lastDotIndex); // get the class Type clazz = null; try { clazz = ClassLoader.GetSystemClassLoader().LoadClass(className); } catch (Exception) { Redwood.Util.Err("Could not set option: " + entry.Key + "; either the option is mistyped, not defined, or the class " + className + " does not exist."); } // get the field if (clazz != null) { string fieldName = Sharpen.Runtime.Substring(rawKeyStr, lastDotIndex + 1); try { target = clazz.GetField(fieldName); } catch (Exception) { Redwood.Util.Err("Could not set option: " + entry.Key + "; no such field: " + fieldName + " in class: " + className); } if (target != null) { Redwood.Util.Log("option overrides " + target + " to '" + value + '\''); FillField(class2object[target.DeclaringType], target, value); } else { Redwood.Util.Err("Could not set option: " + entry.Key + "; no such field: " + fieldName + " in class: " + className); } } } } } } //--Ensure Required bool good = true; foreach (KeyValuePair <string, Pair <bool, bool> > entry_1 in required) { string key = entry_1.Key; Pair <bool, bool> mark = entry_1.Value; if (mark.first && !mark.second) { Redwood.Util.Err("Missing required option: " + interner[key] + " <in class: " + canFill[key].DeclaringType + '>'); required[key] = Pair.MakePair(true, true); //don't duplicate error messages good = false; } } if (!good) { throw new Exception("Specified properties are not parsable or not valid!"); } //System.exit(1); return(canFill); }