mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noel Rouvignac
20.03.2015 ad300c48c51bed98ec639e96be3e7d170d28f7a1
Code cleanup:
- Used java 7 diamond operator
- Compressed javadocs to a single line
- Added toString()
- Extracted methods

Argument.java:
In getDoubleValues(), fixed copied/pasted error message.
4 files modified
480 ■■■■■ changed files
opendj-cli/src/main/java/com/forgerock/opendj/cli/Argument.java 83 ●●●●● patch | view | raw | blame | history
opendj-cli/src/main/java/com/forgerock/opendj/cli/MenuBuilder.java 102 ●●●●● patch | view | raw | blame | history
opendj-cli/src/main/java/com/forgerock/opendj/cli/MenuResult.java 12 ●●●●● patch | view | raw | blame | history
opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/CreateSubCommandHandler.java 283 ●●●●● patch | view | raw | blame | history
opendj-cli/src/main/java/com/forgerock/opendj/cli/Argument.java
@@ -41,44 +41,29 @@
 * order to provide specific functionality.
 */
public abstract class Argument implements DocDescriptionSupplement {
    /**
     * Indicates whether this argument should be hidden in the usage
     * information.
     */
    /** 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.
     */
    /** 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.
     */
    /** 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;
    /** 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;
    /** The set of values for this argument. */
    private final LinkedList<String> values;
    /** The default value for the argument if none other is provided. */
    private String defaultValue;
    /** The long identifier for this argument. */
    private final String longIdentifier;
    private final LinkedList<String> values = new LinkedList<>();
    /** The generic name that will be used to refer to this argument. */
    private final String name;
@@ -86,10 +71,7 @@
    /** 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.
     */
    /** The value placeholder for this argument, which will be used in usage information. */
    private LocalizableMessage valuePlaceholder;
    /**
@@ -161,7 +143,6 @@
            throw new ArgumentException(ERR_ARG_NO_VALUE_PLACEHOLDER.get(name));
        }
        values = new LinkedList<String>();
        isPresent = false;
        isHidden = false;
    }
@@ -244,11 +225,13 @@
    private LocalizableMessage docDescriptionSupplement;
    /** {@inheritDoc} */
    @Override
    public LocalizableMessage getDocDescriptionSupplement() {
        return docDescriptionSupplement != null ? docDescriptionSupplement : LocalizableMessage.EMPTY;
    }
    /** {@inheritDoc} */
    @Override
    public void setDocDescriptionSupplement(final LocalizableMessage docDescriptionSupplement) {
        this.docDescriptionSupplement = docDescriptionSupplement;
    }
@@ -288,20 +271,15 @@
     *             If any of the values cannot be parsed as an integer.
     */
    public LinkedList<Double> getDoubleValues() throws ArgumentException {
        final LinkedList<Double> intList = new LinkedList<Double>();
        final Iterator<String> iterator = values.iterator();
        while (iterator.hasNext()) {
            final String valueString = iterator.next();
        final LinkedList<Double> results = new LinkedList<>();
        for (String valueString : values) {
            try {
                intList.add(Double.valueOf(valueString));
                results.add(Double.valueOf(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_DOUBLE.get(valueString, name), e);
            }
        }
        return intList;
        return results;
    }
    /**
@@ -339,20 +317,15 @@
     *             If any of the values cannot be parsed as an integer.
     */
    public LinkedList<Integer> getIntValues() throws ArgumentException {
        final LinkedList<Integer> intList = new LinkedList<Integer>();
        final Iterator<String> iterator = values.iterator();
        while (iterator.hasNext()) {
            final String valueString = iterator.next();
        final LinkedList<Integer> results = new LinkedList<>();
        for (String valueString : values) {
            try {
                intList.add(Integer.valueOf(valueString));
                results.add(Integer.valueOf(valueString));
            } catch (final Exception e) {
                throw new ArgumentException(ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, name), e);
            }
        }
        return intList;
        return results;
    }
    /**
@@ -409,11 +382,7 @@
     *         are no values and no default value has been given.
     */
    public String getValue() {
        if (values.isEmpty()) {
            return defaultValue;
        }
        return values.getFirst();
        return !values.isEmpty() ? values.getFirst() : defaultValue;
    }
    /**
@@ -421,8 +390,7 @@
     * in the generated usage information.
     *
     * @return The value placeholder that will be displayed for this argument in
     *         the generated usage information, or <CODE>null</CODE> if there is
     *         none.
     *         the generated usage information, or <CODE>null</CODE> if there is none.
     */
    public LocalizableMessage getValuePlaceholder() {
        return valuePlaceholder;
@@ -485,8 +453,7 @@
     * Indicates whether this argument is required to have at least one value.
     *
     * @return <CODE>true</CODE> if this argument is required to have at least
     *         one value, or <CODE>false</CODE> if it does not need to have a
     *         value.
     *         one value, or <CODE>false</CODE> if it does not need to have a value.
     */
    public boolean isRequired() {
        return isRequired;
@@ -497,8 +464,7 @@
     * found is a properties file.
     *
     * @return <CODE>true</CODE> if this argument was provided in the set of
     *         properties found is a properties file, or <CODE>false</CODE> if
     *         not.
     *         properties found is a properties file, or <CODE>false</CODE> if not.
     */
    public boolean isValueSetByProperty() {
        return isValueSetByProperty;
@@ -660,6 +626,7 @@
            sb.append("shortID=");
            sb.append(shortIdentifier);
        }
        sb.append(", values=").append(values);
        sb.append(")");
        return sb.toString();
    }
opendj-cli/src/main/java/com/forgerock/opendj/cli/MenuBuilder.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2007-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 *      Portions Copyright 2014-2015 ForgeRock AS
 */
package com.forgerock.opendj.cli;
@@ -73,13 +73,11 @@
            List<T> values = new ArrayList<T>();
            for (MenuCallback<T> callback : callbacks) {
                MenuResult<T> result = callback.invoke(app);
                if (!result.isSuccess()) {
                    // Throw away all the other results.
                    return result;
                } else {
                    values.addAll(result.getValues());
                }
                values.addAll(result.getValues());
            }
            return MenuResult.success(values);
        }
@@ -94,10 +92,7 @@
     */
    private static final class MenuImpl<T> implements Menu<T> {
        /**
         * Indicates whether the menu will allow selection of multiple
         * numeric options.
         */
        /** Indicates whether the menu will allow selection of multiple numeric options. */
        private final boolean allowMultiSelect;
        /** The application console. */
@@ -111,7 +106,6 @@
        /** The call-back for the optional default action. */
        private final MenuCallback<T> defaultCallback;
        /** The description of the optional default action. */
        private final LocalizableMessage defaultDescription;
@@ -258,7 +252,6 @@
                // Get the user's choice.
                MenuCallback<T> choice;
                if (nMaxTries != -1) {
                    choice = app.readValidatedInput(promptMsg, validator, nMaxTries);
                } else {
@@ -268,14 +261,12 @@
                // Invoke the user's selected choice.
                MenuResult<T> result = choice.invoke(app);
                // Determine if the help needs to be displayed, display it and
                // start again.
                // Determine if the help needs to be displayed, display it and start again.
                if (!result.isAgain()) {
                    return result;
                } else {
                    app.println();
                    app.println();
                }
                app.println();
                app.println();
            }
        }
    }
@@ -301,15 +292,16 @@
            return result;
        }
        @Override
        public String toString() {
            return getClass().getSimpleName() + "(result=" + result + ")";
        }
    }
    /** The multiple column display threshold. */
    private int threshold = -1;
    /**
     * Indicates whether the menu will allow selection of multiple
     * numeric options.
     */
    /** Indicates whether the menu will allow selection of multiple numeric options. */
    private boolean allowMultiSelect;
    /** The application console. */
