/**
   * Initializes the properties on the given object based on the command line arguments. If the
   * object passed in is a type, static properties will be initialized.
   *
   * <p>Note that you will get -h, -help and --help for free, there is no need to explicitly include
   * a help property on your command line class.
   *
   * @param obj the class to initialize from the passed in arguments
   * @param exitOnBadArgs if true is passed in and the arguments incorrectly map to the given type,
   *     a help message will be printed and the JVM will exit with a -1 return value, otherwise a
   *     false value will be returned
   * @return true if initialization was successful
   */
  public static boolean initialize(Object obj, boolean exitOnBadArgs) {
    List<IPropertyInfo> propsToSet = new ArrayList<IPropertyInfo>();
    IType type = obj instanceof IType ? ((IType) obj) : TypeSystem.getFromObject(obj);
    ITypeInfo typeInfo = type.getTypeInfo();
    Options options = deriveOptionsFromTypeInfo(typeInfo, propsToSet, obj instanceof IType);

    CommandLineParser parser = new BasicParser();
    try {
      CommandLine cl = parser.parse(options, _args.toArray(new String[_args.size()]));
      for (IPropertyInfo propertyInfo : propsToSet) {
        propertyInfo = typeInfo.getProperty(propertyInfo.getName());
        if (isBooleanProp(propertyInfo)) {
          propertyInfo.getAccessor().setValue(obj, cl.hasOption(getShortName(propertyInfo)));
        } else {
          String defaultValue = null;
          if (propertyInfo.hasAnnotation(TypeSystem.get(DefaultValue.class))) {
            IAnnotationInfo annotationInfo =
                propertyInfo.getAnnotationsOfType(TypeSystem.get(DefaultValue.class)).get(0);
            defaultValue = ((DefaultValue) annotationInfo.getInstance()).value();
          }

          String shortName = getShortName(propertyInfo);
          Object value;
          if (propertyInfo.getFeatureType().isArray()) {
            value = cl.getOptionValues(shortName);
            if (propertyInfo.hasAnnotation(TypeSystem.get(Args.class))) {
              value = cl.getArgs();
            } else if (value == null) {
              if (defaultValue != null) {
                value = defaultValue.split(" +");
              } else {
                // Set the value to an empty array if the option is present
                if (cl.hasOption(shortName)) {
                  value = new String[0];
                }
              }
            }
          } else {
            if (!needsArg(propertyInfo) && defaultValue == null) {
              defaultValue = "";
            }
            value = cl.getOptionValue(shortName, defaultValue);
          }
          try {
            propertyInfo
                .getAccessor()
                .setValue(obj, convertValue(propertyInfo.getFeatureType(), value));
          } catch (Exception e) {
            throw new ParseException(
                "The parameter \""
                    + shortName
                    + "\" requires an argument of type "
                    + propertyInfo.getFeatureType().getRelativeName()
                    + ".  The value \""
                    + value
                    + "\" cannot be converted to this type.  Please pass in a valid value."
                    + (e.getMessage() == null ? "" : "  Error message was : " + e.getMessage()));
          }
        }
      }
    } catch (ParseException e) {
      if (exitOnBadArgs) {
        if (!e.getMessage().endsWith("-help")
            && !e.getMessage().endsWith("-h")
            && !e.getMessage().endsWith("--help")) {
          System.out.println("\nArgument problem: " + e.getMessage() + "\n");
        }
        try {
          showHelp(getCurrentProgramName(), type);
        } catch (StringIndexOutOfBoundsException e1) {
          System.out.println("Unable to print help message.  Exiting.");
        }
        if (_exitEnabled) {
          System.exit(-1);
        }
        throw new SystemExitIgnoredException();
      }
      return false;
    }

    return true;
  }
 @Override
 protected Object evaluate(Iterator args) {
   Object ctx = _root.evaluate(args);
   return _pi.getAccessor().getValue(ctx);
 }