Martin Peřina has posted comments on this change.

Change subject: uutils: added new cli parser
......................................................................


Patch Set 8:

(17 comments)

Since this is going to be used in all extensions that needs command line 
parsing and also in engine, then we really need proper JavaDoc for API

https://gerrit.ovirt.org/#/c/40157/8/backend/manager/modules/uutils/src/main/java/org/ovirt/engine/core/uutils/cli/parser/ParametersParser.java
File 
backend/manager/modules/uutils/src/main/java/org/ovirt/engine/core/uutils/cli/parser/ParametersParser.java:

Line 19: import java.util.TreeSet;
Line 20: import java.util.regex.Matcher;
Line 21: import java.util.regex.Pattern;
Line 22: 
Line 23: public class ParametersParser {
I would prefer ArgumentParser as it describes better that is parses command 
line arguments
Line 24: 
Line 25:     /**
Line 26:      * Key under which are stored other arguments in map 
<code>arguments</code>.
Line 27:      * Use it to obtain rest of arguments, which was not parsed by 
parser.


Line 33:      */
Line 34:     public static final String PARAMETER_KEY_ERRORS = "__error__";
Line 35: 
Line 36:     private static final String LONG_PREFIX = "--";
Line 37:     private static final Properties defaultProperties = 
loadProperties(ParametersParser.class, "defaults.properties");
Please use:

 private static final Properties defaultProperties = 
         loadProperties(
                
ParametersParser.class.getResourceAsStream("defaults.properties"));

and remove unnecessary loadProperties(Class, String)
Line 38: 
Line 39:     private Properties properties;
Line 40:     private String prefix;
Line 41:     private Map<String, ParserArgument> arguments = new HashMap<>();


Line 40:     private String prefix;
Line 41:     private Map<String, ParserArgument> arguments = new HashMap<>();
Line 42:     private Set<String> mandatory = new HashSet<>();
Line 43: 
Line 44:     static enum ArgumentType {
Please remove static keyword, it's the default for inner enum
Line 45:         has_argument,
Line 46:         optional_argument,
Line 47:         no_argument,
Line 48:     }


Line 43: 
Line 44:     static enum ArgumentType {
Line 45:         has_argument,
Line 46:         optional_argument,
Line 47:         no_argument,
1. Please use Java Coding Conventions, enum value names should be in upper case.

2. Also I would prefer this naming so it's really clear what each value means:

 enum ArgumentValue {
     MANDATORY,
     OPTIONAL,
     NONE
 }

3. This enum doesn't belong here, but it should be part of ParserArgument (if 
it's used only internally) or it should be standalone enum (in its own file)
Line 48:     }
Line 49: 
Line 50:     public ParametersParser(Properties properties, String prefix) {
Line 51:         this.properties = properties;


Line 52:         this.prefix = prefix;
Line 53:         parseProperties();
Line 54:     }
Line 55: 
Line 56:     public ParametersParser(InputStream resource, String prefix) {
Is this really necessary? IMO the caller is responsible for providing 
Properties instance, ParametersParser should not do that.
Line 57:         this(loadProperties(resource), prefix);
Line 58:     }
Line 59: 
Line 60:     public Map<String, Object> parse(String... args) {


Line 70:             String arg = args.get(0);
Line 71:             if(!arg.startsWith(LONG_PREFIX)) {
Line 72:                 break;
Line 73:             }
Line 74:             arg = args.remove(0);
Usually it's a bad behavior to modify Collection provided by caller. Wouldn't 
it be better to reimplement it without modification of args?
Line 75:             if(arg.equals(LONG_PREFIX)) {
Line 76:                 break;
Line 77:             }
Line 78: 


Line 89:                 if (
Line 90:                     value == null &&
Line 91:                     (
Line 92:                         parserArgument.getType() == 
ArgumentType.optional_argument ||
Line 93:                         parserArgument.getType() == 
ArgumentType.has_argument
Wouldn't it be better to use:

  if (value == null && parserArgument.getType() != ArgumentValue.NONE) {
Line 94:                     )
Line 95:                 ) {
Line 96:                     if(args.size() > 0) {
Line 97:                         value = args.get(0);


Line 94:                     )
Line 95:                 ) {
Line 96:                     if(args.size() > 0) {
Line 97:                         value = args.get(0);
Line 98:                         if (value.startsWith("--")) {
Please use LONG_PREFIX constant
Line 99:                             value = null;
Line 100:                         } else {
Line 101:                             args.remove(0);
Line 102:                         }


Line 141:             );
Line 142:         }
Line 143:         others.addAll(args);
Line 144:         argMap.put(PARAMETER_KEY_OTHER, others);
Line 145:         argMap.put(PARAMETER_KEY_ERRORS, errors);
I would prefer to store errors in its own attribute and to provide getErrors() 
method
Line 146: 
Line 147:         return argMap;
Line 148:     }
Line 149: 


Line 162:     private void putValue(Map<String, Object> argMap, ParserArgument 
arg, Object value) {
Line 163:         if (!arg.isMultivalue()) {
Line 164:             argMap.put(arg.getName(), value);
Line 165:         } else {
Line 166:             Collection c = (Collection) argMap.get(arg.getName());
Please use List<?> instead of Collection
Line 167:             if (c == null) {
Line 168:                 c = new ArrayList<>();
Line 169:                 argMap.put(arg.getName(), c);
Line 170:             }


https://gerrit.ovirt.org/#/c/40157/8/backend/manager/modules/uutils/src/main/java/org/ovirt/engine/core/uutils/cli/parser/ParserArgument.java
File 
backend/manager/modules/uutils/src/main/java/org/ovirt/engine/core/uutils/cli/parser/ParserArgument.java:

Line 1: package org.ovirt.engine.core.uutils.cli.parser;
Line 2: 
Line 3: import java.util.regex.Pattern;
Line 4: 
Line 5: public class ParserArgument {
I would prefer just Argument
Line 6: 
Line 7:     private String name;
Line 8:     private String help;
Line 9:     private String defaultValue;


Line 14:     private String metavar;
Line 15:     private boolean multivalue;
Line 16:     private String value;
Line 17: 
Line 18:     public ParserArgument() {}
Please remove this empty constructor
Line 19: 
Line 20:     public String getName() {
Line 21:         return name;
Line 22:     }


Line 104:         }
Line 105:         if(obj == this) {
Line 106:             return true;
Line 107:         }
Line 108: 
Please use this order of conditions as it's considered best practise:

        if (this == obj) {
            return true;
        }
        if (!(obj instanceof ParserArgument)) {
            return false;
        }
Line 109:         return this.name.equals(((ParserArgument) obj).getName());
Line 110:     }
Line 111: 
Line 112:     @Override


Line 105:         if(obj == this) {
Line 106:             return true;
Line 107:         }
Line 108: 
Line 109:         return this.name.equals(((ParserArgument) obj).getName());
Please use:

  return Objects.equals(name, ((ParserArgument) obj).getName());
Line 110:     }
Line 111: 
Line 112:     @Override
Line 113:     public int hashCode() {


Line 110:     }
Line 111: 
Line 112:     @Override
Line 113:     public int hashCode() {
Line 114:         return 37 * name.hashCode();
Please use:

 return Objects.hash(name);
Line 115:     }


https://gerrit.ovirt.org/#/c/40157/8/backend/manager/modules/uutils/src/main/java/org/ovirt/engine/core/uutils/cli/parser/Util.java
File 
backend/manager/modules/uutils/src/main/java/org/ovirt/engine/core/uutils/cli/parser/Util.java:

Line 10: import java.util.HashMap;
Line 11: import java.util.List;
Line 12: import java.util.Map;
Line 13: 
Line 14: public class Util {
Please don't ever use such common name. I would prefer:

 ArgumentValueConverter
 ArgumentParserUtils
Line 15: 
Line 16:     private static final Map<Class<?>, Class<?>> typeBox = new 
HashMap<>();
Line 17:     static {
Line 18:         typeBox.put(boolean.class, Boolean.class);


Line 32:         if (clazz.isPrimitive()) {
Line 33:             clazz = typeBox.get(clazz);
Line 34:         }
Line 35: 
Line 36:         if (v == null) {
Condition is always true here!
Line 37:             if (clazz.equals(Collection.class)) {
Line 38:                 List<Object> r = new ArrayList<>();
Line 39:                 for (String c : value.trim().split(" *, *")) {
Line 40:                     if (!c.isEmpty()) {


-- 
To view, visit https://gerrit.ovirt.org/40157
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: comment
Gerrit-Change-Id: I00042b669e19293641579582223e7ca40717132d
Gerrit-PatchSet: 8
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Ondra Machacek <omach...@redhat.com>
Gerrit-Reviewer: Alon Bar-Lev <alo...@redhat.com>
Gerrit-Reviewer: Martin Peřina <mper...@redhat.com>
Gerrit-Reviewer: Mooli Tayer <mta...@redhat.com>
Gerrit-Reviewer: Ondra Machacek <omach...@redhat.com>
Gerrit-Reviewer: Oved Ourfali <oourf...@redhat.com>
Gerrit-Reviewer: automat...@ovirt.org
Gerrit-Reviewer: mooli tayer <mta...@redhat.com>
Gerrit-Reviewer: oVirt Jenkins CI Server
Gerrit-HasComments: Yes
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to