@@ -320,31 +312,26 @@
    /** The char option keys (must be single-character messages). */
    private final List<LocalizableMessage> charKeys = new ArrayList<LocalizableMessage>();
    /** The synopsis of char options. */
    private final List<LocalizableMessage> charSynopsis = new ArrayList<LocalizableMessage>();
    /** Optional column headings. */
    private final List<LocalizableMessage> columnHeadings = new ArrayList<LocalizableMessage>();
    /** Optional column widths. */
    private final List<Integer> columnWidths = new ArrayList<Integer>();
    /** The call-back for the optional default action. */
    private MenuCallback<T> defaultCallback;
    /** The description of the optional default action. */
    private LocalizableMessage defaultDescription;
    /** The numeric option call-backs. */
    private final List<MenuCallback<T>> numericCallbacks = new ArrayList<MenuCallback<T>>();
    /** The numeric option fields. */
    private final List<List<LocalizableMessage>> numericFields = new ArrayList<List<LocalizableMessage>>();
    /** The menu title. */
    private LocalizableMessage title;
    /** The menu prompt. */
    private LocalizableMessage prompt;
@@ -605,24 +592,10 @@
        // Create optional column headers.
        if (!columnHeadings.isEmpty()) {
            nbuilder.appendHeading();
            for (LocalizableMessage heading : columnHeadings) {
                if (heading != null) {
                    nbuilder.appendHeading(heading);
                } else {
                    nbuilder.appendHeading();
                }
            }
            appendHeadings(nbuilder);
            if (useMultipleColumns) {
                nbuilder.appendHeading();
                for (LocalizableMessage heading : columnHeadings) {
                    if (heading != null) {
                        nbuilder.appendHeading(heading);
                    } else {
                        nbuilder.appendHeading();
                    }
                }
                appendHeadings(nbuilder);
            }
        }
