示例#1
0
 /*
  * ----------
  * 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);
     }
 }
示例#2
0
        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);
        }