private static String getLongName(IPropertyInfo propertyInfo) {
   String shortName = makeCmdLineOptionName(propertyInfo);
   if (propertyInfo.hasAnnotation(TypeSystem.get(LongName.class))) {
     IAnnotationInfo annotation =
         propertyInfo.getAnnotationsOfType(TypeSystem.get(LongName.class)).get(0);
     LongName value = (LongName) annotation.getInstance();
     shortName = value.name();
   }
   return shortName;
 }
 private static boolean needsArg(IPropertyInfo propertyInfo) {
   boolean requiresArgument = true;
   if (isBooleanProp(propertyInfo)) {
     requiresArgument = false;
   } else if (propertyInfo.getFeatureType().isArray()) {
     requiresArgument = false;
   } else if (propertyInfo.hasAnnotation(TypeSystem.get(ArgOptional.class))) {
     requiresArgument = false;
   }
   return requiresArgument;
 }
  /**
   * 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;
  }
  private static Options deriveOptionsFromTypeInfo(
      ITypeInfo typeInfo, /*IN-OUT*/ List<IPropertyInfo> propsToSet, boolean useStaticProps) {
    List<? extends IPropertyInfo> propertyInfos = typeInfo.getProperties();
    Options options = new Options();
    for (IPropertyInfo propertyInfo : propertyInfos) {
      if (propertyInfo instanceof IGosuVarPropertyInfo) {
        IGosuVarPropertyInfo gsVarPropInfo = (IGosuVarPropertyInfo) propertyInfo;
        if (gsVarPropInfo.hasDeclaredProperty() || gsVarPropInfo.isFinal()) {
          continue;
        }
      }
      if (useStaticProps == propertyInfo.isStatic() && propertyInfo.isWritable(null)) {
        String shortName = getShortName(propertyInfo);
        boolean needsArg = needsArg(propertyInfo);

        GosuOption opt =
            new GosuOption(
                shortName, getLongName(propertyInfo), needsArg, deriveDescription(propertyInfo));
        opt.setHidden(propertyInfo.hasAnnotation(TypeSystem.get(Hidden.class)));

        opt.setRequired(propertyInfo.hasAnnotation(TypeSystem.get(Required.class)));
        if (propertyInfo.getFeatureType().isArray()) {
          opt.setType(propertyInfo.getFeatureType().getComponentType().getName());

          if (propertyInfo.hasAnnotation(TypeSystem.get(ArgNames.class))) {
            ArgNames argNames =
                (ArgNames)
                    propertyInfo
                        .getAnnotationsOfType(TypeSystem.get(ArgNames.class))
                        .get(0)
                        .getInstance();
            if (argNames.names() != null && argNames.names().length > 0) {
              String compoundNames = "";
              for (int i = 0; i < argNames.names().length; i++) {
                if (i != 0) {
                  compoundNames += " ";
                }
                compoundNames += argNames.names()[i];
              }
              opt.setArgName(compoundNames);
              if (propertyInfo.hasAnnotation(TypeSystem.get(ArgOptional.class))) {
                opt.setOptionalArg(true);
              }
              opt.setArgs(argNames.names().length);
            }
          } else {
            opt.setArgs(Option.UNLIMITED_VALUES);
          }

          if (propertyInfo.hasAnnotation(TypeSystem.get(Separator.class))) {
            Separator argNames =
                (Separator)
                    propertyInfo
                        .getAnnotationsOfType(TypeSystem.get(Separator.class))
                        .get(0)
                        .getInstance();
            opt.setValueSeparator(argNames.value().charAt(0));
          }

        } else {
          opt.setType(propertyInfo.getFeatureType().getName());
          if (propertyInfo.hasAnnotation(TypeSystem.get(ArgNames.class))) {
            ArgNames argNames =
                (ArgNames)
                    propertyInfo
                        .getAnnotationsOfType(TypeSystem.get(ArgNames.class))
                        .get(0)
                        .getInstance();
            if (argNames.names() != null && argNames.names().length > 0) {
              opt.setArgName(argNames.names()[0]);
            }
          }
        }

        propsToSet.add(propertyInfo);
        options.addOption(opt);
      }
    }
    return options;
  }