@@ -642,29 +615,13 @@
        for (int i = 0, j = rows; i < rows; i++, j++) {
            nbuilder.startRow();
            nbuilder.appendCell(INFO_MENU_NUMERIC_OPTION.get(i + 1));
            for (LocalizableMessage field : numericFields.get(i)) {
                if (field != null) {
                    nbuilder.appendCell(field);
                } else {
                    nbuilder.appendCell();
                }
            }
            appendCells(nbuilder, i);
            callbacks.put(String.valueOf(i + 1), numericCallbacks.get(i));
            // Second column.
            if (useMultipleColumns && j < sz) {
                nbuilder.appendCell(INFO_MENU_NUMERIC_OPTION.get(j + 1));
                for (LocalizableMessage field : numericFields.get(j)) {
                    if (field != null) {
                        nbuilder.appendCell(field);
                    } else {
                        nbuilder.appendCell();
                    }
                }
                appendCells(nbuilder, j);
                callbacks.put(String.valueOf(j + 1), numericCallbacks.get(j));
            }
@@ -686,10 +643,9 @@
        // Configure the table printer.
        TextTablePrinter printer = new TextTablePrinter(app.getErrorStream());
        if (columnHeadings.isEmpty()) {
            printer.setDisplayHeadings(false);
        } else {
            printer.setDisplayHeadings(true);
        boolean hasHeadings = !columnHeadings.isEmpty();
        printer.setDisplayHeadings(hasHeadings);
        if (hasHeadings) {
            printer.setHeadingSeparatorStartColumn(1);
        }
@@ -717,6 +673,28 @@
                defaultCallback, defaultDescription, nMaxTries);
    }
    private void appendCells(TableBuilder nbuilder, int i) {
        nbuilder.appendCell(INFO_MENU_NUMERIC_OPTION.get(i + 1));
        for (LocalizableMessage field : numericFields.get(i)) {
            if (field != null) {
                nbuilder.appendCell(field);
            } else {
                nbuilder.appendCell();
            }
        }
    }
    private void appendHeadings(TableBuilder nbuilder) {
        nbuilder.appendHeading();
        for (LocalizableMessage heading : columnHeadings) {
            if (heading != null) {
                nbuilder.appendHeading(heading);
            } else {
                nbuilder.appendHeading();
            }
        }
    }
    /**
     * Sets the maximum number of tries that the user can provide an invalid value in the menu. -1 for unlimited tries
     * (the default). If this limit is reached a ClientException will be thrown.
opendj-cli/src/main/java/com/forgerock/opendj/cli/MenuResult.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 *      Portions Copyright 2014-2015 ForgeRock AS
 */
