From 9b1384eb5e70df3e6bc1fec5aed5c841adbd094b Mon Sep 17 00:00:00 2001
From: Gaetan Boismal <gaetan.boismal@forgerock.com>
Date: Thu, 11 Feb 2016 13:46:57 +0000
Subject: [PATCH] OPENDJSDK-42 Cli arguments fluent builder

---
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/SubCommand.java                         |   71 
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/MakeLDIF.java           |   57 
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/DocDescriptionSupplement.java           |    8 
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPModify.java         |   90 -
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/CommandBuilder.java                     |    2 
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/SearchRate.java         |   33 
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/Argument.java                           |  406 ++++---
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/FileBasedArgument.java                  |  121 -
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/PerformanceRunner.java  |  136 +-
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/CommonArguments.java                    |  714 +++++++++----
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFSearch.java         |   72 
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFModify.java         |   15 
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/SubCommandArgumentParser.java           |   59 
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/BooleanArgument.java                    |   53 
 opendj-sdk/opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties                     |   31 
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPSearch.java         |  220 ++--
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFDiff.java           |   13 
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/IntegerArgument.java                    |  291 +----
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ModRate.java            |   19 
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AuthRate.java           |   47 
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/StringArgument.java                     |   99 -
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPCompare.java        |   11 
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AddRate.java            |   81 
 opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPPasswordModify.java |   71 
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/ArgumentParser.java                     |  119 +
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java          |    9 
 opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/MultiChoiceArgument.java                |  202 +--
 27 files changed, 1,485 insertions(+), 1,565 deletions(-)

diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/Argument.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/Argument.java
index 8044d1d..9f0d878 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/Argument.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/Argument.java
@@ -34,6 +34,7 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
+import org.forgerock.util.Reject;
 
 /**
  * This class defines a generic argument that may be used in the argument list
@@ -41,38 +42,194 @@
  * order to provide specific functionality.
  */
 public abstract class Argument implements DocDescriptionSupplement {
-    /** Indicates whether this argument should be hidden in the usage information. */
-    private boolean isHidden;
-    /** Indicates whether this argument may be specified more than once for multiple values. */
-    private boolean isMultiValued;
-    /** Indicates whether this argument was provided in the set of command-line arguments. */
-    private boolean isPresent;
-    /** Indicates whether this argument is required to have a value. */
-    private boolean isRequired;
-    /** Indicates whether this argument requires a value. */
-    private boolean needsValue;
-    /** The default value for the argument if none other is provided. */
-    private String defaultValue;
+
+    /**
+     * An abstract base class to build a generic {@link Argument}.
+     *
+     * @param <B>
+     *         The concrete {@link ArgumentBuilder} subclass.
+     * @param <T>
+     *         The default value type of the {@link Argument}.
+     * @param <A>
+     *         The concrete {@link Argument} type to build.
+     */
+    static abstract class ArgumentBuilder<B extends ArgumentBuilder<B, T, A>, T, A extends Argument> {
+        T defaultValue;
+        LocalizableMessage description;
+        LocalizableMessage docDescriptionSupplement;
+        boolean hidden;
+        final String longIdentifier;
+        boolean multiValued;
+        boolean needsValue = true;
+        boolean required;
+        Character shortIdentifier;
+        LocalizableMessage valuePlaceholder;
+
+        ArgumentBuilder(final String longIdentifier) {
+            Reject.ifNull(longIdentifier, "An argument must have a long identifier");
+            this.longIdentifier = longIdentifier;
+        }
+
+        abstract B getThis();
+
+        /**
+         * Build the argument.
+         *
+         * @return The argument built.
+         * @throws ArgumentException
+         *         If there is a problem with any of the parameters used to
+         *         create this argument.
+         */
+        public abstract A buildArgument() throws ArgumentException;
+
+        /**
+         * Build the argument and add it to the provided {@link ArgumentParser}.
+         *
+         * @param parser
+         *         The argument parser.
+         * @return The argument built.
+         * @throws ArgumentException
+         *         If there is a problem with any of the parameters used to
+         *         create this argument.
+         */
+        public A buildAndAddToParser(final ArgumentParser parser) throws ArgumentException {
+            final A arg = buildArgument();
+            parser.addArgument(arg);
+            return arg;
+        }
+
+        /**
+         * Build the argument and add it to the provided {@link SubCommand}.
+         *
+         * @param subCommand
+         *         The sub command.
+         * @return The argument built.
+         * @throws ArgumentException
+         *         If there is a problem with any of the parameters used to
+         *         create this argument.
+         */
+        public A buildAndAddToSubCommand(final SubCommand subCommand) throws ArgumentException {
+            final A arg = buildArgument();
+            subCommand.addArgument(arg);
+            return arg;
+        }
+
+        /**
+         * Sets this argument default value.
+         *
+         * @param defaultValue
+         *         The default value.
+         * @return This builder.
+         */
+        public B defaultValue(final T defaultValue) {
+            this.defaultValue = defaultValue;
+            return getThis();
+        }
+
+        /**
+         * Sets this argument description.
+         *
+         * @param description
+         *         The localized description.
+         * @return This builder.
+         */
+        public B description(final LocalizableMessage description) {
+            this.description = description;
+            return getThis();
+        }
+
+        /**
+         * Sets a supplement to the description intended for use in generated reference documentation.
+         *
+         * @param docDescriptionSupplement
+         *         The supplement to the description for use in generated reference documentation.
+         * @return This builder.
+         */
+        public B docDescriptionSupplement(final LocalizableMessage docDescriptionSupplement) {
+            this.docDescriptionSupplement = docDescriptionSupplement;
+            return getThis();
+        }
+
+        /**
+         * Specifies that this argument is hidden.
+         *
+         * @return This builder.
+         */
+        public B hidden() {
+            this.hidden = true;
+            return getThis();
+        }
+
+        /**
+         * Specifies that this argument may have multiple values.
+         *
+         * @return This builder.
+         */
+        public B multiValued() {
+            this.multiValued = true;
+            return getThis();
+        }
+
+        /**
+         * Specifies that this argument is required.
+         *
+         * @return This builder.
+         */
+        public B required() {
+            this.required = true;
+            return getThis();
+        }
+
+        /**
+         * Sets this argument single-character identifier.
+         *
+         * @param shortIdentifier
+         *         The single-character identifier.
+         * @return This builder.
+         */
+        public B shortIdentifier(final Character shortIdentifier) {
+            this.shortIdentifier = shortIdentifier;
+            return getThis();
+        }
+
+        /**
+         * Sets this argument value placeholder, which will be used in usage information.
+         *
+         * @param valuePlaceholder
+         *         The localized value placeholder.
+         * @return This builder.
+         */
+        public B valuePlaceholder(final LocalizableMessage valuePlaceholder) {
+            this.valuePlaceholder = valuePlaceholder;
+            return getThis();
+        }
+    }
+
+    /** The long identifier for this argument. */
+    final String longIdentifier;
 
     /** The single-character identifier for this argument. */
     private final Character shortIdentifier;
-    /** The long identifier for this argument. */
-    private final String longIdentifier;
-
     /** The unique ID of the description for this argument. */
     private final LocalizableMessage description;
+    /** Indicates whether this argument should be hidden in the usage information. */
+    private final boolean isHidden;
+    /** Indicates whether this argument may be specified more than once for multiple values. */
+    private final boolean isMultiValued;
+    /** Indicates whether this argument is required to have a value. */
+    private final boolean isRequired;
+    /** Indicates whether this argument requires a value. */
+    private final boolean needsValue;
+    /** The default value for the argument if none other is provided. */
+    private final String defaultValue;
+    /** The value placeholder for this argument, which will be used in usage information. */
+    private final LocalizableMessage valuePlaceholder;
 
     /** The set of values for this argument. */
     private final LinkedList<String> values = new LinkedList<>();
 
-    /** The generic name that will be used to refer to this argument. */
-    private final String name;
-
-    /** The name of the property that can be used to set the default value. */
-    private String propertyName;
-
-    /** The value placeholder for this argument, which will be used in usage information. */
-    private LocalizableMessage valuePlaceholder;
+    /** Indicates whether this argument was provided in the set of command-line arguments. */
+    private boolean isPresent;
 
     /**
      * Indicates whether this argument was provided in the set of
@@ -80,71 +237,24 @@
      */
     private boolean isValueSetByProperty;
 
-    /**
-     * Creates a new argument with the provided information.
-     *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
-     * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param isMultiValued
-     *            Indicates whether this argument may be specified more than
-     *            once to provide multiple values.
-     * @param needsValue
-     *            Indicates whether this argument requires a value.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param defaultValue
-     *            The default value that should be used for this argument if
-     *            none is provided in a properties file or on the command line.
-     *            This may be <CODE>null</CODE> if there is no generic default.
-     * @param propertyName
-     *            The name of the property in a property file that may be used
-     *            to override the default value but will be overridden by a
-     *            command-line argument.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
-     */
-    protected Argument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired, final boolean isMultiValued,
-            final boolean needsValue, final LocalizableMessage valuePlaceholder,
-            final String defaultValue, final String propertyName,
-            final LocalizableMessage description) throws ArgumentException {
-        this.name = name;
-        this.shortIdentifier = shortIdentifier;
-        this.longIdentifier = longIdentifier;
-        this.isRequired = isRequired;
-        this.isMultiValued = isMultiValued;
-        this.needsValue = needsValue;
-        this.valuePlaceholder = valuePlaceholder;
-        this.defaultValue = defaultValue;
-        this.propertyName = propertyName;
-        this.description = description;
-        this.isValueSetByProperty = false;
-
-        if (shortIdentifier == null && longIdentifier == null) {
-            throw new ArgumentException(ERR_ARG_NO_IDENTIFIER.get(name));
-        }
+    <B extends ArgumentBuilder<B, T, A>, T, A extends Argument> Argument(final ArgumentBuilder<B, T, A> builder)
+            throws ArgumentException {
+        this.shortIdentifier = builder.shortIdentifier;
+        this.longIdentifier = builder.longIdentifier;
+        this.isRequired = builder.required;
+        this.isMultiValued = builder.multiValued;
+        this.needsValue = builder.needsValue;
+        this.valuePlaceholder = builder.valuePlaceholder;
+        this.defaultValue = builder.defaultValue != null ? String.valueOf(builder.defaultValue) : null;
+        this.description = builder.description;
+        this.isHidden = builder.hidden;
+        this.docDescriptionSupplement = builder.docDescriptionSupplement;
 
         if (needsValue && valuePlaceholder == null) {
-            throw new ArgumentException(ERR_ARG_NO_VALUE_PLACEHOLDER.get(name));
+            throw new ArgumentException(ERR_ARG_NO_VALUE_PLACEHOLDER.get(longIdentifier));
         }
 
         isPresent = false;
-        isHidden = false;
     }
 
     /**
@@ -201,11 +311,6 @@
         return docDescriptionSupplement != null ? docDescriptionSupplement : LocalizableMessage.EMPTY;
     }
 
-    @Override
-    public void setDocDescriptionSupplement(final LocalizableMessage docDescriptionSupplement) {
-        this.docDescriptionSupplement = docDescriptionSupplement;
-    }
-
     /**
      * Retrieves the value of this argument as an integer.
      *
@@ -216,19 +321,19 @@
      */
     public int getIntValue() throws ArgumentException {
         if (values.isEmpty()) {
-            throw new ArgumentException(ERR_ARG_NO_INT_VALUE.get(name));
+            throw new ArgumentException(ERR_ARG_NO_INT_VALUE.get(longIdentifier));
         }
 
         final Iterator<String> iterator = values.iterator();
         final String valueString = iterator.next();
         if (iterator.hasNext()) {
-            throw new ArgumentException(ERR_ARG_INT_MULTIPLE_VALUES.get(name));
+            throw new ArgumentException(ERR_ARG_INT_MULTIPLE_VALUES.get(longIdentifier));
         }
 
         try {
             return Integer.parseInt(valueString);
         } catch (final Exception e) {
-            throw new ArgumentException(ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, name), e);
+            throw new ArgumentException(ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, longIdentifier), e);
         }
     }
 
@@ -244,29 +349,6 @@
     }
 
     /**
-     * Retrieves the generic name that will be used to refer to this argument.
-     *
-     * @return The generic name that will be used to refer to this argument.
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Retrieves the name of a property in a properties file that may be used to
-     * set the default value for this argument if it is present. A value read
-     * from a properties file will override the default value returned from the
-     * <CODE>getDefaultValue</CODE>, but the properties file value will be
-     * overridden by a value supplied on the command line.
-     *
-     * @return The name of a property in a properties file that may be used to
-     *         set the default value for this argument if it is present.
-     */
-    public String getPropertyName() {
-        return propertyName;
-    }
-
-    /**
      * Retrieves the single-character identifier that may be used to specify the
      * value of this argument.
      *
@@ -388,44 +470,6 @@
     }
 
     /**
-     * Specifies the default value that will be used for this argument if it is
-     * not specified on the command line and it is not set from a properties
-     * file.
-     *
-     * @param defaultValue
-     *            The default value that will be used for this argument if it is
-     *            not specified on the command line and it is not set from a
-     *            properties file.
-     */
-    public void setDefaultValue(final String defaultValue) {
-        this.defaultValue = defaultValue;
-    }
-
-    /**
-     * Specifies whether this argument should be hidden from the usage
-     * information.
-     *
-     * @param isHidden
-     *            Indicates whether this argument should be hidden from the
-     *            usage information.
-     */
-    public void setHidden(final boolean isHidden) {
-        this.isHidden = isHidden;
-    }
-
-    /**
-     * Specifies whether this argument may be provided more than once on the
-     * command line to specify multiple values.
-     *
-     * @param isMultiValued
-     *            Indicates whether this argument may be provided more than once
-     *            on the command line to specify multiple values.
-     */
-    public void setMultiValued(final boolean isMultiValued) {
-        this.isMultiValued = isMultiValued;
-    }
-
-    /**
      * Specifies whether this argument is present in the parsed set of
      * command-line arguments.
      *
@@ -437,52 +481,8 @@
         this.isPresent = isPresent;
     }
 
-    /**
-     * Specifies the name of a property in a properties file that may be used to
-     * set the default value for this argument if it is present.
-     *
-     * @param propertyName
-     *            The name of a property in a properties file that may be used
-     *            to set the default value for this argument if it is present.
-     */
-    public void setPropertyName(final String propertyName) {
-        this.propertyName = propertyName;
-    }
-
-    /**
-     * Specifies whether this argument is required to have at least one value.
-     *
-     * @param isRequired
-     *            Indicates whether this argument is required to have at least
-     *            one value.
-     */
-    public void setRequired(final boolean isRequired) {
-        this.isRequired = isRequired;
-    }
-
-    /**
-     * Specifies the value placeholder that will be displayed for this argument
-     * in the generated usage information. It may be <CODE>null</CODE> only if
-     * <CODE>needsValue()</CODE> returns <CODE>false</CODE>.
-     *
-     * @param valuePlaceholder
-     *            The value placeholder that will be displayed for this argument
-     *            in the generated usage information.
-     */
-    public void setValuePlaceholder(final LocalizableMessage valuePlaceholder) {
-        this.valuePlaceholder = valuePlaceholder;
-    }
-
-    /**
-     * Specifies whether this argument was provided in the set of properties
-     * found is a properties file.
-     *
-     * @param isValueSetByProperty
-     *            Specify whether this argument was provided in the set of
-     *            properties found is a properties file.
-     */
-    public void setValueSetByProperty(final boolean isValueSetByProperty) {
-        this.isValueSetByProperty = isValueSetByProperty;
+    void valueSetByProperty() {
+        isValueSetByProperty = true;
     }
 
     /**
@@ -519,4 +519,14 @@
         sb.append(")");
         return sb.toString();
     }
+
+    @Override
+    public boolean equals(final Object arg) {
+        return this == arg || (arg instanceof Argument && ((Argument) arg).longIdentifier.equals(this.longIdentifier));
+    }
+
+    @Override
+    public int hashCode() {
+        return longIdentifier.hashCode();
+    }
 }
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/ArgumentParser.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/ArgumentParser.java
index 0cfac0c..9018fc2 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/ArgumentParser.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/ArgumentParser.java
@@ -38,10 +38,12 @@
 import java.io.PrintStream;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
@@ -68,6 +70,15 @@
 public class ArgumentParser implements ToolRefDocContainer {
 
     private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+
+    private static final Set<String> HOST_LONG_IDENTIFIERS = new HashSet<>(Arrays.asList(
+            OPTION_LONG_HOST,
+            OPTION_LONG_REFERENCED_HOST_NAME,
+            "host1",
+            "host2",
+            "hostSource",
+            "hostDestination"));
+
     /**
      * The name of the OpenDJ configuration direction in the user home
      * directory.
@@ -286,9 +297,9 @@
     public void addArgument(final Argument argument, ArgumentGroup group) throws ArgumentException {
         final Character shortID = argument.getShortIdentifier();
         if (shortID != null && shortIDMap.containsKey(shortID)) {
-            final String conflictingName = shortIDMap.get(shortID).getName();
+            final String conflictingID = shortIDMap.get(shortID).getLongIdentifier();
             throw new ArgumentException(
-                    ERR_ARGPARSER_DUPLICATE_SHORT_ID.get(argument.getName(), shortID, conflictingName));
+                    ERR_ARGPARSER_DUPLICATE_SHORT_ID.get(argument.getLongIdentifier(), shortID, conflictingID));
         }
 
         // JNR: what is the requirement for the following code?
@@ -305,16 +316,9 @@
             }
         }
 
-        String longID = argument.getLongIdentifier();
-        if (longID != null) {
-            if (!longArgumentsCaseSensitive) {
-                longID = toLowerCase(longID);
-            }
-            if (longIDMap.containsKey(longID)) {
-                final String conflictingName = longIDMap.get(longID).getName();
-                throw new ArgumentException(ERR_ARGPARSER_DUPLICATE_LONG_ID.get(
-                    argument.getName(), argument.getLongIdentifier(), conflictingName));
-            }
+        final String longID = formatLongIdentifier(argument.getLongIdentifier());
+        if (longIDMap.containsKey(longID)) {
+            throw new ArgumentException(ERR_ARGPARSER_DUPLICATE_LONG_ID.get(argument.getLongIdentifier()));
         }
 
         if (shortID != null) {
@@ -335,8 +339,10 @@
     }
 
     private BooleanArgument getVersionArgument(final boolean displayShortIdentifier) throws ArgumentException {
-        return new BooleanArgument(OPTION_LONG_PRODUCT_VERSION, displayShortIdentifier ? OPTION_SHORT_PRODUCT_VERSION
-                : null, OPTION_LONG_PRODUCT_VERSION, INFO_DESCRIPTION_PRODUCT_VERSION.get());
+        return BooleanArgument.builder(OPTION_LONG_PRODUCT_VERSION)
+                .shortIdentifier(displayShortIdentifier ? OPTION_SHORT_PRODUCT_VERSION : null)
+                .description(INFO_DESCRIPTION_PRODUCT_VERSION.get())
+                .buildArgument();
     }
 
     /**
@@ -459,7 +465,7 @@
      *         <CODE>null</CODE> if there is no such argument.
      */
     public Argument getArgumentForLongID(final String longID) {
-        return longIDMap.get(longID);
+        return longIDMap.get(formatLongIdentifier(longID));
     }
 
     /**
@@ -531,7 +537,7 @@
      * A supplement to the description for this tool
      * intended for use in generated reference documentation.
      */
-    private DocDescriptionSupplement docToolDescriptionSupplement;
+    private DocSubcommandDescriptionSupplement docToolDescriptionSupplement;
 
     @Override
     public LocalizableMessage getDocToolDescriptionSupplement() {
@@ -551,7 +557,7 @@
      * A supplement to the description for all subcommands of this tool,
      * intended for use in generated reference documentation.
      */
-    private class DocSubcommandsDescriptionSupplement implements DocDescriptionSupplement {
+    private class DocSubcommandDescriptionSupplement implements DocDescriptionSupplement {
         /** A supplement to the description intended for use in generated reference documentation. */
         private LocalizableMessage docDescriptionSupplement;
 
@@ -560,13 +566,12 @@
             return docDescriptionSupplement != null ? docDescriptionSupplement : LocalizableMessage.EMPTY;
         }
 
-        @Override
-        public void setDocDescriptionSupplement(final LocalizableMessage docDescriptionSupplement) {
+        private void setDocDescriptionSupplement(final LocalizableMessage docDescriptionSupplement) {
             this.docDescriptionSupplement = docDescriptionSupplement;
         }
     }
 
-    private DocDescriptionSupplement docSubcommandsDescriptionSupplement;
+    private DocSubcommandDescriptionSupplement docSubcommandsDescriptionSupplement;
 
     @Override
     public LocalizableMessage getDocSubcommandsDescriptionSupplement() {
@@ -582,11 +587,11 @@
         this.docSubcommandsDescriptionSupplement.setDocDescriptionSupplement(supplement);
     }
 
-    private DocDescriptionSupplement constructIfNull(DocDescriptionSupplement supplement) {
+    private DocSubcommandDescriptionSupplement constructIfNull(DocSubcommandDescriptionSupplement supplement) {
         if (supplement != null) {
             return supplement;
         }
-        return new DocSubcommandsDescriptionSupplement();
+        return new DocSubcommandDescriptionSupplement();
     }
 
     /**
@@ -708,15 +713,15 @@
                     continue;
                 }
 
-                // Return a generic FQDN for localhost as the default hostname
-                // in reference documentation.
+                final Map<String, Object> argumentMap = getArgumentMap(a);
+                // Return a generic FQDN for localhost as the default hostname in reference documentation.
                 if (isHostNameArgument(a)) {
-                    a.setDefaultValue("localhost.localdomain");
+                    argumentMap.put("default", REF_DEFAULT.get("localhost.localdomain"));
                 }
 
                 // Return a generic message as default backend type depends on the server distribution.
-                if (a.getName().equalsIgnoreCase(OPTION_LONG_BACKEND_TYPE)) {
-                    a.setDefaultValue(REF_DEFAULT_BACKEND_TYPE.get().toString());
+                if (a.getLongIdentifier().equals(OPTION_LONG_BACKEND_TYPE)) {
+                    argumentMap.put("default", REF_DEFAULT_BACKEND_TYPE.get().toString());
                 }
 
                 // The help argument should be added at the end.
@@ -725,7 +730,7 @@
                     continue;
                 }
 
-                options.add(getArgumentMap(a));
+                options.add(argumentMap);
             }
             group.put("options", options);
             if (!options.isEmpty()) {
@@ -753,13 +758,7 @@
      * @return true if this argument is for setting a hostname.
      */
     boolean isHostNameArgument(final Argument a) {
-        final String name = a.getName();
-        return name.equalsIgnoreCase(OPTION_LONG_HOST)
-                || name.equalsIgnoreCase(OPTION_LONG_REFERENCED_HOST_NAME)
-                || name.equalsIgnoreCase("host1")
-                || name.equalsIgnoreCase("host2")
-                || name.equalsIgnoreCase("hostSource")
-                || name.equalsIgnoreCase("hostDestination");
+        return HOST_LONG_IDENTIFIERS.contains(a.getLongIdentifier());
     }
 
     /**
@@ -948,7 +947,7 @@
      * @return true if the provided argument is the usage argument, false otherwise
      */
     boolean isUsageArgument(final Argument a) {
-        return usageArgument != null && usageArgument.getName().equals(a.getName());
+        return usageArgument != null && usageArgument.getLongIdentifier().equals(a.getLongIdentifier());
     }
 
     /** Prints the version. */
@@ -1063,9 +1062,7 @@
 
                 // If we're not case-sensitive, then convert the name to lowercase.
                 final String origArgName = argName;
-                if (!longArgumentsCaseSensitive) {
-                    argName = toLowerCase(argName);
-                }
+                argName = formatLongIdentifier(argName);
 
                 // Get the argument with the specified name.
                 final Argument a = longIDMap.get(argName);
@@ -1579,10 +1576,9 @@
     void normalizeArguments(final Properties argumentProperties, final List<Argument> arguments)
             throws ArgumentException {
         for (final Argument a : arguments) {
-            if (!a.isPresent()
-                    // See if there is a value in the properties that can be used
-                    && argumentProperties != null && a.getPropertyName() != null) {
-                final String value = argumentProperties.getProperty(a.getPropertyName().toLowerCase());
+            // See if there is a value in the properties that can be used
+            if (!a.isPresent() && argumentProperties != null) {
+                final String value = argumentProperties.getProperty(a.getLongIdentifier().toLowerCase());
                 final LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
                 if (value != null) {
                     boolean addValue = (a instanceof BooleanArgument) || a.valueIsAcceptable(value, invalidReason);
@@ -1591,7 +1587,7 @@
                         if (a.needsValue()) {
                             a.setPresent(true);
                         }
-                        a.setValueSetByProperty(true);
+                        a.valueSetByProperty();
                     }
                 }
             }
@@ -1604,7 +1600,7 @@
 
                 // If there is still no value and the argument is required, then that's a problem.
                 if (!a.hasValue() && a.isRequired()) {
-                    throw new ArgumentException(ERR_ARGPARSER_NO_VALUE_FOR_REQUIRED_ARG.get(a.getName()));
+                    throw new ArgumentException(ERR_ARGPARSER_NO_VALUE_FOR_REQUIRED_ARG.get(a.getLongIdentifier()));
                 }
             }
         }
@@ -1656,4 +1652,37 @@
         }
         return null;
     }
+
+    /**
+     * Replace the provided {@link Argument} from this parser by the provided {@link Argument}.
+     * If the {@link Argument} is not present in this parser, do nothing.
+     *
+     * @param argument
+     *          The {@link Argument} to replace.
+     */
+    public void replaceArgument(final Argument argument) {
+        replaceArgumentInCollections(longIDMap, shortIDMap, argumentList, argument);
+    }
+
+    void replaceArgumentInCollections(final Map<String, Argument> longIDToArg,
+            final Map<Character, Argument> shortIDToArg, final List<Argument> argumentList, final Argument argument) {
+        final String longID = formatLongIdentifier(argument.getLongIdentifier());
+        if (!longIDToArg.containsKey(longID)) {
+            return;
+        }
+        longIDToArg.put(longID, argument);
+        shortIDToArg.put(argument.getShortIdentifier(), argument);
+        argumentList.remove(argument);
+        argumentList.add(argument);
+        for (final ArgumentGroup group : argumentGroups) {
+            if (group.getArguments().contains(argument)) {
+                group.removeArgument(argument);
+                group.addArgument(argument);
+            }
+        }
+    }
+
+    String formatLongIdentifier(final String longIdentifier) {
+        return longArgumentsCaseSensitive ? longIdentifier : toLowerCase(longIdentifier);
+    }
 }
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/BooleanArgument.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/BooleanArgument.java
index 55a8ec9..4425469 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/BooleanArgument.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/BooleanArgument.java
@@ -28,7 +28,6 @@
 
 import static com.forgerock.opendj.cli.CliMessages.ERR_BOOLEANARG_NO_VALUE_ALLOWED;
 
-import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
 
 /**
@@ -39,32 +38,42 @@
  * default value will always be "false".
  */
 public final class BooleanArgument extends Argument {
+
     /**
-     * Creates a new Boolean argument with the provided information.
+     * Returns a builder which can be used for incrementally constructing a new
+     * {@link BooleanArgument}.
      *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
      * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
+     *         The long identifier that will be used to refer to this argument.
+     * @return A builder to continue building the {@link BooleanArgument}.
      */
-    public BooleanArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final LocalizableMessage description)
-            throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, false, false, false, null, String
-                .valueOf(false), null, description);
+    public static Builder builder(final String longIdentifier) {
+        return new Builder(longIdentifier);
     }
 
