timoninmaxim commented on code in PR #10581:
URL: https://github.com/apache/ignite/pull/10581#discussion_r1175199941


##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.

Review Comment:
   s/represents/represent/



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ * @param <T> Compute task type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R, T extends 
ComputeTask<VisorTaskArgument<A>, R>> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<A> args();
+
+    /** @return Task class. */
+    public Class<T> task();
+
+    /**
+     * Prints command result to the user.
+     * @param arg Argument.
+     * @param res Result.
+     * @param printer Implementation specific printer.
+     */
+    public default void printResult(A arg, R res, Consumer<String> printer) {
+        // No-op.
+    }
+
+    /** @return {@code true} if the command is experimental, {@code false} 
otherwise. */
+    default boolean experimental() {

Review Comment:
   All methods in interfaces must be declared as `public`. 



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.

Review Comment:
   s/usesull/usefull/



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ * @param <T> Compute task type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R, T extends 
ComputeTask<VisorTaskArgument<A>, R>> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<A> args();
+
+    /** @return Task class. */
+    public Class<T> task();
+
+    /**
+     * Prints command result to the user.
+     * @param arg Argument.
+     * @param res Result.
+     * @param printer Implementation specific printer.
+     */
+    public default void printResult(A arg, R res, Consumer<String> printer) {
+        // No-op.
+    }
+
+    /** @return {@code true} if the command is experimental, {@code false} 
otherwise. */
+    default boolean experimental() {
+        return false;
+    }
+
+    /**
+     * @return {@code true} if the command must be explicitly confirmed, 
{@code false} otherwise.
+     */
+    default boolean confirmable() {
+        return false;
+    }
+
+    /**
+     * @param nodes Live nodes.
+     * @param arg Argument.
+     * @return nodes to execute command on, empty collection means default 
node must be used.
+     */
+    default Collection<UUID> nodes(Collection<UUID> nodes, A arg) {
+        return Collections.emptyList();

Review Comment:
   `return nodes;` ?



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *

Review Comment:
   You should use tags like `<p>` to define paragraphs and/or new lines in 
javadocs. Otherwise it's represented as single line. You can check how it looks 
like with:
   <img width="970" alt="Снимок экрана 2023-04-24 в 15 20 07" 
src="https://user-images.githubusercontent.com/5667421/233994685-8e0c74df-c3bb-4611-b226-55faeb2d8a92.png";>
   



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/AbstractCommand.java:
##########
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/** Basic command implementation. */
+public abstract class AbstractCommand<A extends IgniteDataTransferObject, R, T
+    extends ComputeTask<VisorTaskArgument<A>, R>> implements Command<A, R, T> {
+

Review Comment:
   There should not be an empty line. Let's move the curly brace here.



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Argument.java:
##########
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Fields marked with this annotation is command arguments.
+ * @see Command
+ * @see CommandsRegistry
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Argument {
+    /** @return {@code True} if argument optional, {@code false} if required. 
*/
+    public boolean optional() default false;
+
+    /** @return Argument description. */
+    public String description() default "";
+
+    /** @return Command example. If empty string returned then example will be 
generated automatically. */

Review Comment:
   Command example -> Argument example?



##########
modules/core/src/main/java/org/apache/ignite/internal/util/lang/PeekableIterator.java:
##########
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.util.lang;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Iterator extension that adds {@link #peek()} method to get element without 
moving to the next.
+ */
+public class PeekableIterator<T1> implements Iterator<T1> {
+    /** Underlying iterator. */
+    private final Iterator<T1> iter;
+
+    /** Peeked element. */
+    private T1 peeked;
+
+    /**
+     * @param iter Underlying iterator.
+     */
+    public PeekableIterator(Iterator<T1> iter) {
+        this.iter = iter;
+    }
+
+    /**
+     * Peek and return the next element in the iteration.
+     *
+     * @return the next element in the iteration.
+     * @throws NoSuchElementException if the iteration has no more elements.
+     */
+    public T1 peek() {
+        if (peeked == null && iter.hasNext())

Review Comment:
   I'm not sure we should invoke `next()` in the `peek()` method. It looks 
strange:
   ```
   List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));        
   PeekableIterator<String> iter = new PeekableIterator<>(list.iterator());
   
   assertEquals("a", iter.peek());
   assertEquals("a", iter.next());
   ```
   
   IMHO, `peek()` should throw if no `next()` is invoked before. WDYT?



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<? extends A> args();
+
+    /** @return Task class. */
+    public Class<? extends ComputeTask<VisorTaskArgument<A>, R>> task();

Review Comment:
   taskClass()?



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ * @param <T> Compute task type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R, T extends 
ComputeTask<VisorTaskArgument<A>, R>> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<A> args();
+
+    /** @return Task class. */
+    public Class<T> task();
+
+    /**
+     * Prints command result to the user.
+     * @param arg Argument.
+     * @param res Result.
+     * @param printer Implementation specific printer.
+     */
+    public default void printResult(A arg, R res, Consumer<String> printer) {
+        // No-op.
+    }
+
+    /** @return {@code true} if the command is experimental, {@code false} 
otherwise. */
+    default boolean experimental() {
+        return false;
+    }
+
+    /**
+     * @return {@code true} if the command must be explicitly confirmed, 
{@code false} otherwise.
+     */
+    default boolean confirmable() {

Review Comment:
   needConfirm?



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/CommandUtils.java:
##########
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.UUID;
+import java.util.function.Supplier;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.lang.IgniteUuid;
+import static 
org.apache.ignite.internal.management.api.AbstractCommand.CMD_NAME_POSTFIX;
+
+/**
+ * Utility class for management commands.
+ */
+public class CommandUtils {
+    /** CLI named parameter prefix. */
+    public static final String PARAMETER_PREFIX = "--";
+
+    /** Delimeter for words in parameter and command names. */
+    public static final char CMD_WORDS_DELIM = '-';
+
+    /** Delimeter for words in positional parameters and parameter examples. */
+    public static final char PARAM_WORDS_DELIM = '_';
+
+    /** Indent for help output. */
+    public static final String INDENT = "  ";
+
+    /** Double indent for help output. */
+    public static final String DOUBLE_INDENT = INDENT + INDENT;
+
+    /**
+     * Example: {@code "SystemView" -> "system-view"}.
+     *
+     * @param cls Command name class.
+     * @param delim Words delimeter.
+     * @return Formatted command name.
+     */
+    public static String toFormattedCommandName(Class<?> cls, char delim) {
+        String name = cls.getSimpleName();
+
+        assert name.endsWith(CMD_NAME_POSTFIX);
+
+        return toFormattedName(name.substring(0, name.length() - 
CMD_NAME_POSTFIX.length()), delim);
+    }
+
+    /**
+     * @param fld Field.
+     * @return Formatted name of parameter for this field.
+     */
+    public static String toFormattedFieldName(Field fld) {
+        return PARAMETER_PREFIX + toFormattedFieldName(fld, CMD_WORDS_DELIM);
+    }
+
+    /**
+     * @param name Field, command name.
+     * @param delim Words delimeter.
+     * @return Formatted name.
+     */
+    public static String toFormattedName(String name, char delim) {
+        StringBuilder formatted = new StringBuilder();
+
+        formatted.append(Character.toLowerCase(name.charAt(0)));
+
+        int i = 1;
+
+        while (i < name.length()) {
+            if (Character.isLowerCase(name.charAt(i))) {
+                formatted.append(name.charAt(i));
+
+                i++;
+            }
+            else {
+                formatted.append(delim);
+                formatted.append(Character.toLowerCase(name.charAt(i)));
+                i++;
+            }
+        }
+
+        return formatted.toString();
+    }
+
+    /**
+     * Example: {@code "system-view" -> "SystemView"}.
+     *
+     * @param formatted Formatted command name.
+     * @param delim Words delimeter.
+     * @return Source command name.
+     */
+    public static String fromFormattedCommandName(String formatted, char 
delim) {
+        StringBuilder name = new StringBuilder();
+
+        name.append(Character.toUpperCase(formatted.charAt(0)));
+
+        int i = 1;
+
+        while (i < formatted.length()) {
+            if (formatted.charAt(i) != delim) {
+                name.append(formatted.charAt(i));
+
+                i++;
+            }
+            else {
+                i++;
+                name.append(Character.toUpperCase(formatted.charAt(i)));
+                i++;

Review Comment:
   Here and below, code duplication, `i++` can be out of if-else block.



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<? extends A> args();
+
+    /** @return Task class. */
+    public Class<? extends ComputeTask<VisorTaskArgument<A>, R>> task();
+
+    /**
+     * Prints command result to the user.
+     * @param arg Argument.
+     * @param res Result.
+     * @param printer Implementation specific printer.
+     */
+    public default void printResult(A arg, R res, Consumer<String> printer) {
+        // No-op.
+    }
+
+    /** @return {@code true} if the command is experimental, {@code false} 
otherwise. */
+    public default boolean experimental() {
+        return false;
+    }
+
+    /**
+     * @return Message text to show user for. If null it means that 
confirmantion is not needed.
+     */
+    public default String confirmationPrompt() {
+        return null;
+    }
+
+    /**
+     * @param nodes Live nodes.
+     * @param arg Argument.
+     * @return nodes to execute command on, {@code null} means default node 
must be used.
+     */
+    public default Collection<UUID> nodes(Collection<UUID> nodes, A arg) {

Review Comment:
   `@Nullable`



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<? extends A> args();
+
+    /** @return Task class. */
+    public Class<? extends ComputeTask<VisorTaskArgument<A>, R>> task();
+
+    /**
+     * Prints command result to the user.
+     * @param arg Argument.
+     * @param res Result.
+     * @param printer Implementation specific printer.
+     */
+    public default void printResult(A arg, R res, Consumer<String> printer) {
+        // No-op.
+    }
+
+    /** @return {@code true} if the command is experimental, {@code false} 
otherwise. */
+    public default boolean experimental() {
+        return false;
+    }
+
+    /**
+     * @return Message text to show user for. If null it means that 
confirmantion is not needed.
+     */
+    public default String confirmationPrompt() {
+        return null;
+    }
+
+    /**
+     * @param nodes Live nodes.
+     * @param arg Argument.
+     * @return nodes to execute command on, {@code null} means default node 
must be used.

Review Comment:
   default -> balanced?



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<? extends A> args();
+
+    /** @return Task class. */
+    public Class<? extends ComputeTask<VisorTaskArgument<A>, R>> task();
+
+    /**
+     * Prints command result to the user.
+     * @param arg Argument.
+     * @param res Result.
+     * @param printer Implementation specific printer.
+     */
+    public default void printResult(A arg, R res, Consumer<String> printer) {
+        // No-op.
+    }
+
+    /** @return {@code true} if the command is experimental, {@code false} 
otherwise. */
+    public default boolean experimental() {
+        return false;
+    }
+
+    /**
+     * @return Message text to show user for. If null it means that 
confirmantion is not needed.

Review Comment:
   code -> {@code null}



##########
modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/CommonArgParser.java:
##########
@@ -246,6 +246,9 @@ ConnectionAndSslParameters 
parseAndValidate(Iterator<String> rawArgIter) {
 
                 cmd.parseArguments(argIter);
 
+                autoConfirmation |=

Review Comment:
   Should we add a TODO for removing following lines?
   
   ```
                       case CMD_AUTO_CONFIRMATION:
                           autoConfirmation = true;
   
                           break;
   ```



##########
modules/core/src/main/java/org/apache/ignite/internal/management/jmx/JmxCommandsRegistryInvokerPlugin.java:
##########
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.jmx;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.management.api.Command;
+import org.apache.ignite.internal.management.api.ComplexCommand;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.plugin.IgnitePlugin;
+import org.apache.ignite.plugin.PluginContext;
+import static org.apache.ignite.internal.util.IgniteUtils.makeMBeanName;
+
+/**
+ * Plugin registers each {@link Command} from {@link 
org.apache.ignite.internal.management.IgniteCommandRegistry}
+ * as JMX bean ({@link CommandMBean} which allow to execute management 
commands via JMX.

Review Comment:
   allow to execute (give permissions) -> allow executing (make available).



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/ComplexCommand.java:
##########
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+
+/**
+ * Command that have subcommands. Combine {@link Command} and {@link 
CommandsRegistry} features.
+ * Subcommand name must start with the base command name like:
+ * <ul>
+ *     <li>Base command: {@code StateCommand}.</li>
+ *     <li>Subcommand: {@code StateSetCommand}, {@code StateGetCommand}, 
etc.</li>
+ * </ul>
+ */
+public interface ComplexCommand<A extends IgniteDataTransferObject, R>
+    extends Command<A, R>, CommandsRegistry {
+    /** @return {@code True} if base command represented by this registry can 
itself be executed. */
+    public default boolean canBeExecuted() {
+        return false;

Review Comment:
   Can be replaced with `task() != null`?



##########
modules/core/src/main/java/org/apache/ignite/internal/management/encryption/EncryptionCacheGroupArg.java:
##########
@@ -15,54 +15,43 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.visor.encryption;
+package org.apache.ignite.internal.management.encryption;
 
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import org.apache.ignite.internal.dto.IgniteDataTransferObject;
-import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.management.api.Argument;
+import org.apache.ignite.internal.management.api.Positional;
 import org.apache.ignite.internal.util.typedef.internal.U;
 
-/**
- * Cache group aware task argument.
- */
-public class VisorCacheGroupEncryptionTaskArg extends IgniteDataTransferObject 
{
+/** */
+public class EncryptionCacheGroupArg extends IgniteDataTransferObject {
     /** */
-    private static final long serialVersionUID = 0L;
-
-    /** Cache group name. */
-    private String grpName;
-
-    /** Default constructor. */
-    public VisorCacheGroupEncryptionTaskArg() {
-        // No-op.
-    }
+    private static final long serialVersionUID = 0;
 
-    /**
-     * @param grpName Cache group name.
-     */
-    public VisorCacheGroupEncryptionTaskArg(String grpName) {
-        this.grpName = grpName;
-    }
-
-    /** @return Cache group name. */
-    public String groupName() {
-        return grpName;
-    }
+    /** */
+    @Positional
+    @Argument(javaStyleExample = true)
+    private String cacheGroupName;
 
     /** {@inheritDoc} */
     @Override protected void writeExternalData(ObjectOutput out) throws 
IOException {
-        U.writeString(out, grpName);
+        U.writeString(out, cacheGroupName);
     }
 
     /** {@inheritDoc} */
-    @Override protected void readExternalData(byte ver, ObjectInput in) throws 
IOException, ClassNotFoundException {
-        grpName = U.readString(in);
+    @Override protected void readExternalData(byte protoVer, ObjectInput in) 
throws IOException, ClassNotFoundException {
+        cacheGroupName = U.readString(in);
     }
 
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(VisorCacheGroupEncryptionTaskArg.class, this);
+    /** */
+    public String getCacheGroupName() {

Review Comment:
   Internal API must not use get/set prefixes



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/EmptyArg.java:
##########
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+
+/** Utility class for commands without any specific arguments. */
+public class EmptyArg extends IgniteDataTransferObject {

Review Comment:
   EmptyArg -> NoArg?



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/ComplexCommand.java:
##########
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+
+/**
+ * Command that have subcommands. Combine {@link Command} and {@link 
CommandsRegistry} features.
+ * Subcommand name must start with the base command name like:
+ * <ul>
+ *     <li>Base command: {@code StateCommand}.</li>
+ *     <li>Subcommand: {@code StateSetCommand}, {@code StateGetCommand}, 
etc.</li>
+ * </ul>
+ */
+public interface ComplexCommand<A extends IgniteDataTransferObject, R>

Review Comment:
   Actually no need in ComplexCommand at all. Registry is enough. Registry 
should be available to handle another registry,



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<? extends A> args();
+
+    /** @return Task class. */
+    public Class<? extends ComputeTask<VisorTaskArgument<A>, R>> task();
+
+    /**
+     * Prints command result to the user.
+     * @param arg Argument.
+     * @param res Result.
+     * @param printer Implementation specific printer.
+     */
+    public default void printResult(A arg, R res, Consumer<String> printer) {
+        // No-op.
+    }
+
+    /** @return {@code true} if the command is experimental, {@code false} 
otherwise. */
+    public default boolean experimental() {
+        return false;
+    }
+
+    /**
+     * @return Message text to show user for. If null it means that 
confirmantion is not needed.

Review Comment:
   s/confirmantion/confirmation/



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/CommandsRegistry.java:
##########
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Map;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+
+/**
+ * Registry that knows all of its subcommands.
+ *
+ * @see org.apache.ignite.internal.management.IgniteCommandRegistry
+ */
+public interface CommandsRegistry extends Iterable<Map.Entry<String, 
Command<?, ?, ?>>> {
+    /**
+     * @param name Name of the command.
+     * @return Command instance by name.
+     */
+    public <A extends IgniteDataTransferObject> Command<A, ?, ?> 
command(String name);
+
+    /** @return {@code True} if base command represented by this registry can 
itself be executed. */
+    public default boolean canBeExecuted() {

Review Comment:
   CommandsRegistry doesn't extend Command. Looks like this method should be a 
part of CommandsRegistryImpl, and looks like `return this.taskCls != null;`



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<? extends A> args();

Review Comment:
   `Class<A>`?



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<? extends A> args();
+
+    /** @return Task class. */
+    public Class<? extends ComputeTask<VisorTaskArgument<A>, R>> task();
+
+    /**
+     * Prints command result to the user.
+     * @param arg Argument.
+     * @param res Result.
+     * @param printer Implementation specific printer.
+     */
+    public default void printResult(A arg, R res, Consumer<String> printer) {
+        // No-op.
+    }
+
+    /** @return {@code true} if the command is experimental, {@code false} 
otherwise. */
+    public default boolean experimental() {
+        return false;
+    }
+
+    /**
+     * @return Message text to show user for. If null it means that 
confirmantion is not needed.
+     */
+    public default String confirmationPrompt() {

Review Comment:
   `@Nullable`



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/CommandRegistryImpl.java:
##########
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import static 
org.apache.ignite.internal.management.api.Command.CMD_NAME_POSTFIX;
+
+/**
+ * All commands class names stored in registry must ends with {@link 
Command#CMD_NAME_POSTFIX}.
+ *
+ * @see org.apache.ignite.internal.management.kill.KillCommand
+ * @see org.apache.ignite.internal.management.kill.KillComputeCommand
+ */
+public abstract class CommandRegistryImpl implements CommandsRegistry {
+    /** Subcommands. */
+    private final Map<String, Command<?, ?>> commands = new LinkedHashMap<>();
+
+    /** */
+    protected CommandRegistryImpl() {
+        subcommands().forEach(this::register);

Review Comment:
   Why do we need `subcommands()` method? Can we use instead parameterized 
constructor instead? For registering command from plugins `register()` method 
should be public?



##########
modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/DeclarativeCommandAdapter.java:
##########
@@ -0,0 +1,409 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.commandline;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.client.GridClient;
+import org.apache.ignite.internal.client.GridClientCompute;
+import org.apache.ignite.internal.client.GridClientConfiguration;
+import org.apache.ignite.internal.client.GridClientNode;
+import org.apache.ignite.internal.commandline.argument.parser.CLIArgument;
+import 
org.apache.ignite.internal.commandline.argument.parser.CLIArgumentParser;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.management.AbstractCommandInvoker;
+import org.apache.ignite.internal.management.IgniteCommandRegistry;
+import org.apache.ignite.internal.management.api.Argument;
+import org.apache.ignite.internal.management.api.CliPositionalSubcommands;
+import org.apache.ignite.internal.management.api.CommandsRegistry;
+import org.apache.ignite.internal.management.api.ComplexCommand;
+import org.apache.ignite.internal.management.api.EnumDescription;
+import org.apache.ignite.internal.util.lang.GridTuple3;
+import org.apache.ignite.internal.util.lang.PeekableIterator;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+import org.apache.ignite.lang.IgniteBiTuple;
+import static java.util.Collections.singleton;
+import static 
org.apache.ignite.internal.commandline.CommandHandler.UTILITY_NAME;
+import static 
org.apache.ignite.internal.commandline.CommandLogger.DOUBLE_INDENT;
+import static org.apache.ignite.internal.commandline.CommandLogger.INDENT;
+import static 
org.apache.ignite.internal.commandline.CommonArgParser.CMD_AUTO_CONFIRMATION;
+import static 
org.apache.ignite.internal.commandline.TaskExecutor.getBalancedNode;
+import static 
org.apache.ignite.internal.commandline.argument.parser.CLIArgument.optionalArg;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.CMD_WORDS_DELIM;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.PARAMETER_PREFIX;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.PARAM_WORDS_DELIM;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.parameterExample;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.toFormattedCommandName;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.toFormattedFieldName;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.valueExample;
+
+/**
+ * Adapter of new management API command for legacy {@code control.sh} 
execution flow.
+ */
+public class DeclarativeCommandAdapter<A extends IgniteDataTransferObject> 
extends AbstractCommandInvoker implements Command<A> {
+    /** All commands registry. */
+    private final IgniteCommandRegistry standaloneRegistry = new 
IgniteCommandRegistry();

Review Comment:
   static?



##########
modules/core/src/main/java/org/apache/ignite/internal/management/api/Command.java:
##########
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.api;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+
+/**
+ * Management command interface.
+ * Implementations represents single action to manage Ignite cluster.
+ *
+ * Name of the command that is expected from caller derived from actual 
command class name.
+ * Name format: all words divided by capital letters except "Command" suffix 
will form hierarchical command name.
+ * Example: {@code MyUsefullCommand} is name of command so {@code control.sh 
--my-usesull param1 param2} expected from user.
+ * Other protocols must expose command similarly. Rest API must expect {@code 
/api-root/my-usefull?param1=value1&param2=value2} URI.
+ *
+ * @param <A> Argument type.
+ * @param <R> Result type.
+ */
+public interface Command<A extends IgniteDataTransferObject, R> {
+    /** */
+    public String CMD_NAME_POSTFIX = "Command";
+
+    /** Command description. */
+    public String description();
+
+    /** @return Arguments class. */
+    public Class<? extends A> args();

Review Comment:
   argClass()?



##########
modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/DeclarativeCommandAdapter.java:
##########
@@ -0,0 +1,409 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.commandline;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.client.GridClient;
+import org.apache.ignite.internal.client.GridClientCompute;
+import org.apache.ignite.internal.client.GridClientConfiguration;
+import org.apache.ignite.internal.client.GridClientNode;
+import org.apache.ignite.internal.commandline.argument.parser.CLIArgument;
+import 
org.apache.ignite.internal.commandline.argument.parser.CLIArgumentParser;
+import org.apache.ignite.internal.dto.IgniteDataTransferObject;
+import org.apache.ignite.internal.management.AbstractCommandInvoker;
+import org.apache.ignite.internal.management.IgniteCommandRegistry;
+import org.apache.ignite.internal.management.api.Argument;
+import org.apache.ignite.internal.management.api.CliPositionalSubcommands;
+import org.apache.ignite.internal.management.api.CommandsRegistry;
+import org.apache.ignite.internal.management.api.ComplexCommand;
+import org.apache.ignite.internal.management.api.EnumDescription;
+import org.apache.ignite.internal.util.lang.GridTuple3;
+import org.apache.ignite.internal.util.lang.PeekableIterator;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.internal.visor.VisorTaskArgument;
+import org.apache.ignite.lang.IgniteBiTuple;
+import static java.util.Collections.singleton;
+import static 
org.apache.ignite.internal.commandline.CommandHandler.UTILITY_NAME;
+import static 
org.apache.ignite.internal.commandline.CommandLogger.DOUBLE_INDENT;
+import static org.apache.ignite.internal.commandline.CommandLogger.INDENT;
+import static 
org.apache.ignite.internal.commandline.CommonArgParser.CMD_AUTO_CONFIRMATION;
+import static 
org.apache.ignite.internal.commandline.TaskExecutor.getBalancedNode;
+import static 
org.apache.ignite.internal.commandline.argument.parser.CLIArgument.optionalArg;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.CMD_WORDS_DELIM;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.PARAMETER_PREFIX;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.PARAM_WORDS_DELIM;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.parameterExample;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.toFormattedCommandName;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.toFormattedFieldName;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.valueExample;
+
+/**
+ * Adapter of new management API command for legacy {@code control.sh} 
execution flow.
+ */
+public class DeclarativeCommandAdapter<A extends IgniteDataTransferObject> 
extends AbstractCommandInvoker implements Command<A> {
+    /** All commands registry. */
+    private final IgniteCommandRegistry standaloneRegistry = new 
IgniteCommandRegistry();
+
+    /** Root command to start parsing from. */
+    private final org.apache.ignite.internal.management.api.Command<A, ?> 
baseCmd;
+
+    /** State of adapter after {@link #parseArguments(CommandArgIterator)} 
invokation. */
+    private GridTuple3<org.apache.ignite.internal.management.api.Command<A, 
?>, A, Boolean> parsed;
+
+    /** @param name Root command name. */
+    public DeclarativeCommandAdapter(String name) {
+        baseCmd = standaloneRegistry.command(name);
+
+        assert baseCmd != null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void parseArguments(CommandArgIterator argIterator) {

Review Comment:
   argIterator -> argIter



##########
modules/core/src/main/java/org/apache/ignite/internal/management/encryption/CacheGroupEncryptionCommand.java:
##########
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.management.encryption;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.UUID;
+import java.util.function.Consumer;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.management.api.Command;
+import 
org.apache.ignite.internal.visor.encryption.VisorCacheGroupEncryptionTask;
+import 
org.apache.ignite.internal.visor.encryption.VisorCacheGroupEncryptionTaskResult;
+import static 
org.apache.ignite.internal.management.api.CommandUtils.DOUBLE_INDENT;
+import static org.apache.ignite.internal.management.api.CommandUtils.INDENT;
+
+/** */
+abstract class CacheGroupEncryptionCommand<T, C extends 
VisorCacheGroupEncryptionTask<T>>

Review Comment:
   Don't need type C



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to