package com.forgerock.opendj.cli;
@@ -194,11 +194,10 @@
     * @see #isSuccess()
     */
    public T getValue() {
        if (values.isEmpty()) {
            return null;
        } else {
        if (!values.isEmpty()) {
            return values.iterator().next();
        }
        return null;
    }
    /**
@@ -258,4 +257,9 @@
    public boolean isSuccess() {
        return type == Type.SUCCESS;
    }
    @Override
    public String toString() {
        return getClass().getSimpleName() + "(type=" + type + ", values=" + values + ")";
    }
}
opendj-config/src/main/java/org/forgerock/opendj/config/dsconfig/CreateSubCommandHandler.java
@@ -22,13 +22,13 @@
 *
 *
 *      Copyright 2007-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2013-2014 ForgeRock AS
 *      Portions Copyright 2013-2015 ForgeRock AS
 */
package org.forgerock.opendj.config.dsconfig;
import static com.forgerock.opendj.cli.ArgumentConstants.*;
import static com.forgerock.opendj.cli.CliMessages.*;
import static com.forgerock.opendj.cli.ReturnCode.*;
import static com.forgerock.opendj.cli.ArgumentConstants.LIST_TABLE_SEPARATOR;
import static com.forgerock.opendj.dsconfig.DsconfigMessages.*;
import static org.forgerock.opendj.config.dsconfig.ArgumentExceptionFactory.*;
@@ -82,6 +82,7 @@
import com.forgerock.opendj.cli.Argument;
import com.forgerock.opendj.cli.ArgumentException;
import com.forgerock.opendj.cli.ClientException;
import com.forgerock.opendj.cli.CommandBuilder;
import com.forgerock.opendj.cli.ConsoleApplication;
import com.forgerock.opendj.cli.HelpCallback;
import com.forgerock.opendj.cli.MenuBuilder;
@@ -112,8 +113,7 @@
    private static class MyPropertyProvider implements PropertyProvider {
        /** Decoded set of properties. */
        private final Map<PropertyDefinition<?>, Collection<?>> properties
            = new HashMap<PropertyDefinition<?>, Collection<?>>();
        private final Map<PropertyDefinition<?>, Collection<?>> properties = new HashMap<>();
        /**
         * Create a new property provider using the provided set of property value arguments.
@@ -155,8 +155,7 @@
                    throw ArgumentExceptionFactory.unknownProperty(d, propertyName);
                }
                // Make sure that the user is not attempting to set the naming
                // property.
                // Make sure that the user is not attempting to set the naming property.
                if (pd.equals(namingPropertyDefinition)) {
                    throw ArgumentExceptionFactory.unableToSetNamingProperty(d, pd);
                }
@@ -176,6 +175,7 @@
        }
        /** {@inheritDoc} */
        @Override
        @SuppressWarnings("unchecked")
        public <T> Collection<T> getPropertyValues(PropertyDefinition<T> d) {
            Collection<T> values = (Collection<T>) properties.get(d);
@@ -198,7 +198,7 @@
            Collection<T> values = (Collection<T>) properties.get(pd);
            if (values == null) {
                values = new LinkedList<T>();
                values = new LinkedList<>();
            }
            values.add(value);
@@ -226,6 +226,7 @@
        }
        /** {@inheritDoc} */
        @Override
        public void display(ConsoleApplication app) {
            app.println(INFO_DSCFG_CREATE_TYPE_HELP_HEADING.get(d.getUserFriendlyPluralName()));
@@ -251,16 +252,12 @@
            boolean isFirst = true;
            for (ManagedObjectDefinition<?, ?> mod : getSubTypes(d).values()) {
                // Only display advanced types and custom types in advanced mode.
                if (!app.isAdvancedMode()) {
                    if (mod.hasOption(ManagedObjectOption.ADVANCED)) {
                if (!app.isAdvancedMode()
                        && (mod.hasOption(ManagedObjectOption.ADVANCED)
                                || CLIProfile.getInstance().isForCustomization(mod))) {
                        continue;
                    }
                    if (CLIProfile.getInstance().isForCustomization(mod)) {
                        continue;
                    }
                }
                LocalizableMessage ufn = mod.getUserFriendlyName();
                LocalizableMessage synopsis = mod.getSynopsis();
                LocalizableMessage description = mod.getDescription();
@@ -301,34 +298,17 @@
        }
    }
    /**
     * The value for the long option set.
     */
    /** The value for the long option set. */
    private static final String OPTION_DSCFG_LONG_SET = "set";
    /**
     * The value for the long option type.
     */
    /** The value for the long option type. */
    private static final String OPTION_DSCFG_LONG_TYPE = "type";
    /**
     * The value for the short option property.
     */
    /** The value for the short option property. */
    private static final Character OPTION_DSCFG_SHORT_SET = null;
    /**
     * The value for the short option type.
     */
    /** The value for the short option type. */
    private static final Character OPTION_DSCFG_SHORT_TYPE = 't';
    /**
     * The value for the long option remove (this is used only internally).
     */
    /** The value for the long option remove (this is used only internally). */
    private static final String OPTION_DSCFG_LONG_REMOVE = "remove";
    /**
     * The value for the long option reset (this is used only internally).
     */
    /** The value for the long option reset (this is used only internally). */
    private static final String OPTION_DSCFG_LONG_RESET = "reset";
    /**
@@ -351,7 +331,7 @@
    public static <C extends ConfigurationClient, S extends Configuration> CreateSubCommandHandler<C, S> create(
            SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<C, S> r)
            throws ArgumentException {
        return new CreateSubCommandHandler<C, S>(parser, p, r, r.getNamingPropertyDefinition(), p.child(r, "DUMMY"));
        return new CreateSubCommandHandler<>(parser, p, r, r.getNamingPropertyDefinition(), p.child(r, "DUMMY"));
    }
    /**
@@ -374,7 +354,7 @@
    public static <C extends ConfigurationClient, S extends Configuration> CreateSubCommandHandler<C, S> create(
            SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p, SetRelationDefinition<C, S> r)
            throws ArgumentException {
        return new CreateSubCommandHandler<C, S>(parser, p, r, null, p.child(r));
        return new CreateSubCommandHandler<>(parser, p, r, null, p.child(r));
    }
    /**
@@ -397,7 +377,7 @@
    public static <C extends ConfigurationClient, S extends Configuration> CreateSubCommandHandler<C, S> create(
            SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p, OptionalRelationDefinition<C, S> r)
            throws ArgumentException {
        return new CreateSubCommandHandler<C, S>(parser, p, r, null, p.child(r));
        return new CreateSubCommandHandler<>(parser, p, r, null, p.child(r));
    }
    /**
@@ -471,10 +451,10 @@
        }
        // Now create the component.
        app.println();
        app.println();
        // FIXME: handle default value exceptions?
        List<PropertyException> exceptions = new LinkedList<PropertyException>();
        app.println();
        app.println();
        List<PropertyException> exceptions = new LinkedList<>();
        ManagedObject<? extends C> mo = createChildInteractively(app, parent, rd, mod, exceptions);
        // Let the user interactively configure the managed object and commit it.
@@ -634,12 +614,10 @@
        while (true) {
            // Interactively set properties if applicable.
            if (app.isInteractive()) {
                SortedSet<PropertyDefinition<?>> properties = new TreeSet<PropertyDefinition<?>>();
                SortedSet<PropertyDefinition<?>> properties = new TreeSet<>();
                for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
                    if (pd.hasOption(PropertyOption.HIDDEN)) {
                        continue;
                    }
                    if (!app.isAdvancedMode() && pd.hasOption(PropertyOption.ADVANCED)) {
                    if (pd.hasOption(PropertyOption.HIDDEN)
                            || (!app.isAdvancedMode() && pd.hasOption(PropertyOption.ADVANCED))) {
                        continue;
                    }
                    properties.add(pd);
@@ -692,18 +670,16 @@
                }
                return MenuResult.success();
            } catch (MissingMandatoryPropertiesException e) {
                if (app.isInteractive()) {
                    // If interactive, give the user the chance to fix the
                    // problems.
                if (!app.isInteractive()) {
                    throw new ClientException(ReturnCode.CONSTRAINT_VIOLATION, e.getMessageObject(), e);
                }
                // If interactive, give the user the chance to fix the problems.
                    app.errPrintln();
                    displayMissingMandatoryPropertyException(app, e);
                    app.errPrintln();
                    if (!app.confirmAction(INFO_DSCFG_PROMPT_EDIT_AGAIN.get(ufn), true)) {
                        return MenuResult.cancel();
                    }
                } else {
                    throw new ClientException(ReturnCode.CONSTRAINT_VIOLATION, e.getMessageObject(), e);
                }
            } catch (AuthorizationException e) {
                LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_AUTHZ.get(ufn);
                throw new ClientException(ReturnCode.INSUFFICIENT_ACCESS_RIGHTS, msg);
@@ -711,7 +687,9 @@
                LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_CME.get(ufn);
                throw new ClientException(ReturnCode.CONSTRAINT_VIOLATION, msg);
            } catch (OperationRejectedException e) {
                if (app.isInteractive()) {
                if (!app.isInteractive()) {
                    throw new ClientException(ReturnCode.CONSTRAINT_VIOLATION, e.getMessageObject(), e);
                }
                    // If interactive, give the user the chance to fix the problems.
                    app.errPrintln();
                    displayOperationRejectedException(app, e);
@@ -719,9 +697,6 @@
                    if (!app.confirmAction(INFO_DSCFG_PROMPT_EDIT_AGAIN.get(ufn), true)) {
                        return MenuResult.cancel();
                    }
                } else {
                    throw new ClientException(ReturnCode.CONSTRAINT_VIOLATION, e.getMessageObject(), e);
                }
            } catch (LdapException e) {
                LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_CE.get(ufn, e.getMessage());
                return interactivePrintOrThrowError(app, msg, CLIENT_SIDE_SERVER_DOWN);
@@ -743,6 +718,7 @@
        ValidationCallback<ManagedObject<? extends C>> validator
            = new ValidationCallback<ManagedObject<? extends C>>() {
                @Override
                public ManagedObject<? extends C> validate(ConsoleApplication app, String input)
                        throws ClientException {
                    ManagedObject<? extends C> child;
@@ -833,7 +809,7 @@
            throws ClientException {
        // First get the list of available of sub-types.
        List<ManagedObjectDefinition<? extends C, ? extends S>> filteredTypes
            = new LinkedList<ManagedObjectDefinition<? extends C, ? extends S>>(getSubTypes(d).values());
            = new LinkedList<>(getSubTypes(d).values());
        boolean isOnlyOneType = filteredTypes.size() == 1;
        Iterator<ManagedObjectDefinition<? extends C, ? extends S>> i;
@@ -860,8 +836,7 @@
        } else if (filteredTypes.size() == 1) {
            ManagedObjectDefinition<? extends C, ? extends S> type = filteredTypes.iterator().next();
            if (!isOnlyOneType) {
                // Only one option available so confirm that the user wishes to
                // use it.
                // Only one option available so confirm that the user wishes to use it.
                LocalizableMessage msg = INFO_DSCFG_TYPE_PROMPT_SINGLE.get(d.getUserFriendlyName(),
                        type.getUserFriendlyName());
                if (!app.confirmAction(msg, true)) {
@@ -870,8 +845,7 @@
            }
            return MenuResult.<ManagedObjectDefinition<? extends C, ? extends S>> success(type);
        } else {
            MenuBuilder<ManagedObjectDefinition<? extends C, ? extends S>> builder
                = new MenuBuilder<ManagedObjectDefinition<? extends C, ? extends S>>(app);
            MenuBuilder<ManagedObjectDefinition<? extends C, ? extends S>> builder = new MenuBuilder<>(app);
            LocalizableMessage msg = INFO_DSCFG_CREATE_TYPE_PROMPT.get(d.getUserFriendlyName());
            builder.setMultipleColumnThreshold(MULTI_COLUMN_THRESHOLD);
            builder.setPrompt(msg);
@@ -905,9 +879,7 @@
    /** The path of the parent managed object. */
    private final ManagedObjectPath<?, ?> path;
    /**
     * The argument which should be used to specify zero or more property values.
     */
    /** The argument which should be used to specify zero or more property values. */
    private final StringArgument propertySetArgument;
    /** The relation which should be used for creating children. */
@@ -916,19 +888,14 @@
    /** The sub-command associated with this handler. */
    private final SubCommand subCommand;
    /**
     * The argument which should be used to specify the type of managed object to be created.
     */
    /** The argument which should be used to specify the type of managed object to be created. */
    private final StringArgument typeArgument;
    /**
     * The set of instantiable managed object definitions and their associated type option value.
     */
    private final SortedMap<String, ManagedObjectDefinition<? extends C, ? extends S>> types;
    /** The syntax of the type argument. */
    private final String typeUsage;
    /** The set of instantiable managed object definitions and their associated type option value. */
    private final SortedMap<String, ManagedObjectDefinition<? extends C, ? extends S>> types;
    /** Common constructor. */
    private CreateSubCommandHandler(SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
            RelationDefinition<C, S> r, PropertyDefinition<?> pd, ManagedObjectPath<?, ?> c) throws ArgumentException {
@@ -1002,7 +969,7 @@
    @Override
    public MenuResult<Integer> run(ConsoleApplication app, LDAPManagementContextFactory factory)
            throws ArgumentException, ClientException {
        LocalizableMessage ufn = relation.getUserFriendlyName();
        final LocalizableMessage rufn = relation.getUserFriendlyName();
        // Get the naming argument values.
        List<String> names = getNamingArgValues(app, namingArgs);
@@ -1020,7 +987,7 @@
        try {
            result = getManagedObject(app, context, path, names);
        } catch (AuthorizationException e) {
            LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_AUTHZ.get(ufn);
            LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_AUTHZ.get(rufn);
            throw new ClientException(ReturnCode.INSUFFICIENT_ACCESS_RIGHTS, msg);
        } catch (DefinitionDecodingException e) {
            LocalizableMessage pufn = path.getManagedObjectDefinition().getUserFriendlyName();
@@ -1031,7 +998,7 @@
            LocalizableMessage msg = ERR_DSCFG_ERROR_GET_PARENT_MODE.get(pufn);
            throw new ClientException(ReturnCode.OTHER, msg, e);
        } catch (ConcurrentModificationException e) {
            LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_CME.get(ufn);
            LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_CME.get(rufn);
            throw new ClientException(ReturnCode.CONSTRAINT_VIOLATION, msg);
        } catch (ManagedObjectNotFoundException e) {
            LocalizableMessage pufn = path.getManagedObjectDefinition().getUserFriendlyName();
@@ -1045,7 +1012,7 @@
            if (!app.isMenuDrivenMode()) {
                // User chose to cancel creation.
                app.println();
                app.println(INFO_DSCFG_CONFIRM_CREATE_FAIL.get(ufn));
                app.println(INFO_DSCFG_CONFIRM_CREATE_FAIL.get(rufn));
            }
            return MenuResult.quit();
        } else if (result.isCancel()) {
@@ -1061,19 +1028,19 @@
        Set<String> prohibitedTypes;
        if (relation instanceof SetRelationDefinition) {
            SetRelationDefinition<C, S> sr = (SetRelationDefinition<C, S>) relation;
            prohibitedTypes = new HashSet<String>();
            prohibitedTypes = new HashSet<>();
            try {
                for (String child : parent.listChildren(sr)) {
                    prohibitedTypes.add(child);
                }
            } catch (AuthorizationException e) {
                LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_AUTHZ.get(ufn);
                LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_AUTHZ.get(rufn);
                throw new ClientException(ReturnCode.INSUFFICIENT_ACCESS_RIGHTS, msg);
            } catch (ConcurrentModificationException e) {
                LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_CME.get(ufn);
                LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_CME.get(rufn);
                throw new ClientException(ReturnCode.CONSTRAINT_VIOLATION, msg);
            } catch (LdapException e) {
                LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_CE.get(ufn, e.getMessage());
                LocalizableMessage msg = ERR_DSCFG_ERROR_CREATE_CE.get(rufn, e.getMessage());
                throw new ClientException(ReturnCode.CLIENT_SIDE_SERVER_DOWN, msg);
            }
        } else {
@@ -1098,7 +1065,7 @@
                    // Must be quit.
                    if (!app.isMenuDrivenMode()) {
                        app.println();
                        app.println(INFO_DSCFG_CONFIRM_CREATE_FAIL.get(ufn));
                        app.println(INFO_DSCFG_CONFIRM_CREATE_FAIL.get(rufn));
                    }
                    return MenuResult.quit();
                }
@@ -1119,7 +1086,7 @@
        MyPropertyProvider provider = new MyPropertyProvider(d, namingPropertyDefinition, propertyArgs);
        ManagedObject<? extends C> child;
        List<PropertyException> exceptions = new LinkedList<PropertyException>();
        List<PropertyException> exceptions = new LinkedList<>();
        boolean isNameProvidedInteractively = false;
        String providedNamingArgName = null;
        if (relation instanceof InstantiableRelationDefinition) {
@@ -1151,8 +1118,7 @@
            child = parent.createChild(orelation, d, exceptions);
        }
        // FIXME: display any default behavior exceptions in verbose
        // mode.
        // FIXME: display any default behavior exceptions in verbose mode.
        // Set any properties specified on the command line.
        for (PropertyDefinition<?> pd : provider.getProperties()) {
@@ -1160,23 +1126,31 @@
        }
        // Now the command line changes have been made, create the managed
        // object interacting with the user to fix any problems if
        // required.
        // object interacting with the user to fix any problems if required.
        MenuResult<Void> result2 = commitManagedObject(app, context, child, this);
        if (result2.isCancel()) {
            return MenuResult.cancel();
        } else if (result2.isQuit()) {
            return MenuResult.quit();
        } else {
            addArgumentsToCommandBuilder(d, child, isNameProvidedInteractively, providedNamingArgName);
            return MenuResult.success(0);
        }
    }
    private void addArgumentsToCommandBuilder(ManagedObjectDefinition<? extends C, ? extends S> d,
            ManagedObject<? extends C> child, boolean isNameProvidedInteractively, String providedNamingArgName)
            throws ArgumentException {
        CommandBuilder commandBuilder = getCommandBuilder();
            if (typeArgument.hasValue()) {
                getCommandBuilder().addArgument(typeArgument);
            commandBuilder.addArgument(typeArgument);
            } else {
                // Set the type provided by the user
                StringArgument arg = new StringArgument(typeArgument.getName(), OPTION_DSCFG_SHORT_TYPE,
                        OPTION_DSCFG_LONG_TYPE, false, false, true, INFO_TYPE_PLACEHOLDER.get(),
                        typeArgument.getDefaultValue(), typeArgument.getPropertyName(), typeArgument.getDescription());
                arg.addValue(getTypeName(d));
                getCommandBuilder().addArgument(arg);
            commandBuilder.addArgument(arg);
            }
            if (propertySetArgument.hasValue()) {
                /*
@@ -1187,54 +1161,22 @@
                        OPTION_DSCFG_LONG_SET, false, true, true, INFO_VALUE_SET_PLACEHOLDER.get(), null, null,
                        INFO_DSCFG_DESCRIPTION_PROP_VAL.get());
                for (String value : propertySetArgument.getValues()) {
                    boolean addValue = true;
                    int index = value.indexOf(':');
                    if (index != -1) {
                        String propName = value.substring(0, index);
                        for (Argument arg : getCommandBuilder().getArguments()) {
                            for (String value2 : arg.getValues()) {
                                String prop2Name;
                                if (OPTION_DSCFG_LONG_SET.equals(arg.getName())
                                        || OPTION_DSCFG_LONG_REMOVE.equals(arg.getName())) {
                                    int index2 = value2.indexOf(':');
                                    if (index2 != -1) {
                                        prop2Name = value2.substring(0, index2);
                                    } else {
                                        prop2Name = null;
                                    }
                                } else if (OPTION_DSCFG_LONG_RESET.equals(arg.getName())) {
                                    prop2Name = value2;
                                } else {
                                    prop2Name = null;
                                }
                                if (prop2Name != null && prop2Name.equalsIgnoreCase(propName)) {
                                    addValue = false;
                                    break;
                                }
                            }
                            if (!addValue) {
                                break;
                            }
                        }
                    } else {
                        addValue = false;
                    }
                    if (addValue) {
                if (canAddValue(commandBuilder, value)) {
                        filteredArg.addValue(value);
                    }
                }
                if (filteredArg.hasValue()) {
                    getCommandBuilder().addArgument(filteredArg);
                commandBuilder.addArgument(filteredArg);
                }
            }
            /* Filter the arguments that are used internally */
            List<Argument> argsCopy = new LinkedList<Argument>(getCommandBuilder().getArguments());
        List<Argument> argsCopy = new LinkedList<>(commandBuilder.getArguments());
            for (Argument arg : argsCopy) {
                if (arg != null
                        && (OPTION_DSCFG_LONG_RESET.equals(arg.getName()) || OPTION_DSCFG_LONG_REMOVE.equals(arg
                                .getName()))) {
                    getCommandBuilder().removeArgument(arg);
                    && (OPTION_DSCFG_LONG_RESET.equals(arg.getName())
                            || OPTION_DSCFG_LONG_REMOVE.equals(arg.getName()))) {
                commandBuilder.removeArgument(arg);
                }
            }
@@ -1243,25 +1185,50 @@
                        true, INFO_NAME_PLACEHOLDER.get(), INFO_DSCFG_DESCRIPTION_NAME_CREATE.get(d
                                .getUserFriendlyName()));
                arg.addValue(child.getManagedObjectPath().getName());
                getCommandBuilder().addArgument(arg);
            commandBuilder.addArgument(arg);
            } else {
                for (StringArgument arg : namingArgs) {
                    if (arg.isPresent()) {
                        getCommandBuilder().addArgument(arg);
                    commandBuilder.addArgument(arg);
                    }
                }
            }
            return MenuResult.success(0);
        }
    private boolean canAddValue(CommandBuilder commandBuilder, String value) {
        final int index = value.indexOf(':');
        if (index == -1) {
            return false;
        }
        String propName = value.substring(0, index);
        for (Argument arg : commandBuilder.getArguments()) {
            for (String value2 : arg.getValues()) {
                String prop2Name = getPropName(arg.getName(), value2);
                if (propName.equalsIgnoreCase(prop2Name)) {
                    return false;
                }
            }
        }
        return true;
    }
    private String getPropName(String argName, String value) {
        if (OPTION_DSCFG_LONG_SET.equals(argName)
                || OPTION_DSCFG_LONG_REMOVE.equals(argName)) {
            final int index = value.indexOf(':');
            if (index != -1) {
                return value.substring(0, index);
            }
        } else if (OPTION_DSCFG_LONG_RESET.equals(argName)) {
            return value;
        }
        return null;
    }
    /** Set a property's initial values. */
    private <T> void setProperty(ManagedObject<?> mo, MyPropertyProvider provider, PropertyDefinition<T> pd) {
        Collection<T> values = provider.getPropertyValues(pd);
        // This cannot fail because the property values have already been
        // validated.
        mo.setPropertyValues(pd, values);
        // This cannot fail because the property values have already been validated.
        mo.setPropertyValues(pd, provider.getPropertyValues(pd));
    }
    /**
@@ -1277,42 +1244,36 @@
    private static <T> Argument createArgument(PropertyEditorModification<T> mod) throws ArgumentException {
        StringArgument arg;
        PropertyDefinition<T> propertyDefinition = mod.getPropertyDefinition();
        String propName = propertyDefinition.getName();
        switch (mod.getType()) {
        case ADD:
            arg = new StringArgument(OPTION_DSCFG_LONG_SET, OPTION_DSCFG_SHORT_SET, OPTION_DSCFG_LONG_SET, false, true,
                    true, INFO_VALUE_SET_PLACEHOLDER.get(), null, null, INFO_DSCFG_DESCRIPTION_PROP_VAL.get());
            for (T value : mod.getModificationValues()) {
                arg.addValue(propName + ':' + getArgumentValue(propertyDefinition, value));
            }
            break;
        case SET:
            arg = new StringArgument(OPTION_DSCFG_LONG_SET, OPTION_DSCFG_SHORT_SET, OPTION_DSCFG_LONG_SET, false, true,
                    true, INFO_VALUE_SET_PLACEHOLDER.get(), null, null, INFO_DSCFG_DESCRIPTION_PROP_VAL.get());
            for (T value : mod.getModificationValues()) {
                arg.addValue(propName + ':' + getArgumentValue(propertyDefinition, value));
            }
            break;
            addValues(mod, arg);
            return arg;
        case RESET:
            arg = new StringArgument(OPTION_DSCFG_LONG_RESET, null, OPTION_DSCFG_LONG_RESET, false, true, true,
                    INFO_PROPERTY_PLACEHOLDER.get(), null, null, INFO_DSCFG_DESCRIPTION_RESET_PROP.get());
            arg.addValue(propName);
            break;
            arg.addValue(mod.getPropertyDefinition().getName());
            return arg;
        case REMOVE:
            arg = new StringArgument(OPTION_DSCFG_LONG_REMOVE, null, OPTION_DSCFG_LONG_REMOVE, false, true, true,
                    INFO_VALUE_SET_PLACEHOLDER.get(), null, null, INFO_DSCFG_DESCRIPTION_REMOVE_PROP_VAL.get());
            for (T value : mod.getModificationValues()) {
                arg.addValue(propName + ':' + getArgumentValue(propertyDefinition, value));
            }
            arg = null;
            break;
            addValues(mod, arg);
            return arg;
        default:
            // Bug
            throw new IllegalStateException("Unknown modification type: " + mod.getType());
        }
        return arg;
    }
    private static <T> void addValues(PropertyEditorModification<T> mod, StringArgument arg) {
        PropertyDefinition<T> propertyDefinition = mod.getPropertyDefinition();
        String propName = propertyDefinition.getName();
        for (T value : mod.getModificationValues()) {
            arg.addValue(propName + ':' + getArgumentValue(propertyDefinition, value));
        }
    }
    /**
@@ -1323,14 +1284,12 @@
     * @return the type name for the provided ManagedObjectDefinition.
     */
    private String getTypeName(ManagedObjectDefinition<? extends C, ? extends S> d) {
        String name = d.getName();
        for (String key : types.keySet()) {
            ManagedObjectDefinition<? extends C, ? extends S> current = types.get(key);
            if (current.equals(d)) {
                name = key;
                break;
                return key;
            }
        }
        return name;
        return d.getName();
    }
}