-    /** {@inheritDoc} */
+    /** A fluent API for incrementally constructing {@link BooleanArgument}. */
+    public static final class Builder extends ArgumentBuilder<Builder, Boolean, BooleanArgument> {
+        private Builder(final String longIdentifier) {
+            super(longIdentifier);
+            this.needsValue = false;
+            this.defaultValue = false;
+        }
+
+        @Override
+        Builder getThis() {
+            return this;
+        }
+
+        @Override
+        public BooleanArgument buildArgument() throws ArgumentException {
+            return new BooleanArgument(this);
+        }
+    }
+
+    private BooleanArgument(final Builder builder) throws ArgumentException {
+        super(builder);
+    }
+
     @Override
     public final void addValue(final String valueString) {
         if (valueString != null) {
@@ -83,7 +92,7 @@
     public boolean valueIsAcceptable(final String valueString, final LocalizableMessageBuilder invalidReason) {
         // This argument type should never have a value, so any value
         // provided will be unacceptable.
-        invalidReason.append(ERR_BOOLEANARG_NO_VALUE_ALLOWED.get(getName()));
+        invalidReason.append(ERR_BOOLEANARG_NO_VALUE_ALLOWED.get(longIdentifier));
 
         return false;
     }
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/CommandBuilder.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/CommandBuilder.java
index c37ad31..d9fb269 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/CommandBuilder.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/CommandBuilder.java
@@ -175,7 +175,7 @@
         for (final Argument arg : args) {
             // This CLI is always using SSL, and the argument has been removed from
             // the user interface
-            if ("useSSL".equals(arg.getName())) {
+            if (ArgumentConstants.OPTION_LONG_USE_SSL.equals(arg.getLongIdentifier())) {
                 continue;
             }
             String argName;
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/CommonArguments.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/CommonArguments.java
index c5502f2..bbd4453 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/CommonArguments.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/CommonArguments.java
@@ -50,8 +50,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getShowUsage() throws ArgumentException {
-        return new BooleanArgument(OPTION_LONG_HELP.toLowerCase(), OPTION_SHORT_HELP, OPTION_LONG_HELP,
-                INFO_DESCRIPTION_SHOWUSAGE.get());
+        return BooleanArgument.builder(OPTION_LONG_HELP)
+                .shortIdentifier(OPTION_SHORT_HELP)
+                .description(INFO_DESCRIPTION_SHOWUSAGE.get())
+                .buildArgument();
     }
 
     /**
@@ -62,10 +64,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getVerbose() throws ArgumentException {
-        final BooleanArgument verbose = new BooleanArgument(OPTION_LONG_VERBOSE.toLowerCase(), OPTION_SHORT_VERBOSE,
-                OPTION_LONG_VERBOSE, INFO_DESCRIPTION_VERBOSE.get());
-        verbose.setPropertyName("verbose");
-        return verbose;
+        return BooleanArgument.builder(OPTION_LONG_VERBOSE)
+                .shortIdentifier(OPTION_SHORT_VERBOSE)
+                .description(INFO_DESCRIPTION_VERBOSE.get())
+                .buildArgument();
     }
 
     /**
@@ -96,9 +98,13 @@
      */
     public static IntegerArgument getPort(final int defaultPort, final LocalizableMessage description)
             throws ArgumentException {
-        return new IntegerArgument(OPTION_LONG_PORT.toLowerCase(), OPTION_SHORT_PORT, OPTION_LONG_PORT, false, false,
-                true, INFO_PORT_PLACEHOLDER.get(), defaultPort, OPTION_LONG_PORT, true, 1, true, 65535,
-                description != null ? description : INFO_DESCRIPTION_ADMIN_PORT.get());
+        return IntegerArgument.builder(OPTION_LONG_PORT)
+                .shortIdentifier(OPTION_SHORT_PORT)
+                .description(description != null ? description : INFO_DESCRIPTION_ADMIN_PORT.get())
+                .range(1, 65535)
+                .defaultValue(defaultPort)
+                .valuePlaceholder(INFO_PORT_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -109,8 +115,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getPropertiesFile() throws ArgumentException {
-        return new StringArgument(OPTION_LONG_PROP_FILE_PATH.toLowerCase(), null, OPTION_LONG_PROP_FILE_PATH, false,
-                false, true, INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null, INFO_DESCRIPTION_PROP_FILE_PATH.get());
+        return StringArgument.builder(OPTION_LONG_PROP_FILE_PATH)
+                .description(INFO_DESCRIPTION_PROP_FILE_PATH.get())
+                .valuePlaceholder(INFO_PROP_FILE_PATH_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -121,9 +129,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getProxyAuthId() throws ArgumentException {
-        return new StringArgument("proxyauthzid", OPTION_SHORT_PROXYAUTHID, OPTION_LONG_PROXYAUTHID, false, false,
-                true, INFO_PROXYAUTHID_PLACEHOLDER.get(), null, OPTION_LONG_PROXYAUTHID,
-                INFO_DESCRIPTION_PROXYAUTHZID.get());
+        return StringArgument.builder(OPTION_LONG_PROXYAUTHID)
+                .shortIdentifier(OPTION_SHORT_PROXYAUTHID)
+                .description(INFO_DESCRIPTION_PROXYAUTHZID.get())
+                .valuePlaceholder(INFO_PROXYAUTHID_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -134,8 +144,9 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getNoPropertiesFile() throws ArgumentException {
-        return new BooleanArgument(OPTION_LONG_NO_PROP_FILE.toLowerCase(), null, OPTION_LONG_NO_PROP_FILE,
-                INFO_DESCRIPTION_NO_PROP_FILE.get());
+        return BooleanArgument.builder(OPTION_LONG_NO_PROP_FILE)
+                .description(INFO_DESCRIPTION_NO_PROP_FILE.get())
+                .buildArgument();
     }
 
     /**
@@ -147,10 +158,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getContinueOnError() throws ArgumentException {
-        final BooleanArgument continueOnError = new BooleanArgument("continueOnError", 'c', "continueOnError",
-                INFO_DESCRIPTION_CONTINUE_ON_ERROR.get());
-        continueOnError.setPropertyName("continueOnError");
-        return continueOnError;
+        return BooleanArgument.builder("continueOnError")
+                .shortIdentifier('c')
+                .description(INFO_DESCRIPTION_CONTINUE_ON_ERROR.get())
+                .buildArgument();
     }
 
     /**
@@ -161,12 +172,13 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getControl() throws ArgumentException {
-        StringArgument controlStr =
-                new StringArgument(OPTION_LONG_CONTROL.toLowerCase(), OPTION_SHORT_CONTROL, OPTION_LONG_CONTROL, false,
-                true, true, INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, OPTION_LONG_CONTROL,
-                INFO_DESCRIPTION_CONTROLS.get());
-        controlStr.setDocDescriptionSupplement(SUPPLEMENT_DESCRIPTION_CONTROLS.get());
-        return controlStr;
+        return StringArgument.builder(OPTION_LONG_CONTROL)
+                .shortIdentifier(OPTION_SHORT_CONTROL)
+                .description(INFO_DESCRIPTION_CONTROLS.get())
+                .docDescriptionSupplement(SUPPLEMENT_DESCRIPTION_CONTROLS.get())
+                .multiValued()
+                .valuePlaceholder(INFO_LDAP_CONTROL_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -177,9 +189,12 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static IntegerArgument getLdapVersion() throws ArgumentException {
-        return new IntegerArgument(OPTION_LONG_PROTOCOL_VERSION.toLowerCase(), OPTION_SHORT_PROTOCOL_VERSION,
-                OPTION_LONG_PROTOCOL_VERSION, false, false, true, INFO_PROTOCOL_VERSION_PLACEHOLDER.get(), 3,
-                OPTION_LONG_PROTOCOL_VERSION, INFO_DESCRIPTION_VERSION.get());
+        return IntegerArgument.builder(OPTION_LONG_PROTOCOL_VERSION)
+                .shortIdentifier(OPTION_SHORT_PROTOCOL_VERSION)
+                .description(INFO_DESCRIPTION_VERSION.get())
+                .defaultValue(3)
+                .valuePlaceholder(INFO_PROTOCOL_VERSION_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -190,11 +205,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getQuiet() throws ArgumentException {
-        final BooleanArgument quiet = new BooleanArgument(OPTION_LONG_QUIET, OPTION_SHORT_QUIET, OPTION_LONG_QUIET,
-                INFO_DESCRIPTION_QUIET.get());
-        quiet.setPropertyName(OPTION_LONG_QUIET);
-        return quiet;
-
+        return BooleanArgument.builder(OPTION_LONG_QUIET)
+                .shortIdentifier(OPTION_SHORT_QUIET)
+                .description(INFO_DESCRIPTION_QUIET.get())
+                .buildArgument();
     }
 
     /**
@@ -206,7 +220,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getNoOp() throws ArgumentException {
-        return new BooleanArgument("no-op", OPTION_SHORT_DRYRUN, OPTION_LONG_DRYRUN, INFO_DESCRIPTION_NOOP.get());
+        return BooleanArgument.builder(OPTION_LONG_DRYRUN)
+                .shortIdentifier(OPTION_SHORT_DRYRUN)
+                .description(INFO_DESCRIPTION_NOOP.get())
+                .buildArgument();
     }
 
     /**
@@ -218,8 +235,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getNoPrompt() throws ArgumentException {
-        return new BooleanArgument(OPTION_LONG_NO_PROMPT, OPTION_SHORT_NO_PROMPT, OPTION_LONG_NO_PROMPT,
-                INFO_DESCRIPTION_NO_PROMPT.get());
+        return BooleanArgument.builder(OPTION_LONG_NO_PROMPT)
+                .shortIdentifier(OPTION_SHORT_NO_PROMPT)
+                .description(INFO_DESCRIPTION_NO_PROMPT.get())
+                .buildArgument();
     }
 
     /**
@@ -230,8 +249,9 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getAcceptLicense() throws ArgumentException {
-        return new BooleanArgument(OPTION_LONG_ACCEPT_LICENSE, null, OPTION_LONG_ACCEPT_LICENSE,
-                INFO_OPTION_ACCEPT_LICENSE.get());
+        return BooleanArgument.builder(OPTION_LONG_ACCEPT_LICENSE)
+                .description(INFO_OPTION_ACCEPT_LICENSE.get())
+                .buildArgument();
     }
 
     /**
@@ -244,8 +264,13 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static IntegerArgument getTimeLimit() throws ArgumentException {
-        return new IntegerArgument("timelimit", 't', "timeLimit", false, false, true,
-                INFO_TIME_LIMIT_PLACEHOLDER.get(), 0, null, true, 0, false, 0, INFO_DESCRIPTION_TIME_LIMIT.get());
+        return IntegerArgument.builder("timeLimit")
+                .shortIdentifier('t')
+                .description(INFO_DESCRIPTION_TIME_LIMIT.get())
+                .lowerBound(0)
+                .defaultValue(0)
+                .valuePlaceholder(INFO_TIME_LIMIT_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -256,10 +281,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getTrustAll() throws ArgumentException {
-        final BooleanArgument trustAll = new BooleanArgument(OPTION_LONG_TRUSTALL, OPTION_SHORT_TRUSTALL,
-                OPTION_LONG_TRUSTALL, INFO_DESCRIPTION_TRUSTALL.get());
-        trustAll.setPropertyName(OPTION_LONG_TRUSTALL);
-        return trustAll;
+        return BooleanArgument.builder(OPTION_LONG_TRUSTALL)
+                .shortIdentifier(OPTION_SHORT_TRUSTALL)
+                .description(INFO_DESCRIPTION_TRUSTALL.get())
+                .buildArgument();
     }
 
     /**
@@ -272,9 +297,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getTrustManagerProviderDN() throws ArgumentException {
-        return new StringArgument("trustmanagerproviderdn", 't', "trustManagerProviderDN", false, false, true,
-                INFO_TRUST_MANAGER_PROVIDER_DN_PLACEHOLDER.get(), null, null,
-                INFO_DESCRIPTION_TRUSTMANAGER_PROVIDER_DN.get());
+        return StringArgument.builder("trustManagerProviderDN")
+                .shortIdentifier('t')
+                .description(INFO_DESCRIPTION_TRUSTMANAGER_PROVIDER_DN.get())
+                .valuePlaceholder(INFO_TRUST_MANAGER_PROVIDER_DN_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -285,9 +312,25 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getTrustStorePath() throws ArgumentException {
-        return new StringArgument("trustStorePath", OPTION_SHORT_TRUSTSTOREPATH, OPTION_LONG_TRUSTSTOREPATH, false,
-                false, true, INFO_TRUSTSTOREPATH_PLACEHOLDER.get(), null, OPTION_LONG_TRUSTSTOREPATH,
-                INFO_DESCRIPTION_TRUSTSTOREPATH.get());
+        return getTrustStorePath(null);
+    }
+
+    /**
+     * Returns the "trustStorePath" string argument initialized with the provided default value.
+     *
+     * @param defaultValue
+     *          The "trustStorePath" argument default value
+     * @return The "trustStorePath" string argument initialized with the provided default value.
+     * @throws ArgumentException
+     *             If there is a problem with any of the parameters used to create this argument.
+     */
+    public static StringArgument getTrustStorePath(final String defaultValue) throws ArgumentException {
+        return StringArgument.builder(OPTION_LONG_TRUSTSTOREPATH)
+                .shortIdentifier(OPTION_SHORT_TRUSTSTOREPATH)
+                .description(INFO_DESCRIPTION_TRUSTSTOREPATH.get())
+                .defaultValue(defaultValue)
+                .valuePlaceholder(INFO_TRUSTSTOREPATH_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -298,10 +341,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getTypesOnly() throws ArgumentException {
-        final BooleanArgument typesOnly = new BooleanArgument("typesOnly", 'A', "typesOnly",
-                INFO_DESCRIPTION_TYPES_ONLY.get());
-        typesOnly.setPropertyName("typesOnly");
-        return typesOnly;
+        return BooleanArgument.builder("typesOnly")
+                .shortIdentifier('A')
+                .description(INFO_DESCRIPTION_TYPES_ONLY.get())
+                .buildArgument();
     }
 
     /**
@@ -312,9 +355,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getTrustStorePassword() throws ArgumentException {
-        return new StringArgument("truststorepw", OPTION_SHORT_TRUSTSTORE_PWD, OPTION_LONG_TRUSTSTORE_PWD, false,
-                false, true, INFO_TRUSTSTORE_PWD_PLACEHOLDER.get(), null, OPTION_LONG_TRUSTSTORE_PWD,
-                INFO_DESCRIPTION_TRUSTSTOREPASSWORD.get());
+        return StringArgument.builder(OPTION_LONG_TRUSTSTORE_PWD)
+                .shortIdentifier(OPTION_SHORT_TRUSTSTORE_PWD)
+                .description(INFO_DESCRIPTION_TRUSTSTOREPASSWORD.get())
+                .valuePlaceholder(INFO_TRUSTSTORE_PWD_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -325,28 +370,49 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static FileBasedArgument getTrustStorePasswordFile() throws ArgumentException {
-        return new FileBasedArgument("trustStorePasswordFile", OPTION_SHORT_TRUSTSTORE_PWD_FILE,
-                OPTION_LONG_TRUSTSTORE_PWD_FILE, false, false, INFO_TRUSTSTORE_PWD_FILE_PLACEHOLDER.get(), null,
-                OPTION_LONG_TRUSTSTORE_PWD_FILE, INFO_DESCRIPTION_TRUSTSTOREPASSWORD_FILE.get());
+        return FileBasedArgument.builder(OPTION_LONG_TRUSTSTORE_PWD_FILE)
+                .shortIdentifier(OPTION_SHORT_TRUSTSTORE_PWD_FILE)
+                .description(INFO_DESCRIPTION_TRUSTSTOREPASSWORD_FILE.get())
+                .valuePlaceholder(INFO_TRUSTSTORE_PWD_FILE_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
-     * Returns the "connectTimeout" integer argument.
+     * Returns a "connectTimeout" hidden integer argument.
      *
-     * @return The "connectTimeout" argument.
+     * @return A "connectTimeout" hidden integer argument.
+     * @throws ArgumentException
+     *             If there is a problem with any of the parameters used to create this argument.
+     */
+    public static IntegerArgument getConnectTimeOutHidden() throws ArgumentException {
+        return getConnectTimeOut(true);
+    }
+
+    /**
+     * Returns a "connectTimeout" integer argument.
+     *
+     * @return A "connectTimeout" integer argument.
      * @throws ArgumentException
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static IntegerArgument getConnectTimeOut() throws ArgumentException {
-        final IntegerArgument connectTimeout = new IntegerArgument(OPTION_LONG_CONNECT_TIMEOUT, null,
-                OPTION_LONG_CONNECT_TIMEOUT, false, false, true, INFO_TIMEOUT_PLACEHOLDER.get(),
-                DEFAULT_LDAP_CONNECT_TIMEOUT, null, true, 0, false, Integer.MAX_VALUE,
-                INFO_DESCRIPTION_CONNECTION_TIMEOUT.get());
-        connectTimeout.setPropertyName(OPTION_LONG_CONNECT_TIMEOUT);
-        connectTimeout.setHidden(true);
-        return connectTimeout;
+        return getConnectTimeOut(false);
     }
 
+    private static IntegerArgument getConnectTimeOut(final boolean hidden) throws ArgumentException {
+        final IntegerArgument.Builder builder = IntegerArgument.builder(OPTION_LONG_CONNECT_TIMEOUT)
+                .description(INFO_DESCRIPTION_CONNECTION_TIMEOUT.get())
+                .lowerBound(0)
+                .defaultValue(DEFAULT_LDAP_CONNECT_TIMEOUT)
+                .valuePlaceholder(INFO_TIMEOUT_PLACEHOLDER.get());
+        if (hidden) {
+            builder.hidden();
+        }
+        return builder.buildArgument();
+    }
+
+
+
     /**
      * Returns the "cleanupservice" string argument. <br>
      * <i> N.B : the 'c' short option is also used by continueOnError, compress.</i>
@@ -356,9 +422,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getCleanupService() throws ArgumentException {
-        return new StringArgument("cleanupservice", 'c', "cleanupService", false, false, true,
-                INFO_SERVICE_NAME_PLACEHOLDER.get(), null, null,
-                INFO_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_CLEANUP.get());
+        return StringArgument.builder("cleanupService")
+                .shortIdentifier('c')
+                .description(INFO_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_CLEANUP.get())
+                .valuePlaceholder(INFO_SERVICE_NAME_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -370,10 +438,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getCLI() throws ArgumentException {
-        final BooleanArgument cli = new BooleanArgument(OPTION_LONG_CLI.toLowerCase(), OPTION_SHORT_CLI,
-                OPTION_LONG_CLI, INFO_ARGUMENT_DESCRIPTION_CLI.get());
-        cli.setPropertyName(OPTION_LONG_CLI);
-        return cli;
+        return BooleanArgument.builder(OPTION_LONG_CLI)
+                .shortIdentifier(OPTION_SHORT_CLI)
+                .description(INFO_ARGUMENT_DESCRIPTION_CLI.get())
+                .buildArgument();
     }
 
     /**
@@ -385,9 +453,13 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getConfigFile() throws ArgumentException {
-        final StringArgument configFile = new StringArgument("configfile", 'f', "configFile", true, false, true,
-                INFO_CONFIGFILE_PLACEHOLDER.get(), null, null, INFO_DESCRIPTION_CONFIG_FILE.get());
-        configFile.setHidden(true);
+        final StringArgument configFile = StringArgument.builder("configFile")
+                .shortIdentifier('f')
+                .description(INFO_DESCRIPTION_CONFIG_FILE.get())
+                .hidden()
+                .required()
+                .valuePlaceholder(INFO_CONFIGFILE_PLACEHOLDER.get())
+                .buildArgument();
         return configFile;
     }
 
@@ -401,11 +473,14 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getConfigClass(final String configFileHandlerName) throws ArgumentException {
-        final StringArgument configClass = new StringArgument("configclass", OPTION_SHORT_CONFIG_CLASS,
-                OPTION_LONG_CONFIG_CLASS, true, false, true, INFO_CONFIGCLASS_PLACEHOLDER.get(), configFileHandlerName,
-                null, INFO_DESCRIPTION_CONFIG_CLASS.get());
-        configClass.setHidden(true);
-        return configClass;
+        return StringArgument.builder(OPTION_LONG_CONFIG_CLASS)
+                .shortIdentifier(OPTION_SHORT_CONFIG_CLASS)
+                .description(INFO_DESCRIPTION_CONFIG_CLASS.get())
+                .hidden()
+                .required()
+                .defaultValue(configFileHandlerName)
+                .valuePlaceholder(INFO_CONFIGCLASS_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -417,8 +492,12 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getBackendId() throws ArgumentException {
-        return new StringArgument("backendid", 'n', "backendID", false, true, true, INFO_BACKENDNAME_PLACEHOLDER.get(),
-                null, null, INFO_BACKUPDB_DESCRIPTION_BACKEND_ID.get());
+        return StringArgument.builder("backendID")
+                .shortIdentifier('n')
+                .description(INFO_BACKUPDB_DESCRIPTION_BACKEND_ID.get())
+                .multiValued()
+                .valuePlaceholder(INFO_BACKENDNAME_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -430,8 +509,12 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getBackupDirectory() throws ArgumentException {
-        return new StringArgument("backupdirectory", 'd', "backupDirectory", true, false, true,
-                INFO_BACKUPDIR_PLACEHOLDER.get(), null, null, INFO_DESCRIPTION_BACKUP_DIR.get());
+        return StringArgument.builder("backupDirectory")
+                .shortIdentifier('d')
+                .description(INFO_DESCRIPTION_BACKUP_DIR.get())
+                .required()
+                .valuePlaceholder(INFO_BACKUPDIR_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -442,9 +525,12 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getBaseDN() throws ArgumentException {
-        return new StringArgument(OPTION_LONG_BASEDN.toLowerCase(), OPTION_SHORT_BASEDN, OPTION_LONG_BASEDN, false,
-                true, true, INFO_BASEDN_PLACEHOLDER.get(), null, OPTION_LONG_BASEDN,
-                INFO_ARGUMENT_DESCRIPTION_BASEDN.get());
+        return StringArgument.builder(OPTION_LONG_BASEDN)
+                .shortIdentifier(OPTION_SHORT_BASEDN)
+                .description(INFO_ARGUMENT_DESCRIPTION_BASEDN.get())
+                .multiValued()
+                .valuePlaceholder(INFO_BASEDN_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -455,9 +541,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getBatchFilePath() throws ArgumentException {
-        return new StringArgument(OPTION_LONG_BATCH_FILE_PATH, OPTION_SHORT_BATCH_FILE_PATH,
-                OPTION_LONG_BATCH_FILE_PATH, false, false, true, INFO_BATCH_FILE_PATH_PLACEHOLDER.get(), null, null,
-                INFO_DESCRIPTION_BATCH_FILE_PATH.get());
+        return StringArgument.builder(OPTION_LONG_BATCH_FILE_PATH)
+                .shortIdentifier(OPTION_SHORT_BATCH_FILE_PATH)
+                .description(INFO_DESCRIPTION_BATCH_FILE_PATH.get())
+                .valuePlaceholder(INFO_BATCH_FILE_PATH_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -471,8 +559,12 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getBindDN(final String defaultBindDN) throws ArgumentException {
-        return new StringArgument("bindDN", OPTION_SHORT_BINDDN, OPTION_LONG_BINDDN, false, false, true,
-                INFO_BINDDN_PLACEHOLDER.get(), defaultBindDN, OPTION_LONG_BINDDN, INFO_DESCRIPTION_BINDDN.get());
+        return StringArgument.builder(OPTION_LONG_BINDDN)
+                .shortIdentifier(OPTION_SHORT_BINDDN)
+                .description(INFO_DESCRIPTION_BINDDN.get())
+                .defaultValue(defaultBindDN)
+                .valuePlaceholder(INFO_BINDDN_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -483,8 +575,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getBindPassword() throws ArgumentException {
-        return new StringArgument("bindPassword", OPTION_SHORT_BINDPWD, OPTION_LONG_BINDPWD, false, false, true,
-                INFO_BINDPWD_PLACEHOLDER.get(), null, OPTION_LONG_BINDPWD, INFO_DESCRIPTION_BINDPASSWORD.get());
+        return StringArgument.builder(OPTION_LONG_BINDPWD)
+                .shortIdentifier(OPTION_SHORT_BINDPWD)
+                .description(INFO_DESCRIPTION_BINDPASSWORD.get())
+                .valuePlaceholder(INFO_BINDPWD_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -495,9 +590,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static FileBasedArgument getBindPasswordFile() throws ArgumentException {
-        return new FileBasedArgument("bindPasswordFile", OPTION_SHORT_BINDPWD_FILE, OPTION_LONG_BINDPWD_FILE, false,
-                false, INFO_BINDPWD_FILE_PLACEHOLDER.get(), null, OPTION_LONG_BINDPWD_FILE,
-                INFO_DESCRIPTION_BINDPASSWORDFILE.get());
+        return FileBasedArgument.builder(OPTION_LONG_BINDPWD_FILE)
+                .shortIdentifier(OPTION_SHORT_BINDPWD_FILE)
+                .description(INFO_DESCRIPTION_BINDPASSWORDFILE.get())
+                .valuePlaceholder(INFO_BINDPWD_FILE_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -509,10 +606,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getAddBaseEntry() throws ArgumentException {
-        final BooleanArgument addBaseEntryArg = new BooleanArgument("addBaseEntry".toLowerCase(), 'a', "addBaseEntry",
-                INFO_ARGUMENT_DESCRIPTION_ADDBASE.get());
-        addBaseEntryArg.setPropertyName("addBaseEntry");
-        return addBaseEntryArg;
+        return BooleanArgument.builder("addBaseEntry")
+                .shortIdentifier('a')
+                .description(INFO_ARGUMENT_DESCRIPTION_ADDBASE.get())
+                .buildArgument();
     }
 
     /**
@@ -524,8 +621,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getRejectedImportLdif() throws ArgumentException {
-        return new StringArgument("rejectFile".toLowerCase(), 'R', "rejectFile", false, false, true,
-                INFO_REJECT_FILE_PLACEHOLDER.get(), null, "rejectFile", INFO_GENERAL_DESCRIPTION_REJECTED_FILE.get());
+        return StringArgument.builder("rejectFile")
+                .shortIdentifier('R')
+                .description(INFO_GENERAL_DESCRIPTION_REJECTED_FILE.get())
+                .valuePlaceholder(INFO_REJECT_FILE_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -537,10 +637,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getRemote() throws ArgumentException {
-        final BooleanArgument remote = new BooleanArgument(OPTION_LONG_REMOTE.toLowerCase(), OPTION_SHORT_REMOTE,
-                OPTION_LONG_REMOTE, INFO_DESCRIPTION_REMOTE.get());
-        remote.setPropertyName(OPTION_LONG_REMOTE);
-        return remote;
+        return BooleanArgument.builder(OPTION_LONG_REMOTE)
+                .shortIdentifier(OPTION_SHORT_REMOTE)
+                .description(INFO_DESCRIPTION_REMOTE.get())
+                .buildArgument();
     }
 
     /**
@@ -551,10 +651,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getReportAuthzId() throws ArgumentException {
-        final BooleanArgument report = new BooleanArgument(OPTION_LONG_REPORT_AUTHZ_ID.toLowerCase(), 'E',
-                OPTION_LONG_REPORT_AUTHZ_ID, INFO_DESCRIPTION_REPORT_AUTHZID.get());
-        report.setPropertyName("reportAuthzID");
-        return report;
+        return BooleanArgument.builder(OPTION_LONG_REPORT_AUTHZ_ID)
+                .shortIdentifier('E')
+                .description(INFO_DESCRIPTION_REPORT_AUTHZID.get())
+                .buildArgument();
     }
 
     /**
@@ -566,10 +666,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getRestart() throws ArgumentException {
-        final BooleanArgument restart = new BooleanArgument(OPTION_LONG_RESTART.toLowerCase(), 'R',
-                OPTION_LONG_RESTART, INFO_DESCRIPTION_RESTART.get());
-        restart.setPropertyName(OPTION_LONG_RESTART);
-        return restart;
+        return BooleanArgument.builder(OPTION_LONG_RESTART)
+                .shortIdentifier('R')
+                .description(INFO_DESCRIPTION_RESTART.get())
+                .buildArgument();
     }
 
     /**
@@ -580,8 +680,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getSkippedImportFile() throws ArgumentException {
-        return new StringArgument("skipFile".toLowerCase(), null, "skipFile", false, false, true,
-                INFO_SKIP_FILE_PLACEHOLDER.get(), null, "skipFile", INFO_GENERAL_DESCRIPTION_SKIPPED_FILE.get());
+        return StringArgument.builder("skipFile")
+                .description(INFO_GENERAL_DESCRIPTION_SKIPPED_FILE.get())
+                .valuePlaceholder(INFO_SKIP_FILE_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -593,9 +695,13 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static IntegerArgument getSampleData() throws ArgumentException {
-        return new IntegerArgument("sampleData".toLowerCase(), 'd', "sampleData", false, false, true,
-                INFO_NUM_ENTRIES_PLACEHOLDER.get(), 0, "sampleData", true, 0, false, 0,
-                INFO_SETUP_DESCRIPTION_SAMPLE_DATA.get());
+        return IntegerArgument.builder("sampleData")
+                .shortIdentifier('d')
+                .description(INFO_SETUP_DESCRIPTION_SAMPLE_DATA.get())
+                .lowerBound(0)
+                .defaultValue(0)
+                .valuePlaceholder(INFO_NUM_ENTRIES_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -607,9 +713,12 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getSASL() throws ArgumentException {
-        return new StringArgument("sasloption", OPTION_SHORT_SASLOPTION, OPTION_LONG_SASLOPTION, false, true, true,
-                INFO_SASL_OPTION_PLACEHOLDER.get(), null, OPTION_LONG_SASLOPTION,
-                INFO_LDAP_CONN_DESCRIPTION_SASLOPTIONS.get());
+        return StringArgument.builder(OPTION_LONG_SASLOPTION)
+                .shortIdentifier(OPTION_SHORT_SASLOPTION)
+                .description(INFO_LDAP_CONN_DESCRIPTION_SASLOPTIONS.get())
+                .multiValued()
+                .valuePlaceholder(INFO_SASL_OPTION_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -621,13 +730,13 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static MultiChoiceArgument<SearchScope> getSearchScope() throws ArgumentException {
-        final MultiChoiceArgument<SearchScope> searchScope = new MultiChoiceArgument<>(
-                OPTION_LONG_SEARCHSCOPE, OPTION_SHORT_SEARCHSCOPE, OPTION_LONG_SEARCHSCOPE, false, true,
-                INFO_SEARCH_SCOPE_PLACEHOLDER.get(), SearchScope.values(), false,
-                INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE.get());
-        searchScope.setPropertyName(OPTION_LONG_SEARCHSCOPE);
-        searchScope.setDefaultValue(SearchScope.WHOLE_SUBTREE);
-        return searchScope;
+        return MultiChoiceArgument.<SearchScope>builder(OPTION_LONG_SEARCHSCOPE)
+                .shortIdentifier(OPTION_SHORT_SEARCHSCOPE)
+                .description(INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE.get())
+                .allowedValues(SearchScope.values())
+                .defaultValue(SearchScope.WHOLE_SUBTREE)
+                .valuePlaceholder(INFO_SEARCH_SCOPE_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -639,10 +748,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getServerRoot() throws ArgumentException {
-        final StringArgument serverRoot = new StringArgument("serverRoot", OPTION_SHORT_SERVER_ROOT,
-                OPTION_LONG_SERVER_ROOT, false, false, true, INFO_SERVER_ROOT_DIR_PLACEHOLDER.get(), null, null, null);
-        serverRoot.setHidden(true);
-        return serverRoot;
+        return StringArgument.builder(OPTION_LONG_SERVER_ROOT)
+                .shortIdentifier(OPTION_SHORT_SERVER_ROOT)
+                .hidden()
+                .valuePlaceholder(INFO_SERVER_ROOT_DIR_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -654,8 +764,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getServiceState() throws ArgumentException {
-        return new BooleanArgument("servicestate", 's', "serviceState",
-                INFO_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_STATE.get());
+        return BooleanArgument.builder("serviceState")
+                .shortIdentifier('s')
+                .description(INFO_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_STATE.get())
+                .buildArgument();
     }
 
     /**
@@ -667,10 +779,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getScriptFriendly() throws ArgumentException {
-        final BooleanArgument sf = new BooleanArgument("script-friendly", OPTION_SHORT_SCRIPT_FRIENDLY,
-                OPTION_LONG_SCRIPT_FRIENDLY, INFO_DESCRIPTION_SCRIPT_FRIENDLY.get());
-        sf.setPropertyName(OPTION_LONG_SCRIPT_FRIENDLY);
-        return sf;
+        return BooleanArgument.builder(OPTION_LONG_SCRIPT_FRIENDLY)
+                .shortIdentifier(OPTION_SHORT_SCRIPT_FRIENDLY)
+                .description(INFO_DESCRIPTION_SCRIPT_FRIENDLY.get())
+                .buildArgument();
     }
 
     /**
@@ -683,9 +795,13 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static IntegerArgument getLDAPPort(final int defaultLdapPort) throws ArgumentException {
-        return new IntegerArgument("ldapPort".toLowerCase(), OPTION_SHORT_PORT, "ldapPort", false, false, true,
-                INFO_PORT_PLACEHOLDER.get(), defaultLdapPort, "ldapPort", true, 1, true, 65535,
-                INFO_ARGUMENT_DESCRIPTION_LDAPPORT.get());
+        return IntegerArgument.builder("ldapPort")
+                .shortIdentifier(OPTION_SHORT_PORT)
+                .description(INFO_ARGUMENT_DESCRIPTION_LDAPPORT.get())
+                .range(1, 65535)
+                .defaultValue(defaultLdapPort)
+                .valuePlaceholder(INFO_PORT_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -698,9 +814,12 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static IntegerArgument getAdminLDAPPort(final int defaultAdminPort) throws ArgumentException {
-        return new IntegerArgument("adminConnectorPort".toLowerCase(), null, "adminConnectorPort", false, false, true,
-                INFO_PORT_PLACEHOLDER.get(), defaultAdminPort, "adminConnectorPort", true, 1, true, 65535,
-                INFO_ARGUMENT_DESCRIPTION_ADMINCONNECTORPORT.get());
+        return IntegerArgument.builder("adminConnectorPort")
+                .description(INFO_ARGUMENT_DESCRIPTION_ADMINCONNECTORPORT.get())
+                .range(1, 65535)
+                .defaultValue(defaultAdminPort)
+                .valuePlaceholder(INFO_PORT_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -711,10 +830,9 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getAdvancedMode() throws ArgumentException {
-        final BooleanArgument advanced = new BooleanArgument(OPTION_LONG_ADVANCED, null, OPTION_LONG_ADVANCED,
-                INFO_DESCRIPTION_ADVANCED.get());
-        advanced.setPropertyName(OPTION_LONG_ADVANCED);
-        return advanced;
+        return BooleanArgument.builder(OPTION_LONG_ADVANCED)
+                .description(INFO_DESCRIPTION_ADVANCED.get())
+                .buildArgument();
     }
 
     /**
@@ -725,9 +843,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getAssertionFilter() throws ArgumentException {
-        return new StringArgument("assertionfilter", null, OPTION_LONG_ASSERTION_FILE, false, false, true,
-                INFO_ASSERTION_FILTER_PLACEHOLDER.get(), null, OPTION_LONG_ASSERTION_FILE,
-                INFO_DESCRIPTION_ASSERTION_FILTER.get());
+        return StringArgument.builder(OPTION_LONG_ASSERTION_FILE)
+                .description(INFO_DESCRIPTION_ASSERTION_FILTER.get())
+                .valuePlaceholder(INFO_ASSERTION_FILTER_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -740,9 +859,13 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static IntegerArgument getJMXPort(final int defaultJMXPort) throws ArgumentException {
-        return new IntegerArgument("jmxPort".toLowerCase(), 'x', "jmxPort", false, false, true,
-                INFO_JMXPORT_PLACEHOLDER.get(), defaultJMXPort, "jmxPort", true, 1, true, 65535,
-                INFO_ARGUMENT_DESCRIPTION_SKIPPORT.get());
+        return IntegerArgument.builder("jmxPort")
+                .shortIdentifier('x')
+                .description(INFO_ARGUMENT_DESCRIPTION_SKIPPORT.get())
+                .range(1, 65535)
+                .defaultValue(defaultJMXPort)
+                .valuePlaceholder(INFO_JMXPORT_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -753,10 +876,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getSkipPortCheck() throws ArgumentException {
-        final BooleanArgument skipPortCheck = new BooleanArgument("skipPortCheck".toLowerCase(), 'S', "skipPortCheck",
-                INFO_ARGUMENT_DESCRIPTION_SKIPPORT.get());
-        skipPortCheck.setPropertyName("skipPortCheck");
-        return skipPortCheck;
+        return BooleanArgument.builder("skipPortCheck")
+                .shortIdentifier('S')
+                .description(INFO_ARGUMENT_DESCRIPTION_SKIPPORT.get())
+                .buildArgument();
     }
 
     /**
@@ -767,10 +890,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getStartTLS() throws ArgumentException {
-        final BooleanArgument useStartTLS = new BooleanArgument("startTLS", OPTION_SHORT_START_TLS,
-                OPTION_LONG_START_TLS, INFO_DESCRIPTION_START_TLS.get());
-        useStartTLS.setPropertyName(OPTION_LONG_START_TLS);
-        return useStartTLS;
+        return BooleanArgument.builder(OPTION_LONG_START_TLS)
+                .shortIdentifier(OPTION_SHORT_START_TLS)
+                .description(INFO_DESCRIPTION_START_TLS.get())
+                .buildArgument();
     }
 
     /**
@@ -782,8 +905,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getStopReason() throws ArgumentException {
-        return new StringArgument("stopreason", 'r', "stopReason", false, false, true,
-                INFO_STOP_REASON_PLACEHOLDER.get(), null, "stopReason", INFO_DESCRIPTION_STOP_REASON.get());
+        return StringArgument.builder("stopReason")
+                .shortIdentifier('r')
+                .description(INFO_DESCRIPTION_STOP_REASON.get())
+                .valuePlaceholder(INFO_STOP_REASON_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -795,8 +921,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getStopTime() throws ArgumentException {
-        return new StringArgument("stoptime", 't', "stopTime", false, false, true, INFO_STOP_TIME_PLACEHOLDER.get(),
-                null, "stopTime", INFO_DESCRIPTION_STOP_TIME.get());
+        return StringArgument.builder("stopTime")
+                .shortIdentifier('t')
+                .description(INFO_DESCRIPTION_STOP_TIME.get())
+                .valuePlaceholder(INFO_STOP_TIME_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -808,9 +937,12 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getRootDN() throws ArgumentException {
-        return new StringArgument(OPTION_LONG_ROOT_USER_DN.toLowerCase(), OPTION_SHORT_ROOT_USER_DN,
-                OPTION_LONG_ROOT_USER_DN, false, false, true, INFO_ROOT_USER_DN_PLACEHOLDER.get(),
-                "cn=Directory Manager", OPTION_LONG_ROOT_USER_DN, INFO_ARGUMENT_DESCRIPTION_ROOTDN.get());
+        return StringArgument.builder(OPTION_LONG_ROOT_USER_DN)
+                .shortIdentifier(OPTION_SHORT_ROOT_USER_DN)
+                .description(INFO_ARGUMENT_DESCRIPTION_ROOTDN.get())
+                .defaultValue("cn=Directory Manager")
+                .valuePlaceholder(INFO_ROOT_USER_DN_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -821,9 +953,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getRootDNPwd() throws ArgumentException {
-        return new StringArgument("rootUserPassword".toLowerCase(), OPTION_SHORT_BINDPWD, "rootUserPassword", false,
-                false, true, INFO_ROOT_USER_PWD_PLACEHOLDER.get(), null, "rootUserPassword",
-                INFO_ROOT_USER_PWD_PLACEHOLDER.get());
+        return StringArgument.builder("rootUserPassword")
+                .shortIdentifier(OPTION_SHORT_BINDPWD)
+                .description(INFO_ROOT_USER_PWD_PLACEHOLDER.get())
+                .valuePlaceholder(INFO_ROOT_USER_PWD_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -834,9 +968,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static FileBasedArgument getRootDNPwdFile() throws ArgumentException {
-        return new FileBasedArgument("rootUserPasswordFile".toLowerCase(), OPTION_SHORT_BINDPWD_FILE,
-                "rootUserPasswordFile", false, false, INFO_ROOT_USER_PWD_FILE_PLACEHOLDER.get(), null,
-                "rootUserPasswordFile", INFO_ARGUMENT_DESCRIPTION_ROOTPWFILE.get());
+        return FileBasedArgument.builder("rootUserPasswordFile")
+                .shortIdentifier(OPTION_SHORT_BINDPWD_FILE)
+                .description(INFO_ARGUMENT_DESCRIPTION_ROOTPWFILE.get())
+                .valuePlaceholder(INFO_ROOT_USER_PWD_FILE_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -847,10 +983,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getEnableWindowsService() throws ArgumentException {
-        final BooleanArgument enableWindowsServiceArg = new BooleanArgument("enableWindowsService".toLowerCase(), 'e',
-                "enableWindowsService", INFO_ARGUMENT_DESCRIPTION_ENABLE_WINDOWS_SERVICE.get());
-        enableWindowsServiceArg.setPropertyName("enableWindowsService");
-        return enableWindowsServiceArg;
+        return BooleanArgument.builder("enableWindowsService")
+                .shortIdentifier('e')
+                .description(INFO_ARGUMENT_DESCRIPTION_ENABLE_WINDOWS_SERVICE.get())
+                .buildArgument();
     }
 
     /**
@@ -862,8 +998,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getEncoding() throws ArgumentException {
-        return new StringArgument("encoding", 'i', "encoding", false, false, true, INFO_ENCODING_PLACEHOLDER.get(),
-                null, "encoding", INFO_DESCRIPTION_ENCODING.get());
+        return StringArgument.builder("encoding")
+                .shortIdentifier('i')
+                .description(INFO_DESCRIPTION_ENCODING.get())
+                .valuePlaceholder(INFO_ENCODING_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -874,10 +1013,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getDoNotStart() throws ArgumentException {
-        final BooleanArgument doNotStartArg = new BooleanArgument("doNotStart".toLowerCase(), 'O', "doNotStart",
-                INFO_SETUP_DESCRIPTION_DO_NOT_START.get());
-        doNotStartArg.setPropertyName("doNotStart");
-        return doNotStartArg;
+        return BooleanArgument.builder("doNotStart")
+                .shortIdentifier('O')
+                .description(INFO_SETUP_DESCRIPTION_DO_NOT_START.get())
+                .buildArgument();
     }
 
     /**
@@ -889,8 +1028,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getDisableService() throws ArgumentException {
-        return new BooleanArgument("disableservice", 'd', "disableService",
-                INFO_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_DISABLE.get());
+        return BooleanArgument.builder("disableService")
+                .shortIdentifier('d')
+                .description(INFO_CONFIGURE_WINDOWS_SERVICE_DESCRIPTION_DISABLE.get())
+                .buildArgument();
     }
 
     /**
@@ -901,8 +1042,9 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getDisplayEquivalentCommand() throws ArgumentException {
-        return new BooleanArgument(OPTION_LONG_DISPLAY_EQUIVALENT, null, OPTION_LONG_DISPLAY_EQUIVALENT,
-                INFO_DESCRIPTION_DISPLAY_EQUIVALENT.get());
+        return BooleanArgument.builder(OPTION_LONG_DISPLAY_EQUIVALENT)
+                .description(INFO_DESCRIPTION_DISPLAY_EQUIVALENT.get())
+                .buildArgument();
     }
 
     /**
@@ -916,9 +1058,10 @@
      */
     public static StringArgument getEquivalentCommandFile(final LocalizableMessage description)
             throws ArgumentException {
-        return new StringArgument(OPTION_LONG_EQUIVALENT_COMMAND_FILE_PATH, null,
-                OPTION_LONG_EQUIVALENT_COMMAND_FILE_PATH, false, false, true, INFO_PATH_PLACEHOLDER.get(), null, null,
-                description);
+        return StringArgument.builder(OPTION_LONG_EQUIVALENT_COMMAND_FILE_PATH)
+                .description(description)
+                .valuePlaceholder(INFO_PATH_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -931,8 +1074,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getFilename(final LocalizableMessage description) throws ArgumentException {
-        return new StringArgument("filename", OPTION_SHORT_FILENAME, OPTION_LONG_FILENAME, false, false, true,
-                INFO_FILE_PLACEHOLDER.get(), null, OPTION_LONG_FILENAME, description);
+        return StringArgument.builder(OPTION_LONG_FILENAME)
+                .shortIdentifier(OPTION_SHORT_FILENAME)
+                .description(description)
+                .valuePlaceholder(INFO_FILE_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -943,10 +1089,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getEnableTLS() throws ArgumentException {
-        final BooleanArgument enableStartTLS = new BooleanArgument("enableStartTLS".toLowerCase(),
-                OPTION_SHORT_START_TLS, "enableStartTLS", INFO_SETUP_DESCRIPTION_ENABLE_STARTTLS.get());
-        enableStartTLS.setPropertyName("enableStartTLS");
-        return enableStartTLS;
+        return BooleanArgument.builder("enableStartTLS")
+                .shortIdentifier(OPTION_SHORT_START_TLS)
+                .description(INFO_SETUP_DESCRIPTION_ENABLE_STARTTLS.get())
+                .buildArgument();
     }
 
     /**
@@ -960,9 +1106,13 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static IntegerArgument getLDAPSPort(final int defaultSecurePort) throws ArgumentException {
-        return new IntegerArgument("ldapsPort".toLowerCase(), OPTION_SHORT_USE_SSL, "ldapsPort", false, false, true,
-                INFO_PORT_PLACEHOLDER.get(), defaultSecurePort, "ldapsPort", true, 1, true, 65535,
-                INFO_ARGUMENT_DESCRIPTION_LDAPSPORT.get());
+        return IntegerArgument.builder("ldapsPort")
+                .shortIdentifier(OPTION_SHORT_USE_SSL)
+                .description(INFO_ARGUMENT_DESCRIPTION_LDAPSPORT.get())
+                .range(1, 65535)
+                .defaultValue(defaultSecurePort)
+                .valuePlaceholder(INFO_PORT_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -975,8 +1125,12 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getLDIFFile(final LocalizableMessage description) throws ArgumentException {
-        return new StringArgument(OPTION_LONG_LDIF_FILE.toLowerCase(), OPTION_SHORT_LDIF_FILE, OPTION_LONG_LDIF_FILE,
-                false, true, true, INFO_LDIFFILE_PLACEHOLDER.get(), null, null, description);
+        return StringArgument.builder(OPTION_LONG_LDIF_FILE)
+                .shortIdentifier(OPTION_SHORT_LDIF_FILE)
+                .description(description)
+                .multiValued()
+                .valuePlaceholder(INFO_LDIFFILE_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -987,10 +1141,9 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getGenerateSelfSigned() throws ArgumentException {
-        final BooleanArgument generateSelfSigned = new BooleanArgument("generateSelfSignedCertificate".toLowerCase(),
-                null, "generateSelfSignedCertificate", INFO_ARGUMENT_DESCRIPTION_USE_SELF_SIGNED_CERTIFICATE.get());
-        generateSelfSigned.setPropertyName("generateSelfSignedCertificate");
-        return generateSelfSigned;
+        return BooleanArgument.builder("generateSelfSignedCertificate")
+                .description(INFO_ARGUMENT_DESCRIPTION_USE_SELF_SIGNED_CERTIFICATE.get())
+                .buildArgument();
     }
 
     /**
@@ -1019,9 +1172,12 @@
      */
     public static StringArgument getHostName(final String defaultHostName, final LocalizableMessage description)
             throws ArgumentException {
-        return new StringArgument(OPTION_LONG_HOST.toLowerCase(), OPTION_SHORT_HOST, OPTION_LONG_HOST, false, false,
-                true, INFO_HOST_PLACEHOLDER.get(), defaultHostName, OPTION_LONG_HOST, description != null ? description
-                        : INFO_ARGUMENT_DESCRIPTION_HOST_NAME.get());
+        return StringArgument.builder(OPTION_LONG_HOST)
+                .shortIdentifier(OPTION_SHORT_HOST)
+                .description(description != null ? description : INFO_ARGUMENT_DESCRIPTION_HOST_NAME.get())
+                .defaultValue(defaultHostName)
+                .valuePlaceholder(INFO_HOST_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -1032,10 +1188,9 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getUsePKCS11Keystore() throws ArgumentException {
-        final BooleanArgument usePkcs11 = new BooleanArgument("usePkcs11Keystore".toLowerCase(), null,
-                "usePkcs11Keystore", INFO_ARGUMENT_DESCRIPTION_USE_PKCS11.get());
-        usePkcs11.setPropertyName("usePkcs11Keystore");
-        return usePkcs11;
+        return BooleanArgument.builder("usePkcs11Keystore")
+                .description(INFO_ARGUMENT_DESCRIPTION_USE_PKCS11.get())
+                .buildArgument();
     }
 
     /**
@@ -1046,9 +1201,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getUseJavaKeyStore() throws ArgumentException {
-        return new StringArgument("useJavaKeystore".toLowerCase(), null, "useJavaKeystore", false, false, true,
-                INFO_KEYSTOREPATH_PLACEHOLDER.get(), null, "useJavaKeystore",
-                INFO_ARGUMENT_DESCRIPTION_USE_JAVAKEYSTORE.get());
+        return StringArgument.builder("useJavaKeystore")
+                .description(INFO_ARGUMENT_DESCRIPTION_USE_JAVAKEYSTORE.get())
+                .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -1059,8 +1215,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getUseJCEKS() throws ArgumentException {
-        return new StringArgument("useJCEKS".toLowerCase(), null, "useJCEKS", false, false, true,
-                INFO_KEYSTOREPATH_PLACEHOLDER.get(), null, "useJCEKS", INFO_ARGUMENT_DESCRIPTION_USE_JCEKS.get());
+        return StringArgument.builder("useJCEKS")
+                .description(INFO_ARGUMENT_DESCRIPTION_USE_JCEKS.get())
+                .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -1071,9 +1229,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getUsePKCS12KeyStore() throws ArgumentException {
-        return new StringArgument("usePkcs12keyStore".toLowerCase(), null, "usePkcs12keyStore", false, false, true,
-                INFO_KEYSTOREPATH_PLACEHOLDER.get(), null, "usePkcs12keyStore",
-                INFO_ARGUMENT_DESCRIPTION_USE_PKCS12.get());
+        return StringArgument.builder("usePkcs12keyStore")
+                .description(INFO_ARGUMENT_DESCRIPTION_USE_PKCS12.get())
+                .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -1085,10 +1244,10 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static BooleanArgument getUseSSL() throws ArgumentException {
-        final BooleanArgument useSSL = new BooleanArgument("useSSL", OPTION_SHORT_USE_SSL, OPTION_LONG_USE_SSL,
-                INFO_DESCRIPTION_USE_SSL.get());
-        useSSL.setPropertyName(OPTION_LONG_USE_SSL);
-        return useSSL;
+        return BooleanArgument.builder(OPTION_LONG_USE_SSL)
+                .shortIdentifier(OPTION_SHORT_USE_SSL)
+                .description(INFO_DESCRIPTION_USE_SSL.get())
+                .buildArgument();
     }
 
     /**
@@ -1099,8 +1258,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getKeyManagerPath() throws ArgumentException {
-        return new StringArgument("keymanagerpath", 'm', "keyManagerPath", false, false, true,
-                INFO_KEY_MANAGER_PATH_PLACEHOLDER.get(), null, null, INFO_DESCRIPTION_KEYMANAGER_PATH.get());
+        return StringArgument.builder("keyManagerPath")
+                .shortIdentifier('m')
+                .description(INFO_DESCRIPTION_KEYMANAGER_PATH.get())
+                .valuePlaceholder(INFO_KEY_MANAGER_PATH_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -1111,9 +1273,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getKeyManagerProviderDN() throws ArgumentException {
-        return new StringArgument("keymanagerproviderdn", 'k', "keyManagerProviderDN", false, false, true,
-                INFO_KEY_MANAGER_PROVIDER_DN_PLACEHOLDER.get(), null, null,
-                INFO_DESCRIPTION_KEYMANAGER_PROVIDER_DN.get());
+        return StringArgument.builder("keyManagerProviderDN")
+                .shortIdentifier('k')
+                .description(INFO_DESCRIPTION_KEYMANAGER_PROVIDER_DN.get())
+                .valuePlaceholder(INFO_KEY_MANAGER_PROVIDER_DN_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -1124,9 +1288,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getKeyStorePassword() throws ArgumentException {
-        return new StringArgument(OPTION_LONG_KEYSTORE_PWD.toLowerCase(), OPTION_SHORT_KEYSTORE_PWD,
-                OPTION_LONG_KEYSTORE_PWD, false, false, true, INFO_KEYSTORE_PWD_PLACEHOLDER.get(), null,
-                OPTION_LONG_KEYSTORE_PWD, INFO_ARGUMENT_DESCRIPTION_KEYSTOREPASSWORD.get());
+        return StringArgument.builder(OPTION_LONG_KEYSTORE_PWD)
+                .shortIdentifier(OPTION_SHORT_KEYSTORE_PWD)
+                .description(INFO_ARGUMENT_DESCRIPTION_KEYSTOREPASSWORD.get())
+                .valuePlaceholder(INFO_KEYSTORE_PWD_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -1137,9 +1303,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static FileBasedArgument getKeyStorePasswordFile() throws ArgumentException {
-        return new FileBasedArgument(OPTION_LONG_KEYSTORE_PWD_FILE.toLowerCase(), OPTION_SHORT_KEYSTORE_PWD_FILE,
-                OPTION_LONG_KEYSTORE_PWD_FILE, false, false, INFO_KEYSTORE_PWD_FILE_PLACEHOLDER.get(), null,
-                OPTION_LONG_KEYSTORE_PWD_FILE, INFO_ARGUMENT_DESCRIPTION_KEYSTOREPASSWORD_FILE.get());
+        return FileBasedArgument.builder(OPTION_LONG_KEYSTORE_PWD_FILE)
+                .shortIdentifier(OPTION_SHORT_KEYSTORE_PWD_FILE)
+                .description(INFO_ARGUMENT_DESCRIPTION_KEYSTOREPASSWORD_FILE.get())
+                .valuePlaceholder(INFO_KEYSTORE_PWD_FILE_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -1150,11 +1318,11 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getKeyStorePath() throws ArgumentException {
-        final StringArgument ksPath = new StringArgument("keyStorePath", OPTION_SHORT_KEYSTOREPATH,
-                OPTION_LONG_KEYSTOREPATH, false, false, true, INFO_KEYSTOREPATH_PLACEHOLDER.get(), null, null,
-                INFO_DESCRIPTION_KEYSTOREPATH.get());
-        ksPath.setPropertyName(OPTION_LONG_KEYSTOREPATH);
-        return ksPath;
+        return StringArgument.builder(OPTION_LONG_KEYSTOREPATH)
+                .shortIdentifier(OPTION_SHORT_KEYSTOREPATH)
+                .description(INFO_DESCRIPTION_KEYSTOREPATH.get())
+                .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get())
+                .buildArgument();
     }
 
     /**
@@ -1165,8 +1333,50 @@
      *             If there is a problem with any of the parameters used to create this argument.
      */
     public static StringArgument getCertNickName() throws ArgumentException {
-        return new StringArgument(OPTION_LONG_CERT_NICKNAME.toLowerCase(), OPTION_SHORT_CERT_NICKNAME,
-                OPTION_LONG_CERT_NICKNAME, false, true, true, INFO_NICKNAME_PLACEHOLDER.get(), null,
-                OPTION_LONG_CERT_NICKNAME, INFO_ARGUMENT_DESCRIPTION_CERT_NICKNAME.get());
+        return StringArgument.builder(OPTION_LONG_CERT_NICKNAME)
+                .shortIdentifier(OPTION_SHORT_CERT_NICKNAME)
+                .description(INFO_ARGUMENT_DESCRIPTION_CERT_NICKNAME.get())
+                .multiValued()
+                .valuePlaceholder(INFO_NICKNAME_PLACEHOLDER.get())
+                .buildArgument();
+    }
+
+    /**
+     * Returns the "admin uid" string argument with the provided description.
+     *
+     * @param description
+     *            The argument localizable description.
+     * @return The "admin uid" string argument with the provided description.
+     * @throws ArgumentException
+     *             If there is a problem with any of the parameters used to create this argument.
+     */
+    public static StringArgument getAdminUid(final LocalizableMessage description) throws ArgumentException {
+        return getAdminUid(false, description);
+    }
+
+    /**
+     * Returns the "admin uid" hidden string argument.
+     *
+     * @param description
+     *            The argument localizable description.
+     * @return The "admin uid" hidden string argument.
+     * @throws ArgumentException
+     *             If there is a problem with any of the parameters used to create this argument.
+     */
+    public static StringArgument getAdminUidHidden(final LocalizableMessage description) throws ArgumentException {
+        return getAdminUid(true, description);
+    }
+
+    private static StringArgument getAdminUid(final boolean hidden, final LocalizableMessage description)
+            throws ArgumentException {
+        final StringArgument.Builder builder = StringArgument.builder(OPTION_LONG_ADMIN_UID)
+                .shortIdentifier('I')
+                .description(description)
+                .defaultValue(CliConstants.GLOBAL_ADMIN_UID)
+                .valuePlaceholder(INFO_ADMINUID_PLACEHOLDER.get());
+        if (hidden) {
+            builder.hidden();
+        }
+        return builder.buildArgument();
     }
 }
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
index d3d4f96..4b8ba91 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
@@ -252,14 +252,13 @@
         reportAuthzIDArg = CommonArguments.getReportAuthzId();
         argumentParser.addArgument(reportAuthzIDArg);
 
-        connectTimeOut = CommonArguments.getConnectTimeOut();
+        connectTimeOut = CommonArguments.getConnectTimeOutHidden();
         argumentParser.addArgument(connectTimeOut);
 
         usePasswordPolicyControlArg =
-                new BooleanArgument("usepwpolicycontrol", null, OPTION_LONG_USE_PW_POLICY_CTL,
-                        INFO_DESCRIPTION_USE_PWP_CONTROL.get());
-        usePasswordPolicyControlArg.setPropertyName(OPTION_LONG_USE_PW_POLICY_CTL);
-        argumentParser.addArgument(usePasswordPolicyControlArg);
+                BooleanArgument.builder(OPTION_LONG_USE_PW_POLICY_CTL)
+                        .description(INFO_DESCRIPTION_USE_PWP_CONTROL.get())
+                        .buildAndAddToParser(argumentParser);
     }
 
     /**
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/DocDescriptionSupplement.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/DocDescriptionSupplement.java
index 9285b50..71486f5 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/DocDescriptionSupplement.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/DocDescriptionSupplement.java
@@ -39,12 +39,4 @@
      *         or LocalizableMessage.EMPTY if there is no supplement.
      */
     LocalizableMessage getDocDescriptionSupplement();
-
-    /**
-     * Sets a supplement to the description intended for use in generated reference documentation.
-     *
-     * @param docDescriptionSupplement  The supplement to the description
-     *                                  for use in generated reference documentation.
-     */
-    void setDocDescriptionSupplement(final LocalizableMessage docDescriptionSupplement);
 }
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/FileBasedArgument.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/FileBasedArgument.java
index 6ac905c..42ad6c4 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/FileBasedArgument.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/FileBasedArgument.java
@@ -37,7 +37,6 @@
 import java.util.LinkedHashMap;
 import java.util.Map;
 
-import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
 
 /**
@@ -56,85 +55,41 @@
  * multiple lines, then only the first line will be read.
  */
 public final class FileBasedArgument extends Argument {
+
+    /**
+     * Returns a builder which can be used for incrementally constructing a new
+     * {@link FileBasedArgument}.
+     *
+     * @param longIdentifier
+     *         The generic long identifier that will be used to refer to this argument.
+     * @return A builder to continue building the {@link FileBasedArgument}.
+     */
+    public static Builder builder(final String longIdentifier) {
+        return new Builder(longIdentifier);
+    }
+
+    /** A fluent API for incrementally constructing {@link FileBasedArgument}. */
+    public static final class Builder extends ArgumentBuilder<Builder, String, FileBasedArgument> {
+        private Builder(final String longIdentifier) {
+            super(longIdentifier);
+        }
+
+        @Override
+        Builder getThis() {
+            return this;
+        }
+
+        @Override
+        public FileBasedArgument buildArgument() throws ArgumentException {
+            return new FileBasedArgument(this);
+        }
+    }
+
     /** The mapping between filenames specified and the first lines read from those files. */
     private final Map<String, String> namesToValues = new LinkedHashMap<>();
 
-    /**
-     * Creates a new file-based argument with the provided information.
-     *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
-     * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param isMultiValued
-     *            Indicates whether this argument may be specified more than
-     *            once to provide multiple values.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param defaultValue
-     *            The default value that should be used for this argument if
-     *            none is provided in a properties file or on the command line.
-     *            This may be <CODE>null</CODE> if there is no generic default.
-     * @param propertyName
-     *            The name of the property in a property file that may be used
-     *            to override the default value but will be overridden by a
-     *            command-line argument.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
-     */
-    public FileBasedArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired, final boolean isMultiValued,
-            final LocalizableMessage valuePlaceholder, final String defaultValue,
-            final String propertyName, final LocalizableMessage description)
-            throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued, true,
-                valuePlaceholder, defaultValue, propertyName, description);
-    }
-
-    /**
-     * Creates a new file-based argument with the provided information.
-     *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
-     * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
-     */
-    public FileBasedArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired,
-            final LocalizableMessage valuePlaceholder, final LocalizableMessage description)
-            throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, isRequired, false, true, valuePlaceholder,
-                null, null, description);
+    private FileBasedArgument(final Builder builder) throws ArgumentException {
+        super(builder);
     }
 
     /**
@@ -188,12 +143,12 @@
         try {
             valueFile = new File(valueString);
             if (!valueFile.exists()) {
-                invalidReason.append(ERR_FILEARG_NO_SUCH_FILE.get(valueString, getName()));
+                invalidReason.append(ERR_FILEARG_NO_SUCH_FILE.get(valueString, longIdentifier));
                 return false;
             }
         } catch (final Exception e) {
-            invalidReason.append(ERR_FILEARG_CANNOT_VERIFY_FILE_EXISTENCE.get(valueString,
-                    getName(), getExceptionMessage(e)));
+            invalidReason.append(ERR_FILEARG_CANNOT_VERIFY_FILE_EXISTENCE.get(
+                    valueString, longIdentifier, getExceptionMessage(e)));
             return false;
         }
 
@@ -202,16 +157,16 @@
         try (BufferedReader reader = new BufferedReader(new FileReader(valueFile))) {
             line = reader.readLine();
         } catch (final FileNotFoundException e) {
-            invalidReason.append(ERR_FILEARG_CANNOT_OPEN_FILE.get(valueString, getName(), getExceptionMessage(e)));
+            invalidReason.append(ERR_FILEARG_CANNOT_OPEN_FILE.get(valueString, longIdentifier, getExceptionMessage(e)));
             return false;
         } catch (final IOException e) {
-            invalidReason.append(ERR_FILEARG_CANNOT_READ_FILE.get(valueString, getName(), getExceptionMessage(e)));
+            invalidReason.append(ERR_FILEARG_CANNOT_READ_FILE.get(valueString, longIdentifier, getExceptionMessage(e)));
             return false;
         }
 
         // If the line read is null, then that means the file was empty.
         if (line == null) {
-            invalidReason.append(ERR_FILEARG_EMPTY_FILE.get(valueString, getName()));
+            invalidReason.append(ERR_FILEARG_EMPTY_FILE.get(valueString, longIdentifier));
             return false;
         }
 
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/IntegerArgument.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/IntegerArgument.java
index d832e75..1e727fa 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/IntegerArgument.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/IntegerArgument.java
@@ -36,244 +36,85 @@
  * potentially only those in a given range.
  */
 public final class IntegerArgument extends Argument {
-    /** Indicates whether a lower bound will be enforced for this argument. */
-    private final boolean hasLowerBound;
 
     /**
-     * Indicates whether an upper bound will be enforced for this
-     * argument.
+     * Returns a builder which can be used for incrementally constructing a new
+     * {@link IntegerArgument}.
+     *
+     * @param name
+     *         The generic name that will be used to refer to this argument.
+     * @return A builder to continue building the {@link IntegerArgument}.
      */
-    private final boolean hasUpperBound;
+    public static Builder builder(final String name) {
+        return new Builder(name);
+    }
+
+    /** A fluent API for incrementally constructing {@link IntegerArgument}. */
+    public static final class Builder extends ArgumentBuilder<Builder, Integer, IntegerArgument> {
+        private int lowerBound = Integer.MIN_VALUE;
+        private int upperBound = Integer.MAX_VALUE;
+
+        private Builder(final String name) {
+            super(name);
+        }
+
+        @Override
+        Builder getThis() {
+            return this;
+        }
+
+        /**
+         * Sets the lower bound of this {@link IntegerArgument}.
+         *
+         * @param lowerBound
+         *         The lower bound value.
+         * @return This builder.
+         */
+        public Builder lowerBound(final int lowerBound) {
+            this.lowerBound = lowerBound;
+            return getThis();
+        }
+
+        /**
+         * Sets the range of this {@link IntegerArgument}.
+         *
+         * @param lowerBound
+         *          The range lower bound value.
+         * @param upperBound
+         *          The range upper bound value.
+         * @return This builder.
+         */
+        public Builder range(final int lowerBound, final int upperBound) {
+            this.lowerBound = lowerBound;
+            this.upperBound = upperBound;
+            return getThis();
+        }
+
+        @Override
+        public IntegerArgument buildArgument() throws ArgumentException {
+            return new IntegerArgument(this, lowerBound, upperBound);
+        }
+    }
 
     /** The lower bound that will be enforced for this argument. */
     private final int lowerBound;
-
     /** The upper bound that will be enforced for this argument. */
     private final int upperBound;
 
-    /**
-     * Creates a new integer argument with the provided information.
-     *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
-     * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param isMultiValued
-     *            Indicates whether this argument may be specified more than
-     *            once to provide multiple values.
-     * @param needsValue
-     *            Indicates whether this argument requires a value.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param defaultValue
-     *            The default value that should be used for this argument if
-     *            none is provided in a properties file or on the command line.
-     *            This may be <CODE>null</CODE> if there is no generic default.
-     * @param propertyName
-     *            The name of the property in a property file that may be used
-     *            to override the default value but will be overridden by a
-     *            command-line argument.
-     * @param hasLowerBound
-     *            Indicates whether a lower bound should be enforced for values
-     *            of this argument.
-     * @param lowerBound
-     *            The lower bound that should be enforced for values of this
-     *            argument.
-     * @param hasUpperBound
-     *            Indicates whether an upperbound should be enforced for values
-     *            of this argument.
-     * @param upperBound
-     *            The upper bound that should be enforced for values of this
-     *            argument.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
-     */
-    public IntegerArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired, final boolean isMultiValued,
-            final boolean needsValue, final LocalizableMessage valuePlaceholder,
-            final int defaultValue, final String propertyName, final boolean hasLowerBound,
-            final int lowerBound, final boolean hasUpperBound, final int upperBound,
-            final LocalizableMessage description) throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued, needsValue,
-                valuePlaceholder, String.valueOf(defaultValue), propertyName, description);
-
-        this.hasLowerBound = hasLowerBound;
-        this.hasUpperBound = hasUpperBound;
+    private IntegerArgument(final Builder builder, final int lowerBound, final int upperBound)
+            throws ArgumentException {
+        super(builder);
         this.lowerBound = lowerBound;
         this.upperBound = upperBound;
 
-        if (hasLowerBound && hasUpperBound && (lowerBound > upperBound)) {
+        if (lowerBound > upperBound) {
             final LocalizableMessage message =
-                    ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND.get(name, lowerBound, upperBound);
+                    ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND.get(builder.longIdentifier, lowerBound, upperBound);
             throw new ArgumentException(message);
         }
     }
 
     /**
-     * Creates a new integer argument with the provided information.
-     *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
-     * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param isMultiValued
-     *            Indicates whether this argument may be specified more than
-     *            once to provide multiple values.
-     * @param needsValue
-     *            Indicates whether this argument requires a value.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param defaultValue
-     *            The default value that should be used for this argument if
-     *            none is provided in a properties file or on the command line.
-     *            This may be <CODE>null</CODE> if there is no generic default.
-     * @param propertyName
-     *            The name of the property in a property file that may be used
-     *            to override the default value but will be overridden by a
-     *            command-line argument.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
-     */
-    public IntegerArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired, final boolean isMultiValued,
-            final boolean needsValue, final LocalizableMessage valuePlaceholder,
-            final int defaultValue, final String propertyName, final LocalizableMessage description)
-            throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued, needsValue,
-                valuePlaceholder, String.valueOf(defaultValue), propertyName, description);
-
-        hasLowerBound = false;
-        hasUpperBound = false;
-        lowerBound = Integer.MIN_VALUE;
-        upperBound = Integer.MAX_VALUE;
-    }
-
-    /**
-     * Creates a new integer argument with the provided information.
-     *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
-     * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param needsValue
-     *            Indicates whether this argument requires a value.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param hasLowerBound
-     *            Indicates whether a lower bound should be enforced for values
-     *            of this argument.
-     * @param lowerBound
-     *            The lower bound that should be enforced for values of this
-     *            argument.
-     * @param hasUpperBound
-     *            Indicates whether an upperbound should be enforced for values
-     *            of this argument.
-     * @param upperBound
-     *            The upper bound that should be enforced for values of this
-     *            argument.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
-     */
-    public IntegerArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired, final boolean needsValue,
-            final LocalizableMessage valuePlaceholder, final boolean hasLowerBound,
-            final int lowerBound, final boolean hasUpperBound, final int upperBound,
-            final LocalizableMessage description) throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, isRequired, false, needsValue,
-                valuePlaceholder, null, null, description);
-
-        this.hasLowerBound = hasLowerBound;
-        this.hasUpperBound = hasUpperBound;
-        this.lowerBound = lowerBound;
-        this.upperBound = upperBound;
-
-        if (hasLowerBound && hasUpperBound && (lowerBound > upperBound)) {
-            final LocalizableMessage message =
-                    ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND.get(name, lowerBound, upperBound);
-            throw new ArgumentException(message);
-        }
-    }
-
-    /**
-     * Creates a new integer argument with the provided information.
-     *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
-     * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param needsValue
-     *            Indicates whether this argument requires a value.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
-     */
-    public IntegerArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired, final boolean needsValue,
-            final LocalizableMessage valuePlaceholder, final LocalizableMessage description)
-            throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, isRequired, false, needsValue,
-                valuePlaceholder, null, null, description);
-
-        hasLowerBound = false;
-        hasUpperBound = false;
-        lowerBound = Integer.MIN_VALUE;
-        upperBound = Integer.MAX_VALUE;
-    }
-
-    /**
      * Indicates whether the provided value is acceptable for use in this
      * argument.
      *
@@ -289,19 +130,19 @@
     public boolean valueIsAcceptable(final String valueString, final LocalizableMessageBuilder invalidReason) {
         try {
             final int intValue = Integer.parseInt(valueString);
-            if (hasLowerBound && intValue < lowerBound) {
-                invalidReason.append(ERR_INTARG_VALUE_BELOW_LOWER_BOUND.get(getPropertyName(), intValue, lowerBound));
+            if (intValue < lowerBound) {
+                invalidReason.append(ERR_INTARG_VALUE_BELOW_LOWER_BOUND.get(longIdentifier, intValue, lowerBound));
                 return false;
             }
 
-            if (hasUpperBound && intValue > upperBound) {
-                invalidReason.append(ERR_INTARG_VALUE_ABOVE_UPPER_BOUND.get(getPropertyName(), intValue, upperBound));
+            if (intValue > upperBound) {
+                invalidReason.append(ERR_INTARG_VALUE_ABOVE_UPPER_BOUND.get(longIdentifier, intValue, upperBound));
                 return false;
             }
 
             return true;
         } catch (final NumberFormatException e) {
-            invalidReason.append(ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, getPropertyName()));
+            invalidReason.append(ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, longIdentifier));
             return false;
         }
     }
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/MultiChoiceArgument.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/MultiChoiceArgument.java
index 92b3b9e..05542ef 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/MultiChoiceArgument.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/MultiChoiceArgument.java
@@ -28,130 +28,87 @@
 
 import static com.forgerock.opendj.cli.CliMessages.ERR_MCARG_VALUE_NOT_ALLOWED;
 
+import java.util.Arrays;
 import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
 
-import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
 
 /**
  * This class defines an argument type that will only accept one or more of a
  * specific set of string values.
  *
- * @param <T>
+ * @param <V>
  *            The type of values returned by this argument.
  */
-public final class MultiChoiceArgument<T> extends Argument {
-    /**
-     * Indicates whether argument values should be treated in a
-     * case-sensitive manner.
-     */
-    private final boolean caseSensitive;
-
-    /** The set of values that will be allowed for use with this argument. */
-    private final Collection<T> allowedValues;
+public final class MultiChoiceArgument<V> extends Argument {
 
     /**
-     * Creates a new string argument with the provided information.
+     * Returns a builder which can be used for incrementally constructing a new
+     * {@link MultiChoiceArgument<V>}.
      *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
+     * @param <V>
+     *         The type of values returned by this argument.
      * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param isMultiValued
-     *            Indicates whether this argument may be specified more than
-     *            once to provide multiple values.
-     * @param needsValue
-     *            Indicates whether this argument requires a value.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param defaultValue
-     *            The default value that should be used for this argument if
-     *            none is provided in a properties file or on the command line.
-     *            This may be <CODE>null</CODE> if there is no generic default.
-     * @param propertyName
-     *            The name of the property in a property file that may be used
-     *            to override the default value but will be overridden by a
-     *            command-line argument.
-     * @param allowedValues
-     *            The set of values that are allowed for use for this argument.
-     *            If they are not to be treated in a case-sensitive value then
-     *            they should all be formatted in lowercase.
-     * @param caseSensitive
-     *            Indicates whether the set of allowed values should be treated
-     *            in a case-sensitive manner.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
+     *         The generic long identifier that will be used to refer to this argument.
+     * @return A builder to continue building the {@link MultiChoiceArgument}.
      */
-    public MultiChoiceArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired, final boolean isMultiValued,
-            final boolean needsValue, final LocalizableMessage valuePlaceholder,
-            final String defaultValue, final String propertyName,
-            final Collection<T> allowedValues, final boolean caseSensitive,
-            final LocalizableMessage description) throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued, needsValue,
-                valuePlaceholder, defaultValue, propertyName, description);
-
-        this.allowedValues = allowedValues;
-        this.caseSensitive = caseSensitive;
+    public static <V> Builder<V> builder(final String longIdentifier) {
+        return new Builder<>(longIdentifier);
     }
 
-    /**
-     * Creates a new string argument with the provided information.
-     *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
-     * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param needsValue
-     *            Indicates whether this argument requires a value.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param allowedValues
-     *            The set of values that are allowed for use for this argument.
-     *            If they are not to be treated in a case-sensitive value then
-     *            they should all be formatted in lowercase.
-     * @param caseSensitive
-     *            Indicates whether the set of allowed values should be treated
-     *            in a case-sensitive manner.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
-     */
-    public MultiChoiceArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired, final boolean needsValue,
-            final LocalizableMessage valuePlaceholder, final Collection<T> allowedValues,
-            final boolean caseSensitive, final LocalizableMessage description)
-            throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, isRequired, false, needsValue,
-                valuePlaceholder, null, null, description);
+    /** A fluent API for incrementally constructing {@link MultiChoiceArgument<V>}. */
+    public static final class Builder<V> extends ArgumentBuilder<Builder<V>, V, MultiChoiceArgument<V>> {
+        private final List<V> allowedValues = new LinkedList<>();
 
+        private Builder(final String longIdentifier) {
+            super(longIdentifier);
+        }
+
+        @Override
+        Builder<V> getThis() {
+            return this;
+        }
+
+        /**
+         * Specifies the set of values that are allowed for the {@link MultiChoiceArgument<V>}.
+         *
+         * @param allowedValues
+         *         The {@link MultiChoiceArgument<V>} allowed values.
+         * @return This builder.
+         */
+        public Builder<V> allowedValues(final Collection<V> allowedValues) {
+            this.allowedValues.addAll(allowedValues);
+            return getThis();
+        }
+
+        /**
+         * Specifies the set of values that are allowed for the {@link MultiChoiceArgument<V>}.
+         *
+         * @param allowedValues
+         *         The {@link MultiChoiceArgument<V>} allowed values.
+         * @return This builder.
+         */
+        @SuppressWarnings("unchecked")
+        public final Builder<V> allowedValues(final V... allowedValues) {
+            this.allowedValues.addAll(Arrays.asList(allowedValues));
+            return getThis();
+        }
+
+        @Override
+        public MultiChoiceArgument<V> buildArgument() throws ArgumentException {
+            return new MultiChoiceArgument<>(this, allowedValues);
+        }
+    }
+
+    /** The set of values that will be allowed for use with this argument. */
+    private final Collection<V> allowedValues;
+
+    private <V1> MultiChoiceArgument(final Builder<V1> builder, final Collection<V> allowedValues)
+            throws ArgumentException {
+        super(builder);
         this.allowedValues = allowedValues;
-        this.caseSensitive = caseSensitive;
     }
 
     /**
@@ -164,32 +121,17 @@
      * @throws ArgumentException
      *             The value cannot be parsed.
      */
-    public T getTypedValue() throws ArgumentException {
+    public V getTypedValue() throws ArgumentException {
         final String v = super.getValue();
         if (v == null) {
             return null;
         }
-        for (final T o : allowedValues) {
-            if ((caseSensitive && o.toString().equals(v)) || o.toString().equalsIgnoreCase(v)) {
-                return o;
+        for (final V allowedValue : allowedValues) {
+            if (allowedValue.toString().equalsIgnoreCase(v)) {
+                return allowedValue;
             }
         }
-        // TODO: Some message
-        throw new ArgumentException(null);
-    }
-
-    /**
-     * Specifies the default value that will be used for this argument if it is
-     * not specified on the command line and it is not set from a properties
-     * file.
-     *
-     * @param defaultValue
-     *            The default value that will be used for this argument if it is
-     *            not specified on the command line and it is not set from a
-     *            properties file.
-     */
-    public void setDefaultValue(final T defaultValue) {
-        super.setDefaultValue(defaultValue.toString());
+        throw new IllegalStateException("This MultiChoiceArgument value is not part of the allowed values.");
     }
 
     /**
@@ -205,15 +147,13 @@
      *         <CODE>false</CODE> if it is not.
      */
     @Override
-    public boolean valueIsAcceptable(final String valueString,
-            final LocalizableMessageBuilder invalidReason) {
-        for (final T o : allowedValues) {
-            if ((caseSensitive && o.toString().equals(valueString))
-                    || o.toString().equalsIgnoreCase(valueString)) {
+    public boolean valueIsAcceptable(final String valueString, final LocalizableMessageBuilder invalidReason) {
+        for (final V allowedValue : allowedValues) {
+            if (allowedValue.toString().equalsIgnoreCase(valueString)) {
                 return true;
             }
         }
-        invalidReason.append(ERR_MCARG_VALUE_NOT_ALLOWED.get(getName(), valueString));
+        invalidReason.append(ERR_MCARG_VALUE_NOT_ALLOWED.get(longIdentifier, valueString));
 
         return false;
     }
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/StringArgument.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/StringArgument.java
index 70b52c4..48bd921 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/StringArgument.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/StringArgument.java
@@ -26,93 +26,42 @@
  */
 package com.forgerock.opendj.cli;
 
-import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
 
 /** This class defines an argument type that will accept any string value. */
 public final class StringArgument extends Argument {
     /**
-     * Creates a new string argument with the provided information.
+     * Returns a builder which can be used for incrementally constructing a new
+     * {@link StringArgument}.
      *
      * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
-     * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param isMultiValued
-     *            Indicates whether this argument may be specified more than
-     *            once to provide multiple values.
-     * @param needsValue
-     *            Indicates whether this argument requires a value.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param defaultValue
-     *            The default value that should be used for this argument if
-     *            none is provided in a properties file or on the command line.
-     *            This may be <CODE>null</CODE> if there is no generic default.
-     * @param propertyName
-     *            The name of the property in a property file that may be used
-     *            to override the default value but will be overridden by a
-     *            command-line argument.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
+     *         The generic name that will be used to refer to this argument.
+     * @return A builder to continue building the {@link StringArgument}.
      */
-    public StringArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired, final boolean isMultiValued,
-            final boolean needsValue, final LocalizableMessage valuePlaceholder,
-            final String defaultValue, final String propertyName,
-            final LocalizableMessage description) throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued, needsValue,
-                valuePlaceholder, defaultValue, propertyName, description);
+    public static Builder builder(final String name) {
+        return new Builder(name);
     }
 
-    /**
-     * Creates a new string argument with the provided information.
-     *
-     * @param name
-     *            The generic name that should be used to refer to this
-     *            argument.
-     * @param shortIdentifier
-     *            The single-character identifier for this argument, or
-     *            <CODE>null</CODE> if there is none.
-     * @param longIdentifier
-     *            The long identifier for this argument, or <CODE>null</CODE> if
-     *            there is none.
-     * @param isRequired
-     *            Indicates whether this argument must be specified on the
-     *            command line.
-     * @param needsValue
-     *            Indicates whether this argument requires a value.
-     * @param valuePlaceholder
-     *            The placeholder for the argument value that will be displayed
-     *            in usage information, or <CODE>null</CODE> if this argument
-     *            does not require a value.
-     * @param description
-     *            LocalizableMessage for the description of this argument.
-     * @throws ArgumentException
-     *             If there is a problem with any of the parameters used to
-     *             create this argument.
-     */
-    public StringArgument(final String name, final Character shortIdentifier,
-            final String longIdentifier, final boolean isRequired, final boolean needsValue,
-            final LocalizableMessage valuePlaceholder, final LocalizableMessage description)
-            throws ArgumentException {
-        super(name, shortIdentifier, longIdentifier, isRequired, false, needsValue,
-                valuePlaceholder, null, null, description);
+    /** A fluent API for incrementally constructing {@link StringArgument}. */
+    public static final class Builder extends ArgumentBuilder<Builder, String, StringArgument> {
+        private Builder(final String name) {
+            super(name);
+        }
+
+        @Override
+        Builder getThis() {
+            return this;
+        }
+
+        @Override
+        public StringArgument buildArgument() throws ArgumentException {
+            return new StringArgument(this);
+        }
     }
 
+    private StringArgument(final Builder builder) throws ArgumentException {
+        super(builder);
+    }
 
     @Override
     public boolean valueIsAcceptable(final String valueString, final LocalizableMessageBuilder invalidReason) {
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/SubCommand.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/SubCommand.java
index 15c21f3..303863b 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/SubCommand.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/SubCommand.java
@@ -168,7 +168,12 @@
         return docDescriptionSupplement != null ? docDescriptionSupplement : LocalizableMessage.EMPTY;
     }
 
-    @Override
+    /**
+     * Sets a supplement to the description intended for use in generated reference documentation.
+     *
+     * @param docDescriptionSupplement
+     *            The supplement to the description for use in generated reference documentation.
+     */
     public void setDocDescriptionSupplement(final LocalizableMessage docDescriptionSupplement) {
         this.docDescriptionSupplement = docDescriptionSupplement;
     }
@@ -205,20 +210,15 @@
     }
 
     /**
-     * Retrieves the subcommand argument with the specified name.
+     * Retrieves the subcommand argument with the specified long identifier.
      *
-     * @param name
-     *            The name of the argument to retrieve.
-     * @return The subcommand argument with the specified name, or <CODE>null</CODE> if there is no such argument.
+     * @param longIdentifier
+     *            The long identifier of the argument to retrieve.
+     * @return The subcommand argument with the specified long identifier,
+     *         or <CODE>null</CODE> if there is no such argument.
      */
-    public Argument getArgumentForName(String name) {
-        for (Argument a : arguments) {
-            if (a.getName().equals(name)) {
-                return a;
-            }
-        }
-
-        return null;
+    public Argument getArgumentForLongIdentifier(final String longIdentifier) {
+        return longIDMap.get(parser.longArgumentsCaseSensitive() ? longIdentifier : toLowerCase(longIdentifier));
     }
 
     /**
@@ -231,53 +231,40 @@
      *             associated with this subcommand.
      */
     public void addArgument(Argument argument) throws ArgumentException {
-        String argumentName = argument.getName();
-        for (Argument a : arguments) {
-            if (argumentName.equals(a.getName())) {
-                LocalizableMessage message = ERR_ARG_SUBCOMMAND_DUPLICATE_ARGUMENT_NAME.get(name, argumentName);
-                throw new ArgumentException(message);
-            }
+        final String argumentLongID = argument.getLongIdentifier();
+        if (getArgumentForLongIdentifier(argumentLongID) != null) {
+            throw new ArgumentException(ERR_ARG_SUBCOMMAND_DUPLICATE_ARGUMENT_NAME.get(name, argumentLongID));
         }
 
-        if (parser.hasGlobalArgument(argumentName)) {
-            LocalizableMessage message = ERR_ARG_SUBCOMMAND_ARGUMENT_GLOBAL_CONFLICT.get(argumentName, name);
-            throw new ArgumentException(message);
+        if (parser.hasGlobalArgument(argumentLongID)) {
+            throw new ArgumentException(ERR_ARG_SUBCOMMAND_ARGUMENT_GLOBAL_CONFLICT.get(argumentLongID, name));
         }
 
         Character shortID = argument.getShortIdentifier();
         if (shortID != null) {
             if (shortIDMap.containsKey(shortID)) {
-                LocalizableMessage message = ERR_ARG_SUBCOMMAND_DUPLICATE_SHORT_ID.get(argumentName, name,
-                        String.valueOf(shortID), shortIDMap.get(shortID).getName());
-                throw new ArgumentException(message);
+                throw new ArgumentException(ERR_ARG_SUBCOMMAND_DUPLICATE_SHORT_ID.get(
+                        argumentLongID, name, String.valueOf(shortID), shortIDMap.get(shortID).getLongIdentifier()));
             }
 
             Argument arg = parser.getGlobalArgumentForShortID(shortID);
             if (arg != null) {
-                LocalizableMessage message = ERR_ARG_SUBCOMMAND_ARGUMENT_SHORT_ID_GLOBAL_CONFLICT.get(argumentName,
-                        name, String.valueOf(shortID), arg.getName());
-                throw new ArgumentException(message);
+                throw new ArgumentException(ERR_ARG_SUBCOMMAND_ARGUMENT_SHORT_ID_GLOBAL_CONFLICT.get(
+                        argumentLongID, name, String.valueOf(shortID), arg.getLongIdentifier()));
             }
         }
 
         String longID = argument.getLongIdentifier();
-        if (longID != null) {
-            if (!parser.longArgumentsCaseSensitive()) {
-                longID = toLowerCase(longID);
-            }
-
+        if (!parser.longArgumentsCaseSensitive()) {
+            longID = toLowerCase(longID);
             if (longIDMap.containsKey(longID)) {
-                LocalizableMessage message = ERR_ARG_SUBCOMMAND_DUPLICATE_LONG_ID.get(argumentName, name,
-                        argument.getLongIdentifier(), longIDMap.get(longID).getName());
-                throw new ArgumentException(message);
+                throw new ArgumentException(ERR_ARG_SUBCOMMAND_DUPLICATE_LONG_ID.get(argumentLongID, name));
             }
+        }
 
-            Argument arg = parser.getGlobalArgumentForLongID(longID);
-            if (arg != null) {
-                LocalizableMessage message = ERR_ARG_SUBCOMMAND_ARGUMENT_LONG_ID_GLOBAL_CONFLICT.get(argumentName,
-                        name, argument.getLongIdentifier(), arg.getName());
-                throw new ArgumentException(message);
-            }
+        Argument arg = parser.getGlobalArgumentForLongID(longID);
+        if (arg != null) {
+            throw new ArgumentException(ERR_ARG_SUBCOMMAND_ARGUMENT_LONG_ID_GLOBAL_CONFLICT.get(argumentLongID, name));
         }
 
         arguments.add(argument);
diff --git a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/SubCommandArgumentParser.java b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/SubCommandArgumentParser.java
index 2c0ef33..f044761 100644
--- a/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/SubCommandArgumentParser.java
+++ b/opendj-sdk/opendj-cli/src/main/java/com/forgerock/opendj/cli/SubCommandArgumentParser.java
@@ -207,58 +207,44 @@
      *             defined.
      */
     public void addGlobalArgument(Argument argument, ArgumentGroup group) throws ArgumentException {
-        String argumentName = argument.getName();
-        if (globalArgumentMap.containsKey(argumentName)) {
-            throw new ArgumentException(ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_NAME.get(argumentName));
+        String longID = argument.getLongIdentifier();
+        if (globalArgumentMap.containsKey(longID)) {
+            throw new ArgumentException(ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_NAME.get(longID));
         }
         for (SubCommand s : subCommands.values()) {
-            if (s.getArgumentForName(argumentName) != null) {
+            if (s.getArgumentForLongIdentifier(longID) != null) {
                 throw new ArgumentException(ERR_SUBCMDPARSER_GLOBAL_ARG_NAME_SUBCMD_CONFLICT.get(
-                        argumentName, s.getName()));
+                        longID, s.getName()));
             }
         }
 
         Character shortID = argument.getShortIdentifier();
         if (shortID != null) {
             if (globalShortIDMap.containsKey(shortID)) {
-                String name = globalShortIDMap.get(shortID).getName();
-
+                String conflictingLongID = globalShortIDMap.get(shortID).getLongIdentifier();
                 throw new ArgumentException(ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_SHORT_ID.get(
-                        shortID, argumentName, name));
+                        shortID, longID, conflictingLongID));
             }
 
             for (SubCommand s : subCommands.values()) {
                 if (s.getArgument(shortID) != null) {
-                    String cmdName = s.getName();
-                    String name = s.getArgument(shortID).getName();
-
+                    String conflictingLongID = s.getArgument(shortID).getLongIdentifier();
                     throw new ArgumentException(ERR_SUBCMDPARSER_GLOBAL_ARG_SHORT_ID_CONFLICT.get(
-                            shortID, argumentName, name, cmdName));
+                            shortID, longID, conflictingLongID, s.getName()));
                 }
             }
         }
 
-        String longID = argument.getLongIdentifier();
-        if (longID != null) {
-            if (!longArgumentsCaseSensitive()) {
-                longID = toLowerCase(longID);
-            }
-
+        if (!longArgumentsCaseSensitive()) {
+            longID = toLowerCase(longID);
             if (globalLongIDMap.containsKey(longID)) {
-                String name = globalLongIDMap.get(longID).getName();
-
-                throw new ArgumentException(ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_LONG_ID.get(
-                        argument.getLongIdentifier(), argumentName, name));
+                throw new ArgumentException(ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_LONG_ID.get(longID));
             }
+        }
 
-            for (SubCommand s : subCommands.values()) {
-                if (s.getArgument(longID) != null) {
-                    String cmdName = s.getName();
-                    String name = s.getArgument(longID).getName();
-
-                    throw new ArgumentException(ERR_SUBCMDPARSER_GLOBAL_ARG_LONG_ID_CONFLICT.get(
-                            argument.getLongIdentifier(), argumentName, name, cmdName));
-                }
+        for (SubCommand s : subCommands.values()) {
+            if (s.getArgument(longID) != null) {
+                throw new ArgumentException(ERR_SUBCMDPARSER_GLOBAL_ARG_LONG_ID_CONFLICT.get(longID, s.getName()));
             }
         }
 
@@ -1143,11 +1129,6 @@
                 if (a.isHidden()) {
                     continue;
                 }
-                // Return a generic FQDN for localhost as the default hostname
-                // in reference documentation.
-                if (isHostNameArgument(a)) {
-                    a.setDefaultValue("localhost.localdomain");
-                }
 
                 Map<String, Object> option = new HashMap<>();
                 String optionSynopsis = getOptionSynopsis(a);
@@ -1162,7 +1143,8 @@
                     // Let this build its own arbitrarily formatted additional info.
                     info.put("usage", subCommandUsageHandler.getArgumentAdditionalInfo(subCommand, a, nameOption));
                 } else {
-                    String defaultValue = a.getDefaultValue();
+                    // Return a generic FQDN for localhost as the default hostname in reference documentation.
+                    final String defaultValue = isHostNameArgument(a) ? "localhost.localdomain" : a.getDefaultValue();
                     info.put("default", defaultValue != null ? REF_DEFAULT.get(defaultValue) : null);
 
                     // If there is a supplement to the description for this argument,
@@ -1239,4 +1221,9 @@
         map.put("subcommands", commands);
         applyTemplate(builder, "dscfgReference.ftl", map);
     }
+
+    @Override
+    public void replaceArgument(final Argument argument) {
+        replaceArgumentInCollections(globalLongIDMap, globalShortIDMap, globalArgumentList, argument);
+    }
 }
diff --git a/opendj-sdk/opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties b/opendj-sdk/opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties
index 956028e..4c2d7fb 100755
--- a/opendj-sdk/opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties
+++ b/opendj-sdk/opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties
@@ -21,14 +21,11 @@
 # CDDL HEADER END
 #
 #
-#      Copyright 2014-2015 ForgeRock AS.
+#      Copyright 2014-2016 ForgeRock AS.
 #
 #
 # CLI messages
 #
-ERR_ARG_NO_IDENTIFIER=The %s argument does not have either a \
- single-character or a long identifier that may be used to specify it.  At \
- least one of these must be specified for each argument
 ERR_ARG_NO_VALUE_PLACEHOLDER=The %s argument is configured to take \
  a value but no value placeholder has been defined for it
 ERR_ARG_NO_INT_VALUE=The %s argument does not have any value that \
@@ -75,8 +72,7 @@
  argument list because its short identifier -%s conflicts with the %s argument \
  that has already been defined
 ERR_ARGPARSER_DUPLICATE_LONG_ID=Cannot add argument %s to the \
- argument list because its long identifier --%s conflicts with the %s argument \
- that has already been defined
+ argument list because there is already one defined with the same identifier
 ERR_ARGPARSER_CANNOT_READ_PROPERTIES_FILE=An error occurred while \
  attempting to read the contents of the argument properties file %s:  %s
 ERR_ARGPARSER_TOO_MANY_TRAILING_ARGS=The provided set of \
@@ -203,9 +199,6 @@
  restarted
 INFO_CHECK_STOPPABILITY=Used to determine whether the server can \
  be stopped or not and the mode to be used to stop it
-INFO_DESCRIPTION_WINDOWS_NET_STOP=Used by the window service code \
- to inform that stop-ds is being called from the window services after a call \
- to net stop
 INFO_DESCRIPTION_STOP_TIME=Indicates the date/time at which the \
  shutdown operation will begin as a server task expressed in format \
  YYYYMMDDhhmmssZ for UTC time or YYYYMMDDhhmmss for local time.  A value of \
@@ -663,11 +656,11 @@
 ERR_ARG_SUBCOMMAND_ARGUMENT_SHORT_ID_GLOBAL_CONFLICT=Argument %s \
  for subcommand %s has a short ID -%s that conflicts with that of global \
  argument %s
-ERR_ARG_SUBCOMMAND_DUPLICATE_LONG_ID=Argument %s for subcommand %s \
- has a long identifier --%s that conflicts with that of argument %s
-ERR_ARG_SUBCOMMAND_ARGUMENT_LONG_ID_GLOBAL_CONFLICT=Argument %s for \
- subcommand %s has a long ID --%s that conflicts with that of global argument \
- %s
+ERR_ARG_SUBCOMMAND_DUPLICATE_LONG_ID=Failed to add Argument %s for subcommand %s \
+ because there is already an argument with the same identifier for this subcommand
+ERR_ARG_SUBCOMMAND_ARGUMENT_LONG_ID_GLOBAL_CONFLICT=Failed to add Argument %s for \
+ subcommand %s because there is already a global argument defined with the \
+ same long identifier
 ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_NAME=There is already another \
  global argument named "%s"
 ERR_SUBCMDPARSER_GLOBAL_ARG_NAME_SUBCMD_CONFLICT=The argument name \
@@ -678,11 +671,11 @@
 ERR_SUBCMDPARSER_GLOBAL_ARG_SHORT_ID_CONFLICT=Short ID -%s for \
  global argument %s conflicts with the short ID for the %s argument associated \
  with subcommand %s
-ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_LONG_ID=Long ID --%s for \
- global argument %s conflicts with the long ID of another global argument %s
-ERR_SUBCMDPARSER_GLOBAL_ARG_LONG_ID_CONFLICT=Long ID --%s for \
- global argument %s conflicts with the long ID for the %s argument associated \
- with subcommand %s
+ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_LONG_ID=Failed to add global argument \
+ %s because there is already one defined with the same long identifier
+ERR_SUBCMDPARSER_GLOBAL_ARG_LONG_ID_CONFLICT=Failed to add argument %s to \
+ subcommand %s because there is already one argument with the same long identifier \
+ associated to this subcommand.
 ERR_SUBCMDPARSER_CANNOT_READ_PROPERTIES_FILE=An error occurred \
  while attempting to read the contents of the argument properties file %s:  %s
 ERR_SUBCMDPARSER_LONG_ARG_WITHOUT_NAME=The provided command-line \
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AddRate.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AddRate.java
index c9d0b18..0592a8f 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AddRate.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AddRate.java
@@ -26,6 +26,7 @@
 package com.forgerock.opendj.ldap.tools;
 
 import static com.forgerock.opendj.cli.MultiColumnPrinter.column;
+import static com.forgerock.opendj.cli.CliMessages.INFO_SEED_PLACEHOLDER;
 import static java.util.concurrent.TimeUnit.*;
 
 import static org.forgerock.opendj.ldap.LdapException.*;
@@ -40,7 +41,6 @@
 
 import java.io.IOException;
 import java.io.PrintStream;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -293,7 +293,6 @@
 
         private AddPerformanceRunner(final PerformanceRunnerOptions options) throws ArgumentException {
             super(options);
-            maxIterationsArgument.setPropertyName("maxNumberOfAdd");
         }
 
         @Override
@@ -441,45 +440,60 @@
 
             /* Entries generation parameters */
             resourcePathArg =
-                new StringArgument("resourcepath", 'r', MakeLDIF.OPTION_LONG_RESOURCE_PATH, false, false, true,
-                    INFO_PATH_PLACEHOLDER.get(), null, null, INFO_ADDRATE_DESCRIPTION_RESOURCE_PATH.get());
-            resourcePathArg.setDocDescriptionSupplement(SUPPLEMENT_DESCRIPTION_RESOURCE_PATH.get());
-            argParser.addArgument(resourcePathArg);
+                    StringArgument.builder(MakeLDIF.OPTION_LONG_RESOURCE_PATH)
+                            .shortIdentifier('r')
+                            .description(INFO_ADDRATE_DESCRIPTION_RESOURCE_PATH.get())
+                            .docDescriptionSupplement(SUPPLEMENT_DESCRIPTION_RESOURCE_PATH.get())
+                            .valuePlaceholder(INFO_PATH_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             randomSeedArg =
-                new IntegerArgument("randomseed", 'R', OPTION_LONG_RANDOM_SEED, false, false, true,
-                    INFO_SEED_PLACEHOLDER.get(), 0, null, INFO_ADDRATE_DESCRIPTION_SEED.get());
-            argParser.addArgument(randomSeedArg);
-
+                    IntegerArgument.builder(OPTION_LONG_RANDOM_SEED)
+                            .shortIdentifier('R')
+                            .description(INFO_ADDRATE_DESCRIPTION_SEED.get())
+                            .defaultValue(0)
+                            .valuePlaceholder(INFO_SEED_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             constantsArg =
-                new StringArgument("constant", 'g', MakeLDIF.OPTION_LONG_CONSTANT, false, true, true,
-                    INFO_CONSTANT_PLACEHOLDER.get(), null, null, INFO_ADDRATE_DESCRIPTION_CONSTANT.get());
-            argParser.addArgument(constantsArg);
+                    StringArgument.builder(MakeLDIF.OPTION_LONG_CONSTANT)
+                            .shortIdentifier('g')
+                            .description(INFO_ADDRATE_DESCRIPTION_CONSTANT.get())
+                            .multiValued()
+                            .valuePlaceholder(INFO_CONSTANT_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             /* addrate specifics arguments */
             deleteMode =
-                new MultiChoiceArgument<>("deletemode", 'C', "deleteMode", false, true,
-                    INFO_DELETEMODE_PLACEHOLDER.get(), Arrays.asList(DeleteStrategy.values()), false,
-                    INFO_ADDRATE_DESCRIPTION_DELETEMODE.get());
-            deleteMode.setDefaultValue(DeleteStrategy.FIFO.toString());
-            argParser.addArgument(deleteMode);
+                    MultiChoiceArgument.<DeleteStrategy>builder("deleteMode")
+                            .shortIdentifier('C')
+                            .description(INFO_ADDRATE_DESCRIPTION_DELETEMODE.get())
+                            .allowedValues(DeleteStrategy.values())
+                            .defaultValue(DeleteStrategy.FIFO)
+                            .valuePlaceholder(INFO_DELETEMODE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             deleteSizeThreshold =
-                new IntegerArgument("deletesizethreshold", 's', "deleteSizeThreshold", false, false, true,
-                    INFO_DELETESIZETHRESHOLD_PLACEHOLDER.get(), DEFAULT_SIZE_THRESHOLD, "deleteSizeThreshold", true,
-                    SIZE_THRESHOLD_LOWERBOUND, false, Integer.MAX_VALUE,
-                    INFO_ADDRATE_DESCRIPTION_DELETESIZETHRESHOLD.get());
-            argParser.addArgument(deleteSizeThreshold);
+                    IntegerArgument.builder("deleteSizeThreshold")
+                            .shortIdentifier('s')
+                            .description(INFO_ADDRATE_DESCRIPTION_DELETESIZETHRESHOLD.get())
+                            .lowerBound(SIZE_THRESHOLD_LOWERBOUND)
+                            .defaultValue(DEFAULT_SIZE_THRESHOLD)
+                            .valuePlaceholder(INFO_DELETESIZETHRESHOLD_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             deleteAgeThreshold =
-                new IntegerArgument("deleteagethreshold", 'a', "deleteAgeThreshold", false, true,
-                    INFO_DELETEAGETHRESHOLD_PLACEHOLDER.get(), true, AGE_THRESHOLD_LOWERBOUND, false,
-                    Integer.MAX_VALUE, INFO_ADDRATE_DESCRIPTION_DELETEAGETHRESHOLD.get());
-            deleteAgeThreshold.setPropertyName(deleteAgeThreshold.getLongIdentifier());
-            argParser.addArgument(deleteAgeThreshold);
+                    IntegerArgument.builder("deleteAgeThreshold")
+                            .shortIdentifier('a')
+                            .description(INFO_ADDRATE_DESCRIPTION_DELETEAGETHRESHOLD.get())
+                            .lowerBound(AGE_THRESHOLD_LOWERBOUND)
+                            .valuePlaceholder(INFO_DELETEAGETHRESHOLD_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
-            noPurgeArgument = new BooleanArgument("nopurge", 'n', "noPurge", INFO_ADDRATE_DESCRIPTION_NOPURGE.get());
-            argParser.addArgument(noPurgeArgument);
+            noPurgeArgument =
+                    BooleanArgument.builder("noPurge")
+                        .shortIdentifier('n')
+                        .description(INFO_ADDRATE_DESCRIPTION_NOPURGE.get())
+                        .buildAndAddToParser(argParser);
         } catch (final ArgumentException ae) {
             errPrintln(ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()));
             return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -530,8 +544,9 @@
         argParser.addArgument(verbose);
 
         scriptFriendly =
-            new BooleanArgument("scriptFriendly", 'S', "scriptFriendly", INFO_DESCRIPTION_SCRIPT_FRIENDLY.get());
-        scriptFriendly.setPropertyName("scriptFriendly");
-        argParser.addArgument(scriptFriendly);
+                BooleanArgument.builder("scriptFriendly")
+                        .shortIdentifier('S')
+                        .description(INFO_DESCRIPTION_SCRIPT_FRIENDLY.get())
+                        .buildAndAddToParser(argParser);
     }
 }
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AuthRate.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AuthRate.java
index 881e5d3..14be107 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AuthRate.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AuthRate.java
@@ -424,41 +424,42 @@
             argParser.setUsageArgument(showUsage, getOutputStream());
 
             baseDN =
-                    new StringArgument("baseDN", OPTION_SHORT_BASEDN, OPTION_LONG_BASEDN, false,
-                            false, true, INFO_BASEDN_PLACEHOLDER.get(), null, null,
-                            INFO_SEARCHRATE_TOOL_DESCRIPTION_BASEDN.get());
-            baseDN.setPropertyName(OPTION_LONG_BASEDN);
-            argParser.addArgument(baseDN);
+                    StringArgument.builder(OPTION_LONG_BASEDN)
+                            .shortIdentifier(OPTION_SHORT_BASEDN)
+                            .description(INFO_SEARCHRATE_TOOL_DESCRIPTION_BASEDN.get())
+                            .valuePlaceholder(INFO_BASEDN_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             searchScope = CommonArguments.getSearchScope();
             argParser.addArgument(searchScope);
 
             dereferencePolicy =
-                    new MultiChoiceArgument<>("derefpolicy", 'a',
-                            "dereferencePolicy", false, true, INFO_DEREFERENCE_POLICE_PLACEHOLDER
-                                    .get(), DereferenceAliasesPolicy.values(), false,
-                            INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY.get());
-            dereferencePolicy.setPropertyName("dereferencePolicy");
-            dereferencePolicy.setDefaultValue(DereferenceAliasesPolicy.NEVER);
-            argParser.addArgument(dereferencePolicy);
+                    MultiChoiceArgument.<DereferenceAliasesPolicy>builder("dereferencePolicy")
+                            .shortIdentifier('a')
+                            .description(INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY.get())
+                            .allowedValues(DereferenceAliasesPolicy.values())
+                            .defaultValue(DereferenceAliasesPolicy.NEVER)
+                            .valuePlaceholder(INFO_DEREFERENCE_POLICE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             invalidCredPercent =
-                    new IntegerArgument("invalidPassword", 'I', "invalidPassword", false, false,
-                            true, LocalizableMessage.raw("{invalidPassword}"), 0, null, true, 0,
-                            true, 100, LocalizableMessage
-                                    .raw("Percent of bind operations with simulated "
-                                            + "invalid password"));
-            invalidCredPercent.setPropertyName("invalidPassword");
-            argParser.addArgument(invalidCredPercent);
+                    IntegerArgument.builder("invalidPassword")
+                            .shortIdentifier('I')
+                            .description(LocalizableMessage.raw(
+                                    "Percent of bind operations with simulated invalid password"))
+                            .range(0, 100)
+                            .defaultValue(0)
+                            .valuePlaceholder(LocalizableMessage.raw("{invalidPassword}"))
+                            .buildAndAddToParser(argParser);
 
             verbose = CommonArguments.getVerbose();
             argParser.addArgument(verbose);
 
             scriptFriendly =
-                    new BooleanArgument("scriptFriendly", 'S', "scriptFriendly",
-                            INFO_DESCRIPTION_SCRIPT_FRIENDLY.get());
-            scriptFriendly.setPropertyName("scriptFriendly");
-            argParser.addArgument(scriptFriendly);
+                    BooleanArgument.builder("scriptFriendly")
+                            .shortIdentifier('S')
+                            .description(INFO_DESCRIPTION_SCRIPT_FRIENDLY.get())
+                            .buildAndAddToParser(argParser);
         } catch (final ArgumentException ae) {
             final LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
             errPrintln(message);
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPCompare.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPCompare.java
index b1f339f..799fd37 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPCompare.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPCompare.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
- *      Portions Copyright 2011-2015 ForgeRock AS.
+ *      Portions Copyright 2011-2016 ForgeRock AS.
  */
 package com.forgerock.opendj.ldap.tools;
 
@@ -177,11 +177,10 @@
             argParser.addArgument(proxyAuthzID);
 
             assertionFilter =
-                    new StringArgument("assertionfilter", null, OPTION_LONG_ASSERTION_FILE, false,
-                            false, true, INFO_ASSERTION_FILTER_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_ASSERTION_FILTER.get());
-            assertionFilter.setPropertyName(OPTION_LONG_ASSERTION_FILE);
-            argParser.addArgument(assertionFilter);
+                    StringArgument.builder(OPTION_LONG_ASSERTION_FILE)
+                            .description(INFO_DESCRIPTION_ASSERTION_FILTER.get())
+                            .valuePlaceholder(INFO_ASSERTION_FILTER_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             controlStr = CommonArguments.getControl();
             argParser.addArgument(controlStr);
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPModify.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPModify.java
index c87a3dd..e9453f8 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPModify.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPModify.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
- *      Portions Copyright 2011-2015 ForgeRock AS.
+ *      Portions Copyright 2011-2016 ForgeRock AS.
  */
 package com.forgerock.opendj.ldap.tools;
 
@@ -259,14 +259,11 @@
         BindRequest bindRequest;
 
         BooleanArgument continueOnError;
-        // TODO: Remove this due to new LDIF reader api?
-        BooleanArgument defaultAdd;
         BooleanArgument noop;
         BooleanArgument showUsage;
         IntegerArgument version;
         StringArgument assertionFilter;
         StringArgument controlStr;
-        StringArgument encodingStr;
         StringArgument filename;
         StringArgument postReadAttributes;
         StringArgument preReadAttributes;
@@ -285,64 +282,55 @@
             argParser.addArgument(noPropertiesFileArgument);
             argParser.setNoPropertiesFileArgument(noPropertiesFileArgument);
 
-            defaultAdd =
-                    new BooleanArgument("defaultAdd", 'a', "defaultAdd",
-                            INFO_MODIFY_DESCRIPTION_DEFAULT_ADD.get());
-            argParser.addArgument(defaultAdd);
+            // TODO: Remove this due to new LDIF reader api?
+            BooleanArgument.builder("defaultAdd")
+                    .shortIdentifier('a')
+                    .description(INFO_MODIFY_DESCRIPTION_DEFAULT_ADD.get())
+                    .buildAndAddToParser(argParser);
 
+            StringArgument.builder("encoding")
+                    .shortIdentifier('i')
+                    .description(INFO_DESCRIPTION_ENCODING.get())
+                    .valuePlaceholder(INFO_ENCODING_PLACEHOLDER.get())
+                    .buildAndAddToParser(argParser);
             filename =
-                    new StringArgument("filename", OPTION_SHORT_FILENAME, OPTION_LONG_FILENAME,
-                            false, false, true, INFO_FILE_PLACEHOLDER.get(), null, null,
-                            INFO_LDAPMODIFY_DESCRIPTION_FILENAME.get());
-            filename.setPropertyName(OPTION_LONG_FILENAME);
-            argParser.addArgument(filename);
-
+                    StringArgument.builder(OPTION_LONG_FILENAME)
+                            .shortIdentifier(OPTION_SHORT_FILENAME)
+                            .description(INFO_LDAPMODIFY_DESCRIPTION_FILENAME.get())
+                            .valuePlaceholder(INFO_FILE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             proxyAuthzID =
-                    new StringArgument("proxy_authzid", OPTION_SHORT_PROXYAUTHID,
-                            OPTION_LONG_PROXYAUTHID, false, false, true,
-                            INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_PROXY_AUTHZID.get());
-            proxyAuthzID.setPropertyName(OPTION_LONG_PROXYAUTHID);
-            argParser.addArgument(proxyAuthzID);
-
+                    StringArgument.builder(OPTION_LONG_PROXYAUTHID)
+                            .shortIdentifier(OPTION_SHORT_PROXYAUTHID)
+                            .description(INFO_DESCRIPTION_PROXY_AUTHZID.get())
+                            .valuePlaceholder(INFO_PROXYAUTHID_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             assertionFilter =
-                    new StringArgument("assertionfilter", null, OPTION_LONG_ASSERTION_FILE, false,
-                            false, true, INFO_ASSERTION_FILTER_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_ASSERTION_FILTER.get());
-            assertionFilter.setPropertyName(OPTION_LONG_ASSERTION_FILE);
-            argParser.addArgument(assertionFilter);
-
+                    StringArgument.builder(OPTION_LONG_ASSERTION_FILE)
+                            .description(INFO_DESCRIPTION_ASSERTION_FILTER.get())
+                            .valuePlaceholder(INFO_ASSERTION_FILTER_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             preReadAttributes =
-                    new StringArgument("prereadattrs", null, "preReadAttributes", false, false,
-                            true, INFO_ATTRIBUTE_LIST_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_PREREAD_ATTRS.get());
-            preReadAttributes.setPropertyName("preReadAttributes");
-            argParser.addArgument(preReadAttributes);
-
+                    StringArgument.builder("preReadAttributes")
+                            .description(INFO_DESCRIPTION_PREREAD_ATTRS.get())
+                            .valuePlaceholder(INFO_ATTRIBUTE_LIST_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             postReadAttributes =
-                    new StringArgument("postreadattrs", null, "postReadAttributes", false, false,
-                            true, INFO_ATTRIBUTE_LIST_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_POSTREAD_ATTRS.get());
-            postReadAttributes.setPropertyName("postReadAttributes");
-            argParser.addArgument(postReadAttributes);
-
+                    StringArgument.builder("postReadAttributes")
+                            .description(INFO_DESCRIPTION_POSTREAD_ATTRS.get())
+                            .valuePlaceholder(INFO_ATTRIBUTE_LIST_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             controlStr =
-                    new StringArgument("control", 'J', "control", false, true, true,
-                            INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_CONTROLS.get());
-            controlStr.setPropertyName("control");
-            argParser.addArgument(controlStr);
+                    StringArgument.builder("control")
+                            .shortIdentifier('J')
+                            .description(INFO_DESCRIPTION_CONTROLS.get())
+                            .multiValued()
+                            .valuePlaceholder(INFO_LDAP_CONTROL_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             version = CommonArguments.getLdapVersion();
             argParser.addArgument(version);
 
-            encodingStr =
-                    new StringArgument("encoding", 'i', "encoding", false, false, true,
-                            INFO_ENCODING_PLACEHOLDER.get(), null, null, INFO_DESCRIPTION_ENCODING
-                                    .get());
-            encodingStr.setPropertyName("encoding");
-            argParser.addArgument(encodingStr);
-
             continueOnError = CommonArguments.getContinueOnError();
             argParser.addArgument(continueOnError);
 
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPPasswordModify.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPPasswordModify.java
index 22ed97a..81b04a2 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPPasswordModify.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPPasswordModify.java
@@ -22,10 +22,13 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
- *      Portions Copyright 2011-2015 ForgeRock AS.
+ *      Portions Copyright 2011-2016 ForgeRock AS.
  */
 package com.forgerock.opendj.ldap.tools;
 
+import static com.forgerock.opendj.cli.CliMessages.INFO_FILE_PLACEHOLDER;
+import static com.forgerock.opendj.cli.CliMessages.INFO_LDAPPWMOD_DESCRIPTION_CURRENTPWFILE;
+import static com.forgerock.opendj.cli.CliMessages.INFO_LDAPPWMOD_DESCRIPTION_NEWPWFILE;
 import static com.forgerock.opendj.ldap.tools.ToolsMessages.*;
 import static com.forgerock.opendj.cli.Utils.filterExitCode;
 
@@ -127,46 +130,42 @@
             argParser.setNoPropertiesFileArgument(noPropertiesFileArgument);
 
             newPW =
-                    new StringArgument("newpw", 'n', "newPassword", false, false, true,
-                            INFO_NEW_PASSWORD_PLACEHOLDER.get(), null, null,
-                            INFO_LDAPPWMOD_DESCRIPTION_NEWPW.get());
-            newPW.setPropertyName("newPassword");
-            argParser.addArgument(newPW);
-
+                    StringArgument.builder("newPassword")
+                            .shortIdentifier('n')
+                            .description(INFO_LDAPPWMOD_DESCRIPTION_NEWPW.get())
+                            .valuePlaceholder(INFO_NEW_PASSWORD_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             newPWFile =
-                    new FileBasedArgument("newpwfile", 'F', "newPasswordFile", false, false,
-                            INFO_FILE_PLACEHOLDER.get(), null, null,
-                            INFO_LDAPPWMOD_DESCRIPTION_NEWPWFILE.get());
-            newPWFile.setPropertyName("newPasswordFile");
-            argParser.addArgument(newPWFile);
-
+                    FileBasedArgument.builder("newPasswordFile")
+                            .shortIdentifier('F')
+                            .description(INFO_LDAPPWMOD_DESCRIPTION_NEWPWFILE.get())
+                            .valuePlaceholder(INFO_FILE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             currentPW =
-                    new StringArgument("currentpw", 'c', "currentPassword", false, false, true,
-                            INFO_CURRENT_PASSWORD_PLACEHOLDER.get(), null, null,
-                            INFO_LDAPPWMOD_DESCRIPTION_CURRENTPW.get());
-            currentPW.setPropertyName("currentPassword");
-            argParser.addArgument(currentPW);
-
+                    StringArgument.builder("currentPassword")
+                            .shortIdentifier('c')
+                            .description(INFO_LDAPPWMOD_DESCRIPTION_CURRENTPW.get())
+                            .valuePlaceholder(INFO_CURRENT_PASSWORD_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             currentPWFile =
-                    new FileBasedArgument("currentpwfile", 'C', "currentPasswordFile", false,
-                            false, INFO_FILE_PLACEHOLDER.get(), null, null,
-                            INFO_LDAPPWMOD_DESCRIPTION_CURRENTPWFILE.get());
-            currentPWFile.setPropertyName("currentPasswordFile");
-            argParser.addArgument(currentPWFile);
-
+                    FileBasedArgument.builder("currentPasswordFile")
+                            .shortIdentifier('C')
+                            .description(INFO_LDAPPWMOD_DESCRIPTION_CURRENTPWFILE.get())
+                            .valuePlaceholder(INFO_FILE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             proxyAuthzID =
-                    new StringArgument("authzid", 'a', "authzID", false, false, true,
-                            INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
-                            INFO_LDAPPWMOD_DESCRIPTION_AUTHZID.get());
-            proxyAuthzID.setPropertyName("authzID");
-            argParser.addArgument(proxyAuthzID);
-
+                    StringArgument.builder("authzID")
+                            .shortIdentifier('a')
+                            .description(INFO_LDAPPWMOD_DESCRIPTION_AUTHZID.get())
+                            .valuePlaceholder(INFO_PROXYAUTHID_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             controlStr =
-                    new StringArgument("control", 'J', "control", false, true, true,
-                            INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_CONTROLS.get());
-            controlStr.setPropertyName("control");
-            argParser.addArgument(controlStr);
+                    StringArgument.builder("control")
+                            .shortIdentifier('J')
+                            .description(INFO_DESCRIPTION_CONTROLS.get())
+                            .multiValued()
+                            .valuePlaceholder(INFO_LDAP_CONTROL_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             version = CommonArguments.getLdapVersion();
             argParser.addArgument(version);
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPSearch.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPSearch.java
index 1dcc3fa..8153753 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPSearch.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPSearch.java
@@ -84,6 +84,12 @@
 import com.forgerock.opendj.ldap.controls.AccountUsabilityResponseControl;
 import com.forgerock.opendj.util.StaticUtils;
 
+import static com.forgerock.opendj.cli.CliMessages.INFO_DESCRIPTION_SIMPLE_PAGE_SIZE;
+import static com.forgerock.opendj.cli.CliMessages.INFO_NUM_ENTRIES_PLACEHOLDER;
+import static com.forgerock.opendj.cli.CliMessages.INFO_SEARCH_DESCRIPTION_SIZE_LIMIT;
+import static com.forgerock.opendj.cli.CliMessages.INFO_SEARCH_DESCRIPTION_TIME_LIMIT;
+import static com.forgerock.opendj.cli.CliMessages.INFO_SIZE_LIMIT_PLACEHOLDER;
+import static com.forgerock.opendj.cli.CliMessages.INFO_TIME_LIMIT_PLACEHOLDER;
 import static com.forgerock.opendj.ldap.tools.Utils.printErrorMessage;
 import static com.forgerock.opendj.ldap.tools.Utils.printPasswordPolicyResults;
 import static org.forgerock.util.Utils.*;
@@ -271,146 +277,132 @@
             argParser.setNoPropertiesFileArgument(noPropertiesFileArgument);
 
             baseDN =
-                    new StringArgument("baseDN", OPTION_SHORT_BASEDN, OPTION_LONG_BASEDN, true,
-                            false, true, INFO_BASEDN_PLACEHOLDER.get(), null, null,
-                            INFO_SEARCH_DESCRIPTION_BASEDN.get());
-            baseDN.setPropertyName(OPTION_LONG_BASEDN);
-            argParser.addArgument(baseDN);
+                    StringArgument.builder(OPTION_LONG_BASEDN)
+                            .shortIdentifier(OPTION_SHORT_BASEDN)
+                            .description(INFO_SEARCH_DESCRIPTION_BASEDN.get())
+                            .required()
+                            .valuePlaceholder(INFO_BASEDN_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             searchScope = CommonArguments.getSearchScope();
             argParser.addArgument(searchScope);
 
             filename =
-                    new StringArgument("filename", OPTION_SHORT_FILENAME, OPTION_LONG_FILENAME,
-                            false, false, true, INFO_FILE_PLACEHOLDER.get(), null, null,
-                            INFO_SEARCH_DESCRIPTION_FILENAME.get());
-            searchScope.setPropertyName(OPTION_LONG_FILENAME);
-            argParser.addArgument(filename);
-
+                    StringArgument.builder(OPTION_LONG_FILENAME)
+                            .shortIdentifier(OPTION_SHORT_FILENAME)
+                            .description(INFO_SEARCH_DESCRIPTION_FILENAME.get())
+                            .valuePlaceholder(INFO_FILE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             proxyAuthzID =
-                    new StringArgument("proxy_authzid", OPTION_SHORT_PROXYAUTHID,
-                            OPTION_LONG_PROXYAUTHID, false, false, true,
-                            INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_PROXY_AUTHZID.get());
-            proxyAuthzID.setPropertyName(OPTION_LONG_PROXYAUTHID);
-            argParser.addArgument(proxyAuthzID);
-
+                    StringArgument.builder(OPTION_LONG_PROXYAUTHID)
+                            .shortIdentifier(OPTION_SHORT_PROXYAUTHID)
+                            .description(INFO_DESCRIPTION_PROXY_AUTHZID.get())
+                            .valuePlaceholder(INFO_PROXYAUTHID_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             pSearchInfo =
-                    new StringArgument("psearchinfo", 'C', "persistentSearch", false, false, true,
-                            INFO_PSEARCH_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_PSEARCH_INFO.get());
-            pSearchInfo.setPropertyName("persistentSearch");
-            pSearchInfo.setDocDescriptionSupplement(SUPPLEMENT_DESCRIPTION_PSEARCH_INFO.get());
-            argParser.addArgument(pSearchInfo);
-
+                    StringArgument.builder("persistentSearch")
+                            .shortIdentifier('C')
+                            .description(INFO_DESCRIPTION_PSEARCH_INFO.get())
+                            .docDescriptionSupplement(SUPPLEMENT_DESCRIPTION_PSEARCH_INFO.get())
+                            .valuePlaceholder(INFO_PSEARCH_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             simplePageSize =
-                    new IntegerArgument("simplepagesize", null, "simplePageSize", false, false,
-                            true, INFO_NUM_ENTRIES_PLACEHOLDER.get(), 1000, null, true, 1, false,
-                            0, INFO_DESCRIPTION_SIMPLE_PAGE_SIZE.get());
-            simplePageSize.setPropertyName("simplePageSize");
-            argParser.addArgument(simplePageSize);
-
+                    IntegerArgument.builder("simplePageSize")
+                            .description(INFO_DESCRIPTION_SIMPLE_PAGE_SIZE.get())
+                            .lowerBound(1)
+                            .defaultValue(1000)
+                            .valuePlaceholder(INFO_NUM_ENTRIES_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             assertionFilter =
-                    new StringArgument("assertionfilter", null, OPTION_LONG_ASSERTION_FILE, false,
-                            false, true, INFO_ASSERTION_FILTER_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_ASSERTION_FILTER.get());
-            assertionFilter.setPropertyName(OPTION_LONG_ASSERTION_FILE);
-            argParser.addArgument(assertionFilter);
-
+                    StringArgument.builder(OPTION_LONG_ASSERTION_FILE)
+                            .description(INFO_DESCRIPTION_ASSERTION_FILTER.get())
+                            .valuePlaceholder(INFO_ASSERTION_FILTER_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             matchedValuesFilter =
-                    new StringArgument("matchedvalues", null, "matchedValuesFilter", false, true,
-                            true, INFO_FILTER_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_MATCHED_VALUES_FILTER.get());
-            matchedValuesFilter.setPropertyName("matchedValuesFilter");
-            argParser.addArgument(matchedValuesFilter);
-
+                    StringArgument.builder("matchedValuesFilter")
+                            .description(INFO_DESCRIPTION_MATCHED_VALUES_FILTER.get())
+                            .multiValued()
+                            .valuePlaceholder(INFO_FILTER_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             sortOrder =
-                    new StringArgument("sortorder", 'S', "sortOrder", false, false, true,
-                            INFO_SORT_ORDER_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_SORT_ORDER.get());
-            sortOrder.setPropertyName("sortOrder");
-            argParser.addArgument(sortOrder);
-
+                    StringArgument.builder("sortOrder")
+                            .shortIdentifier('S')
+                            .description(INFO_DESCRIPTION_SORT_ORDER.get())
+                            .valuePlaceholder(INFO_SORT_ORDER_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             vlvDescriptor =
-                    new StringArgument("vlvdescriptor", 'G', "virtualListView", false, false, true,
-                            INFO_VLV_PLACEHOLDER.get(), null, null, INFO_DESCRIPTION_VLV.get());
-            vlvDescriptor.setPropertyName("virtualListView");
-            argParser.addArgument(vlvDescriptor);
-
+                    StringArgument.builder("virtualListView")
+                            .shortIdentifier('G')
+                            .description(INFO_DESCRIPTION_VLV.get())
+                            .valuePlaceholder(INFO_VLV_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             controlStr =
-                    new StringArgument("control", 'J', "control", false, true, true,
-                            INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_CONTROLS.get());
-            controlStr.setPropertyName("control");
-            controlStr.setDocDescriptionSupplement(SUPPLEMENT_DESCRIPTION_CONTROLS.get());
-            argParser.addArgument(controlStr);
-
+                    StringArgument.builder("control")
+                            .shortIdentifier('J')
+                            .description(INFO_DESCRIPTION_CONTROLS.get())
+                            .docDescriptionSupplement(SUPPLEMENT_DESCRIPTION_CONTROLS.get())
+                            .multiValued()
+                            .valuePlaceholder(INFO_LDAP_CONTROL_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             effectiveRightsUser =
-                    new StringArgument("effectiveRightsUser", OPTION_SHORT_EFFECTIVERIGHTSUSER,
-                            OPTION_LONG_EFFECTIVERIGHTSUSER, false, false, true,
-                            INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_EFFECTIVERIGHTS_USER.get());
-            effectiveRightsUser.setPropertyName(OPTION_LONG_EFFECTIVERIGHTSUSER);
-            argParser.addArgument(effectiveRightsUser);
-
+                    StringArgument.builder(OPTION_LONG_EFFECTIVERIGHTSUSER)
+                            .shortIdentifier(OPTION_SHORT_EFFECTIVERIGHTSUSER)
+                            .description(INFO_DESCRIPTION_EFFECTIVERIGHTS_USER.get())
+                            .valuePlaceholder(INFO_PROXYAUTHID_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             effectiveRightsAttrs =
-                    new StringArgument("effectiveRightsAttrs", OPTION_SHORT_EFFECTIVERIGHTSATTR,
-                            OPTION_LONG_EFFECTIVERIGHTSATTR, false, true, true,
-                            INFO_ATTRIBUTE_PLACEHOLDER.get(), null, null,
-                            INFO_DESCRIPTION_EFFECTIVERIGHTS_ATTR.get());
-            effectiveRightsAttrs.setPropertyName(OPTION_LONG_EFFECTIVERIGHTSATTR);
-            argParser.addArgument(effectiveRightsAttrs);
+                    StringArgument.builder(OPTION_LONG_EFFECTIVERIGHTSATTR)
+                            .shortIdentifier(OPTION_SHORT_EFFECTIVERIGHTSATTR)
+                            .description(INFO_DESCRIPTION_EFFECTIVERIGHTS_ATTR.get())
+                            .multiValued()
+                            .valuePlaceholder(INFO_ATTRIBUTE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             version = CommonArguments.getLdapVersion();
             argParser.addArgument(version);
 
-            final StringArgument encodingStr =
-                    new StringArgument("encoding", 'i', "encoding", false, false, true,
-                            INFO_ENCODING_PLACEHOLDER.get(), null, null, INFO_DESCRIPTION_ENCODING
-                                    .get());
-            encodingStr.setPropertyName("encoding");
-            argParser.addArgument(encodingStr);
+            StringArgument.builder("encoding")
+                    .shortIdentifier('i')
+                    .description(INFO_DESCRIPTION_ENCODING.get())
+                    .valuePlaceholder(INFO_ENCODING_PLACEHOLDER.get())
+                    .buildAndAddToParser(argParser);
 
             dereferencePolicy =
-                    new MultiChoiceArgument<>("derefpolicy", 'a',
-                            "dereferencePolicy", false, true, INFO_DEREFERENCE_POLICE_PLACEHOLDER
-                                    .get(), DereferenceAliasesPolicy.values(), false,
-                            INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY.get());
-            dereferencePolicy.setPropertyName("dereferencePolicy");
-            dereferencePolicy.setDefaultValue(DereferenceAliasesPolicy.NEVER);
-            argParser.addArgument(dereferencePolicy);
-
+                    MultiChoiceArgument.<DereferenceAliasesPolicy>builder("dereferencePolicy")
+                            .shortIdentifier('a')
+                            .description(INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY.get())
+                            .allowedValues(DereferenceAliasesPolicy.values())
+                            .defaultValue(DereferenceAliasesPolicy.NEVER)
+                            .valuePlaceholder(INFO_DEREFERENCE_POLICE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             typesOnly =
-                    new BooleanArgument("typesOnly", 'A', "typesOnly", INFO_DESCRIPTION_TYPES_ONLY
-                            .get());
-            typesOnly.setPropertyName("typesOnly");
-            argParser.addArgument(typesOnly);
-
+                    BooleanArgument.builder("typesOnly")
+                            .shortIdentifier('A')
+                            .description(INFO_DESCRIPTION_TYPES_ONLY.get())
+                            .buildAndAddToParser(argParser);
             sizeLimit =
-                    new IntegerArgument("sizeLimit", 'z', "sizeLimit", false, false, true,
-                            INFO_SIZE_LIMIT_PLACEHOLDER.get(), 0, null,
-                            INFO_SEARCH_DESCRIPTION_SIZE_LIMIT.get());
-            sizeLimit.setPropertyName("sizeLimit");
-            argParser.addArgument(sizeLimit);
-
+                    IntegerArgument.builder("sizeLimit")
+                            .shortIdentifier('z')
+                            .description(INFO_SEARCH_DESCRIPTION_SIZE_LIMIT.get())
+                            .defaultValue(0)
+                            .valuePlaceholder(INFO_SIZE_LIMIT_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             timeLimit =
-                    new IntegerArgument("timeLimit", 'l', "timeLimit", false, false, true,
-                            INFO_TIME_LIMIT_PLACEHOLDER.get(), 0, null,
-                            INFO_SEARCH_DESCRIPTION_TIME_LIMIT.get());
-            timeLimit.setPropertyName("timeLimit");
-            argParser.addArgument(timeLimit);
-
+                    IntegerArgument.builder("timeLimit")
+                            .shortIdentifier('l')
+                            .description(INFO_SEARCH_DESCRIPTION_TIME_LIMIT.get())
+                            .defaultValue(0)
+                            .valuePlaceholder(INFO_TIME_LIMIT_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             dontWrap =
-                    new BooleanArgument("dontwrap", 't', "dontWrap", INFO_DESCRIPTION_DONT_WRAP
-                            .get());
-            dontWrap.setPropertyName("dontWrap");
-            argParser.addArgument(dontWrap);
-
+                    BooleanArgument.builder("dontWrap")
+                            .shortIdentifier('t')
+                            .description(INFO_DESCRIPTION_DONT_WRAP.get())
+                            .buildAndAddToParser(argParser);
             countEntries =
-                    new BooleanArgument("countentries", null, "countEntries",
-                            INFO_DESCRIPTION_COUNT_ENTRIES.get());
-            countEntries.setPropertyName("countEntries");
-            argParser.addArgument(countEntries);
+                    BooleanArgument.builder("countEntries")
+                            .description(INFO_DESCRIPTION_COUNT_ENTRIES.get())
+                            .buildAndAddToParser(argParser);
 
             final BooleanArgument continueOnError = CommonArguments.getContinueOnError();
             argParser.addArgument(continueOnError);
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFDiff.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFDiff.java
index d50c509..b54b7cb 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFDiff.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFDiff.java
@@ -87,12 +87,13 @@
         final StringArgument outputFilename;
         try {
             outputFilename =
-                    new StringArgument("outputFilename", OPTION_SHORT_OUTPUT_LDIF_FILENAME,
-                            OPTION_LONG_OUTPUT_LDIF_FILENAME, false, false, true,
-                            INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get(), "stdout", null,
-                            INFO_LDIFDIFF_DESCRIPTION_OUTPUT_FILENAME
-                                    .get(INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get()));
-            argParser.addArgument(outputFilename);
+                    StringArgument.builder(OPTION_LONG_OUTPUT_LDIF_FILENAME)
+                            .shortIdentifier(OPTION_SHORT_OUTPUT_LDIF_FILENAME)
+                            .description(INFO_LDIFDIFF_DESCRIPTION_OUTPUT_FILENAME.get(
+                                    INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get()))
+                            .defaultValue("stdout")
+                            .valuePlaceholder(INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             showUsage = CommonArguments.getShowUsage();
             argParser.addArgument(showUsage);
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFModify.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFModify.java
index f5a1ec1..2ef4c34 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFModify.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFModify.java
@@ -21,7 +21,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2012-2015 ForgeRock AS.
+ *      Copyright 2012-2016 ForgeRock AS.
  */
 package com.forgerock.opendj.ldap.tools;
 
@@ -94,12 +94,13 @@
         final StringArgument outputFilename;
         try {
             outputFilename =
-                    new StringArgument("outputFilename", OPTION_SHORT_OUTPUT_LDIF_FILENAME,
-                            OPTION_LONG_OUTPUT_LDIF_FILENAME, false, false, true,
-                            INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get(), "stdout", null,
-                            INFO_LDIFMODIFY_DESCRIPTION_OUTPUT_FILENAME
-                                    .get(INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get()));
-            argParser.addArgument(outputFilename);
+                    StringArgument.builder(OPTION_LONG_OUTPUT_LDIF_FILENAME)
+                            .shortIdentifier(OPTION_SHORT_OUTPUT_LDIF_FILENAME)
+                            .description(INFO_LDIFMODIFY_DESCRIPTION_OUTPUT_FILENAME.get(
+                                    INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get()))
+                            .defaultValue("stdout")
+                            .valuePlaceholder(INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             continueOnError = CommonArguments.getContinueOnError();
             argParser.addArgument(continueOnError);
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFSearch.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFSearch.java
index f9aa79a..3057645 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFSearch.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFSearch.java
@@ -26,6 +26,10 @@
 package com.forgerock.opendj.ldap.tools;
 
 import static com.forgerock.opendj.cli.ArgumentConstants.*;
+import static com.forgerock.opendj.cli.CliMessages.INFO_SEARCH_DESCRIPTION_SIZE_LIMIT;
+import static com.forgerock.opendj.cli.CliMessages.INFO_SEARCH_DESCRIPTION_TIME_LIMIT;
+import static com.forgerock.opendj.cli.CliMessages.INFO_SIZE_LIMIT_PLACEHOLDER;
+import static com.forgerock.opendj.cli.CliMessages.INFO_TIME_LIMIT_PLACEHOLDER;
 import static com.forgerock.opendj.ldap.tools.ToolsMessages.*;
 import static com.forgerock.opendj.cli.Utils.filterExitCode;
 import static org.forgerock.util.Utils.closeSilently;
@@ -98,49 +102,49 @@
         final IntegerArgument sizeLimit;
         try {
             outputFilename =
-                    new StringArgument("outputFilename", OPTION_SHORT_OUTPUT_LDIF_FILENAME,
-                            OPTION_LONG_OUTPUT_LDIF_FILENAME, false, false, true,
-                            INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get(), "stdout", null,
-                            INFO_LDIFSEARCH_DESCRIPTION_OUTPUT_FILENAME
-                                    .get(INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get()));
-            argParser.addArgument(outputFilename);
-
+                    StringArgument.builder(OPTION_LONG_OUTPUT_LDIF_FILENAME)
+                            .shortIdentifier(OPTION_SHORT_OUTPUT_LDIF_FILENAME)
+                            .description(INFO_LDIFSEARCH_DESCRIPTION_OUTPUT_FILENAME.get(
+                                    INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get()))
+                            .defaultValue("stdout")
+                            .valuePlaceholder(INFO_OUTPUT_LDIF_FILE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             baseDN =
-                    new StringArgument("baseDN", OPTION_SHORT_BASEDN, OPTION_LONG_BASEDN, true,
-                            false, true, INFO_BASEDN_PLACEHOLDER.get(), null, null,
-                            INFO_SEARCH_DESCRIPTION_BASEDN.get());
-            baseDN.setPropertyName(OPTION_LONG_BASEDN);
-            argParser.addArgument(baseDN);
+                    StringArgument.builder(OPTION_LONG_BASEDN)
+                            .shortIdentifier(OPTION_SHORT_BASEDN)
+                            .description(INFO_SEARCH_DESCRIPTION_BASEDN.get())
+                            .required()
+                            .valuePlaceholder(INFO_BASEDN_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             searchScope = CommonArguments.getSearchScope();
             argParser.addArgument(searchScope);
 
             filename =
-                    new StringArgument("filename", OPTION_SHORT_FILENAME, OPTION_LONG_FILENAME,
-                            false, false, true, INFO_FILE_PLACEHOLDER.get(), null, null,
-                            INFO_SEARCH_DESCRIPTION_FILENAME.get());
-            searchScope.setPropertyName(OPTION_LONG_FILENAME);
-            argParser.addArgument(filename);
-
+                    StringArgument.builder(OPTION_LONG_FILENAME)
+                            .shortIdentifier(OPTION_SHORT_FILENAME)
+                            .description(INFO_SEARCH_DESCRIPTION_FILENAME.get())
+                            .valuePlaceholder(INFO_FILE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             typesOnly =
-                    new BooleanArgument("typesOnly", 'A', "typesOnly", INFO_DESCRIPTION_TYPES_ONLY
-                            .get());
-            typesOnly.setPropertyName("typesOnly");
-            argParser.addArgument(typesOnly);
-
+                    BooleanArgument.builder("typesOnly")
+                            .shortIdentifier('A')
+                            .description(INFO_DESCRIPTION_TYPES_ONLY.get())
+                            .buildAndAddToParser(argParser);
             sizeLimit =
-                    new IntegerArgument("sizeLimit", 'z', "sizeLimit", false, false, true,
-                            INFO_SIZE_LIMIT_PLACEHOLDER.get(), 0, null,
-                            INFO_SEARCH_DESCRIPTION_SIZE_LIMIT.get());
-            sizeLimit.setPropertyName("sizeLimit");
-            argParser.addArgument(sizeLimit);
-
+                    IntegerArgument.builder("sizeLimit")
+                            .shortIdentifier('z')
+                            .description(INFO_SEARCH_DESCRIPTION_SIZE_LIMIT.get())
+                            .defaultValue(0)
+                            .valuePlaceholder(INFO_SIZE_LIMIT_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
             timeLimit =
-                    new IntegerArgument("timeLimit", 'l', "timeLimit", false, false, true,
-                            INFO_TIME_LIMIT_PLACEHOLDER.get(), 0, null,
-                            INFO_SEARCH_DESCRIPTION_TIME_LIMIT.get());
-            timeLimit.setPropertyName("timeLimit");
-            argParser.addArgument(timeLimit);
+                    IntegerArgument.builder("timeLimit")
+                            .shortIdentifier('l')
+                            .description(INFO_SEARCH_DESCRIPTION_TIME_LIMIT.get())
+                            .defaultValue(0)
+                            .valuePlaceholder(INFO_TIME_LIMIT_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             showUsage = CommonArguments.getShowUsage();
             argParser.addArgument(showUsage);
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/MakeLDIF.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/MakeLDIF.java
index 7347a0f..bfc1643 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/MakeLDIF.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/MakeLDIF.java
@@ -22,11 +22,13 @@
  *
  *
  *      Copyright 2006-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2013-2015 ForgeRock AS.
+ *      Portions Copyright 2013-2016 ForgeRock AS.
  */
 package com.forgerock.opendj.ldap.tools;
 
 import static com.forgerock.opendj.cli.ArgumentConstants.*;
+import static com.forgerock.opendj.cli.CliMessages.INFO_MAKELDIF_DESCRIPTION_SEED;
+import static com.forgerock.opendj.cli.CliMessages.INFO_SEED_PLACEHOLDER;
 import static com.forgerock.opendj.ldap.tools.ToolsMessages.*;
 import static com.forgerock.opendj.cli.Utils.filterExitCode;
 import static org.forgerock.util.Utils.closeSilently;
@@ -90,28 +92,39 @@
         StringArgument resourcePath;
         StringArgument constants;
         try {
-            resourcePath = new StringArgument("resourcepath", 'r', OPTION_LONG_RESOURCE_PATH, false, false, true,
-                    INFO_PATH_PLACEHOLDER.get(), null, null, INFO_MAKELDIF_DESCRIPTION_RESOURCE_PATH.get());
-            resourcePath.setDocDescriptionSupplement(SUPPLEMENT_DESCRIPTION_RESOURCE_PATH.get());
-            argParser.addArgument(resourcePath);
+            resourcePath =
+                    StringArgument.builder(OPTION_LONG_RESOURCE_PATH)
+                            .shortIdentifier('r')
+                            .description(INFO_MAKELDIF_DESCRIPTION_RESOURCE_PATH.get())
+                            .docDescriptionSupplement(SUPPLEMENT_DESCRIPTION_RESOURCE_PATH.get())
+                            .valuePlaceholder(INFO_PATH_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
+            ldifFile =
+                    StringArgument.builder(OPTION_LONG_OUTPUT_LDIF_FILENAME)
+                            .shortIdentifier(OPTION_SHORT_OUTPUT_LDIF_FILENAME)
+                            .description(INFO_MAKELDIF_DESCRIPTION_LDIF.get())
+                            .valuePlaceholder(INFO_FILE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
+            randomSeed =
+                    IntegerArgument.builder(OPTION_LONG_RANDOM_SEED)
+                            .shortIdentifier(OPTION_SHORT_RANDOM_SEED)
+                            .description(INFO_MAKELDIF_DESCRIPTION_SEED.get())
+                            .defaultValue(0)
+                            .valuePlaceholder(INFO_SEED_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
+            constants =
+                    StringArgument.builder(OPTION_LONG_CONSTANT)
+                            .shortIdentifier('c')
+                            .description(INFO_MAKELDIF_DESCRIPTION_CONSTANT.get())
+                            .multiValued()
+                            .valuePlaceholder(INFO_CONSTANT_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
+            showUsage =
+                    BooleanArgument.builder(OPTION_LONG_HELP)
+                            .shortIdentifier(OPTION_SHORT_HELP)
+                            .description(INFO_MAKELDIF_DESCRIPTION_HELP.get())
+                            .buildAndAddToParser(argParser);
 
-            ldifFile = new StringArgument("ldiffile", OPTION_SHORT_OUTPUT_LDIF_FILENAME,
-                    OPTION_LONG_OUTPUT_LDIF_FILENAME, false, false, true, INFO_FILE_PLACEHOLDER.get(),
-                    null, null, INFO_MAKELDIF_DESCRIPTION_LDIF.get());
-            argParser.addArgument(ldifFile);
-
-            randomSeed = new IntegerArgument("randomseed", OPTION_SHORT_RANDOM_SEED, OPTION_LONG_RANDOM_SEED, false,
-                    false, true, INFO_SEED_PLACEHOLDER.get(), 0, null, INFO_MAKELDIF_DESCRIPTION_SEED.get());
-            argParser.addArgument(randomSeed);
-
-            constants = new StringArgument("constant", 'c', OPTION_LONG_CONSTANT, false, true, true,
-                    INFO_CONSTANT_PLACEHOLDER.get(),
-                    null, null, INFO_MAKELDIF_DESCRIPTION_CONSTANT.get());
-            argParser.addArgument(constants);
-
-            showUsage = new BooleanArgument("help", OPTION_SHORT_HELP, OPTION_LONG_HELP,
-                    INFO_MAKELDIF_DESCRIPTION_HELP.get());
-            argParser.addArgument(showUsage);
             argParser.setUsageArgument(showUsage, getOutputStream());
         } catch (ArgumentException ae) {
             errPrintln(ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()));
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ModRate.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ModRate.java
index 85d499b..5a07cca 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ModRate.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ModRate.java
@@ -189,11 +189,12 @@
             argParser.setNoPropertiesFileArgument(noPropertiesFileArgument);
 
             baseDN =
-                    new StringArgument("targetDN", OPTION_SHORT_BASEDN, OPTION_LONG_TARGETDN, true,
-                            false, true, INFO_TARGETDN_PLACEHOLDER.get(), null, null,
-                            INFO_MODRATE_TOOL_DESCRIPTION_TARGETDN.get());
-            baseDN.setPropertyName(OPTION_LONG_BASEDN);
-            argParser.addArgument(baseDN);
+                    StringArgument.builder(OPTION_LONG_TARGETDN)
+                            .shortIdentifier(OPTION_SHORT_BASEDN)
+                            .description(INFO_MODRATE_TOOL_DESCRIPTION_TARGETDN.get())
+                            .required()
+                            .valuePlaceholder(INFO_TARGETDN_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             verbose = CommonArguments.getVerbose();
             argParser.addArgument(verbose);
@@ -203,10 +204,10 @@
             argParser.setUsageArgument(showUsage, getOutputStream());
 
             scriptFriendly =
-                    new BooleanArgument("scriptFriendly", 'S', "scriptFriendly",
-                            INFO_DESCRIPTION_SCRIPT_FRIENDLY.get());
-            scriptFriendly.setPropertyName("scriptFriendly");
-            argParser.addArgument(scriptFriendly);
+                    BooleanArgument.builder("scriptFriendly")
+                            .shortIdentifier('S')
+                            .description(INFO_DESCRIPTION_SCRIPT_FRIENDLY.get())
+                            .buildAndAddToParser(argParser);
         } catch (final ArgumentException ae) {
             final LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
             errPrintln(message);
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/PerformanceRunner.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/PerformanceRunner.java
index fb7da7f..38870e5 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/PerformanceRunner.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/PerformanceRunner.java
@@ -262,11 +262,15 @@
         ArgumentParser argParser = options.getArgumentParser();
 
         this.app = options.getConsoleApplication();
+
         numThreadsArgument =
-                new IntegerArgument("numThreads", 't', "numThreads", false, false, true,
-                        LocalizableMessage.raw("{numThreads}"), 1, null, true, 1, false, 0,
-                        LocalizableMessage.raw("Number of worker threads per connection"));
-        numThreadsArgument.setPropertyName("numThreads");
+                IntegerArgument.builder("numThreads")
+                        .shortIdentifier('t')
+                        .description(LocalizableMessage.raw("Number of worker threads per connection"))
+                        .lowerBound(1)
+                        .defaultValue(1)
+                        .valuePlaceholder(LocalizableMessage.raw("{numThreads}"))
+                        .buildArgument();
         if (options.supportsMultipleThreadsPerConnection()) {
             argParser.addArgument(numThreadsArgument);
         } else {
@@ -274,87 +278,87 @@
         }
 
         numConnectionsArgument =
-                new IntegerArgument("numConnections", 'c', "numConnections", false, false, true,
-                        LocalizableMessage.raw("{numConnections}"), 1, null, true, 1, false, 0,
-                        LocalizableMessage.raw("Number of connections"));
-        numConnectionsArgument.setPropertyName("numConnections");
-        argParser.addArgument(numConnectionsArgument);
-
+                IntegerArgument.builder("numConnections")
+                        .shortIdentifier('c')
+                        .description(LocalizableMessage.raw("Number of connections"))
+                        .lowerBound(1)
+                        .defaultValue(1)
+                        .valuePlaceholder(LocalizableMessage.raw("{numConnections}"))
+                        .buildAndAddToParser(argParser);
         maxIterationsArgument =
-                new IntegerArgument("maxIterations", 'm', "maxIterations", false, false, true,
-                        LocalizableMessage.raw("{maxIterations}"), 0, null,
-                        LocalizableMessage.raw("Max iterations, 0 for unlimited"));
-        maxIterationsArgument.setPropertyName("maxIterations");
-        argParser.addArgument(maxIterationsArgument);
-
+                IntegerArgument.builder("maxIterations")
+                        .shortIdentifier('m')
+                        .description(LocalizableMessage.raw("Max iterations, 0 for unlimited"))
+                        .defaultValue(0)
+                        .valuePlaceholder(LocalizableMessage.raw("{maxIterations}"))
+                        .buildAndAddToParser(argParser);
         maxDurationArgument =
-            new IntegerArgument("maxDuration", 'd', "maxDuration", false, false, true,
-                LocalizableMessage.raw("{maxDuration}"), 0, null, true, 1, false, 0,
-                LocalizableMessage.raw("Maximum duration in seconds, 0 for unlimited"));
-        argParser.addArgument(maxDurationArgument);
-
+                IntegerArgument.builder("maxDuration")
+                        .shortIdentifier('d')
+                        .description(LocalizableMessage.raw("Maximum duration in seconds, 0 for unlimited"))
+                        .lowerBound(1)
+                        .defaultValue(0)
+                        .valuePlaceholder(LocalizableMessage.raw("{maxDuration}"))
+                        .buildAndAddToParser(argParser);
         warmUpArgument =
-            new IntegerArgument("warmUpDuration", 'B', "warmUpDuration", false, false, true,
-                LocalizableMessage.raw("{warmUpDuration}"), 0, null,
-                LocalizableMessage.raw("Warm up duration in seconds"));
-        argParser.addArgument(warmUpArgument);
-
+                IntegerArgument.builder("warmUpDuration")
+                        .shortIdentifier('B')
+                        .description(LocalizableMessage.raw("Warm up duration in seconds"))
+                        .defaultValue(0)
+                        .valuePlaceholder(LocalizableMessage.raw("{warmUpDuration}"))
+                        .buildAndAddToParser(argParser);
         statsIntervalArgument =
-                new IntegerArgument("statInterval", 'i', "statInterval", false, false, true,
-                        LocalizableMessage.raw("{statInterval}"), 5, null, true, 1, false, 0,
-                        LocalizableMessage.raw("Display results each specified number of seconds"));
-        statsIntervalArgument.setPropertyName("statInterval");
-        argParser.addArgument(statsIntervalArgument);
-
+                IntegerArgument.builder("statInterval")
+                        .shortIdentifier('i')
+                        .description(LocalizableMessage.raw("Display results each specified number of seconds"))
+                        .lowerBound(1)
+                        .defaultValue(5)
+                        .valuePlaceholder(LocalizableMessage.raw("{statInterval}"))
+                        .buildAndAddToParser(argParser);
         targetThroughputArgument =
-                new IntegerArgument("targetThroughput", 'M', "targetThroughput", false, false,
-                        true, LocalizableMessage.raw("{targetThroughput}"), 0, null,
-                        LocalizableMessage.raw("Target average throughput to achieve"));
-        targetThroughputArgument.setPropertyName("targetThroughput");
-        argParser.addArgument(targetThroughputArgument);
-
+                IntegerArgument.builder("targetThroughput")
+                        .shortIdentifier('M')
+                        .description(LocalizableMessage.raw("Target average throughput to achieve"))
+                        .defaultValue(0)
+                        .valuePlaceholder(LocalizableMessage.raw("{targetThroughput}"))
+                        .buildAndAddToParser(argParser);
         percentilesArgument =
-                new IntegerArgument("percentile", 'e', "percentile", false, true,
-                        LocalizableMessage.raw("{percentile}"), true, 0, true, 100,
-                        LocalizableMessage.raw("Calculate max response time for a "
-                                + "percentile of operations"));
-        percentilesArgument.setPropertyName("percentile");
-        percentilesArgument.setMultiValued(true);
-        argParser.addArgument(percentilesArgument);
-
+                IntegerArgument.builder("percentile")
+                        .shortIdentifier('e')
+                        .description(
+                                LocalizableMessage.raw("Calculate max response time for a percentile of operations"))
+                        .multiValued()
+                        .range(0, 100)
+                        .valuePlaceholder(LocalizableMessage.raw("{percentile}"))
+                        .buildAndAddToParser(argParser);
         keepConnectionsOpen =
-                new BooleanArgument("keepConnectionsOpen", 'f', "keepConnectionsOpen",
-                        LocalizableMessage.raw("Keep connections open"));
-        keepConnectionsOpen.setPropertyName("keepConnectionsOpen");
-        argParser.addArgument(keepConnectionsOpen);
-
+                BooleanArgument.builder("keepConnectionsOpen")
+                        .shortIdentifier('f')
+                        .description(LocalizableMessage.raw("Keep connections open"))
+                        .buildAndAddToParser(argParser);
         noRebindArgument =
-                new BooleanArgument("noRebind", 'F', "noRebind", LocalizableMessage
-                        .raw("Keep connections open and do not rebind"));
-        noRebindArgument.setPropertyName("noRebind");
+                BooleanArgument.builder("noRebind")
+                        .shortIdentifier('F')
+                        .description(LocalizableMessage.raw("Keep connections open and do not rebind"))
+                        .buildArgument();
         if (options.supportsRebind()) {
             argParser.addArgument(noRebindArgument);
         }
 
         arguments =
-                new StringArgument(
-                        "argument",
-                        'g',
-                        "argument",
-                        false,
-                        true,
-                        true,
-                        LocalizableMessage.raw("{generator function or static string}"),
-                        null,
-                        null,
-                        LocalizableMessage
+                StringArgument.builder("argument")
+                        .shortIdentifier('g')
+                        .description(LocalizableMessage
                                 .raw("Argument used to evaluate the Java "
                                         + "style format strings in program parameters (ie. Base DN, "
                                         + "Search Filter). The set of all arguments provided form the "
                                         + "the argument list in order. Besides static string "
                                         + "arguments, they can be generated per iteration with the "
                                         + "following functions: " + StaticUtils.EOL
-                                        + DataSource.getUsage()));
+                                        + DataSource.getUsage()))
+                        .multiValued()
+                        .valuePlaceholder(LocalizableMessage.raw("{generator function or static string}"))
+                        .buildArgument();
         if (options.supportsGeneratorArgument()) {
             argParser.addArgument(arguments);
         }
diff --git a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/SearchRate.java b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/SearchRate.java
index f6d7831..0eb2592 100644
--- a/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/SearchRate.java
+++ b/opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/SearchRate.java
@@ -241,32 +241,33 @@
             argParser.setUsageArgument(showUsage, getOutputStream());
 
             baseDN =
-                    new StringArgument("baseDN", OPTION_SHORT_BASEDN, OPTION_LONG_BASEDN, true,
-                            false, true, INFO_BASEDN_PLACEHOLDER.get(), null, null,
-                            INFO_SEARCHRATE_TOOL_DESCRIPTION_BASEDN.get());
-            baseDN.setPropertyName(OPTION_LONG_BASEDN);
-            argParser.addArgument(baseDN);
+                    StringArgument.builder(OPTION_LONG_BASEDN)
+                            .shortIdentifier(OPTION_SHORT_BASEDN)
+                            .description(INFO_SEARCHRATE_TOOL_DESCRIPTION_BASEDN.get())
+                            .required()
+                            .valuePlaceholder(INFO_BASEDN_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             searchScope = CommonArguments.getSearchScope();
             argParser.addArgument(searchScope);
 
             dereferencePolicy =
-                    new MultiChoiceArgument<>("derefpolicy", 'a',
-                            "dereferencePolicy", false, true, INFO_DEREFERENCE_POLICE_PLACEHOLDER
-                                    .get(), DereferenceAliasesPolicy.values(), false,
-                            INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY.get());
-            dereferencePolicy.setPropertyName("dereferencePolicy");
-            dereferencePolicy.setDefaultValue(DereferenceAliasesPolicy.NEVER);
-            argParser.addArgument(dereferencePolicy);
+                    MultiChoiceArgument.<DereferenceAliasesPolicy>builder("dereferencePolicy")
+                            .shortIdentifier('a')
+                            .description(INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY.get())
+                            .allowedValues(DereferenceAliasesPolicy.values())
+                            .defaultValue(DereferenceAliasesPolicy.NEVER)
+                            .valuePlaceholder(INFO_DEREFERENCE_POLICE_PLACEHOLDER.get())
+                            .buildAndAddToParser(argParser);
 
             verbose = CommonArguments.getVerbose();
             argParser.addArgument(verbose);
 
             scriptFriendly =
-                    new BooleanArgument("scriptFriendly", 'S', "scriptFriendly",
-                            INFO_DESCRIPTION_SCRIPT_FRIENDLY.get());
-            scriptFriendly.setPropertyName("scriptFriendly");
-            argParser.addArgument(scriptFriendly);
+                    BooleanArgument.builder("scriptFriendly")
+                            .shortIdentifier('S')
+                            .description(INFO_DESCRIPTION_SCRIPT_FRIENDLY.get())
+                            .buildAndAddToParser(argParser);
         } catch (final ArgumentException ae) {
             final LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
             errPrintln(message);

--
Gitblit v1.10.0