Fix sonar issues in Command line editor 47/68847/1
authorliamfallon <liam.fallon@ericsson.com>
Tue, 25 Sep 2018 12:03:21 +0000 (13:03 +0100)
committerliamfallon <liam.fallon@ericsson.com>
Tue, 25 Sep 2018 12:04:24 +0000 (13:04 +0100)
THe Apex command line editor had issues in teh way its loops for processing
commands were written. The loops are simplified in this review.

Issue-ID: POLICY-1034
Change-Id: If684a57de79bd56211e1ca3e8c446bd9698666be
Signed-off-by: liamfallon <liam.fallon@ericsson.com>
auth/cli-editor/src/main/java/org/onap/policy/apex/auth/clieditor/ApexModelHandler.java
auth/cli-editor/src/main/java/org/onap/policy/apex/auth/clieditor/CommandLineEditorLoop.java
auth/cli-editor/src/main/java/org/onap/policy/apex/auth/clieditor/CommandLineParser.java
model/model-api/src/main/java/org/onap/policy/apex/model/modelapi/ApexApiResult.java

index 3d14a83..67d247e 100644 (file)
@@ -27,6 +27,7 @@ import java.util.Properties;
 import java.util.SortedMap;
 
 import org.onap.policy.apex.model.modelapi.ApexApiResult;
+import org.onap.policy.apex.model.modelapi.ApexApiResult.Result;
 import org.onap.policy.apex.model.modelapi.ApexModel;
 import org.onap.policy.apex.model.modelapi.ApexModelFactory;
 
@@ -76,7 +77,7 @@ public class ApexModelHandler {
      * @param writer A writer to which to write output
      * @return the result of the executed command
      */
-    public ApexApiResult executeCommand(final CommandLineCommand command,
+    public Result executeCommand(final CommandLineCommand command,
                     final SortedMap<String, CommandLineArgumentValue> argumentValues, final PrintWriter writer) {
         // Get the method
         final Method apiMethod = getCommandMethod(command);
@@ -90,7 +91,7 @@ public class ApexModelHandler {
             if (returnObject instanceof ApexApiResult) {
                 final ApexApiResult result = (ApexApiResult) returnObject;
                 writer.println(result);
-                return result;
+                return result.getResult();
             } else {
                 throw new CommandLineException(INVOCATION_OF_SPECIFIED_METHOD + command.getApiMethod()
                                 + FAILED_FOR_COMMAND + command.getName()
index b5e8210..4890529 100644 (file)
@@ -39,6 +39,8 @@ import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.TreeMap;
 
+import org.apache.commons.lang3.tuple.MutablePair;
+import org.apache.commons.lang3.tuple.Pair;
 import org.onap.policy.apex.model.modelapi.ApexApiResult;
 import org.onap.policy.apex.model.modelapi.ApexApiResult.Result;
 import org.onap.policy.apex.model.utilities.TextFileUtils;
@@ -108,35 +110,72 @@ public class CommandLineEditorLoop {
         // The parser parses the input lines into commands and arguments
         final CommandLineParser parser = new CommandLineParser();
 
+        // The execution status has the result of the latest command and a cumulative error count
+        MutablePair<Result, Integer> executionStatus = new MutablePair<>(Result.SUCCESS, 0);
+
         // The main loop for command handing, it continues until EOF on the input stream or until a
         // quit command
-        int errorCount = 0;
-        ApexApiResult result = new ApexApiResult();
-        while (result.getResult() != Result.FINISHED) {
-            if (!parameters.isIgnoreCommandFailures() && errorCount > 0) {
-                break;
+        while (!endOfCommandExecution(executionStatus, parameters)) {
+            processIncomingCommands(parameters, reader, writer, parser, executionStatus);
+        }
+
+        // Get the output model
+        if (!parameters.isSuppressModelOutputSet()) {
+            final String modelString = modelHandler.writeModelToString(writer);
+
+            if (parameters.checkSetOutputModelFileName()) {
+                TextFileUtils.putStringAsTextFile(modelString, parameters.getOutputModelFileName());
+            } else {
+                System.out.println(modelString);
             }
+        }
 
+        reader.close();
+        writer.close();
+
+        return executionStatus.getRight();
+    }
+
+    /**
+     * Check if the command processing loop has come to an end.
+     * 
+     * @param executionStatus a pair containing the result of the last command and the accumulated error count
+     * @param parameters the input parameters for command execution
+     * @return true if the command processing loop should exit
+     */
+    private boolean endOfCommandExecution(Pair<Result, Integer> executionStatus, CommandLineParameters parameters) {
+        if (executionStatus.getLeft() == Result.FINISHED) {
+            return true;
+        }
+
+        return executionStatus.getRight() > 0 && !parameters.isIgnoreCommandFailures();
+    }
+
+    /**
+     * Process the incoming commands one by one.
+     * 
+     * @param parameters the parameters to the CLI editor
+     * @param reader the reader to read the logic block from
+     * @param writer the writer to write results and error messages on
+     * @param executionStatus the status of the logic block read
+     */
+    private void processIncomingCommands(final CommandLineParameters parameters, final BufferedReader reader,
+                    final PrintWriter writer, final CommandLineParser parser,
+                    MutablePair<Result, Integer> executionStatus) {
+
+        try {
             // Output prompt and get a line of input
             writer.print(getPrompt());
             writer.flush();
             String line = reader.readLine();
             if (line == null) {
-                break;
+                executionStatus.setLeft(Result.FINISHED);
+                return;
             }
 
             // Expand any macros in the script
-            try {
-                while (line.contains(macroFileTag)) {
-                    line = expandMacroFile(parameters, line);
-                }
-            }
-            // Print any error messages from command parsing and finding
-            catch (final CommandLineException e) {
-                writer.println(e.getMessage());
-                errorCount++;
-                LOGGER.debug(COMMAND_LINE_ERROR, e);
-                continue;
+            while (line.contains(macroFileTag)) {
+                line = expandMacroFile(parameters, line);
             }
 
             if (parameters.isEchoSet()) {
@@ -147,86 +186,86 @@ public class CommandLineEditorLoop {
             if (line.trim().endsWith(logicBlockStartTag)) {
                 line = line.replace(logicBlockStartTag, "").trim();
 
-                logicBlock = "";
-                while (true) {
-                    String logicLine = reader.readLine();
-                    if (logicLine == null) {
-                        logicBlock = null;
-                        break;
-                    }
-
-                    try {
-                        while (logicLine.contains(macroFileTag)) {
-                            logicLine = expandMacroFile(parameters, logicLine);
-                        }
-                    }
-                    // Print any error messages from command parsing and finding
-                    catch (final CommandLineException e) {
-                        writer.println(e.getMessage());
-                        errorCount++;
-                        LOGGER.debug(COMMAND_LINE_ERROR, e);
-                        continue;
-                    }
-
-                    if (parameters.isEchoSet()) {
-                        writer.println(logicLine);
-                    }
-
-                    if (logicLine.trim().endsWith(logicBlockEndTag)) {
-                        logicBlock += logicLine.replace(logicBlockEndTag, "").trim() + "\n";
-                        break;
-                    } else {
-                        logicBlock += logicLine + "\n";
-                    }
+                logicBlock = readLogicBlock(parameters, reader, writer, executionStatus);
+            }
+
+            // Parse the line into a list of commands and arguments
+            final List<String> commandWords = parser.parse(line, logicBlock);
+
+            // Find the command, if the command is null, then we are simply changing position in
+            // the hierarchy
+            final CommandLineCommand command = findCommand(commandWords);
+            if (command != null) {
+                // Check the arguments of the command
+                final TreeMap<String, CommandLineArgumentValue> argumentValues = getArgumentValues(command,
+                                commandWords);
+
+                // Execute the command, a FINISHED result means a command causes the loop to
+                // leave execution
+                executionStatus.setLeft(executeCommand(command, argumentValues, writer));
+                if (ApexApiResult.Result.isNok(executionStatus.getLeft())) {
+                    executionStatus.setRight(executionStatus.getRight() + 1);
                 }
             }
+        }
+        // Print any error messages from command parsing and finding
+        catch (final CommandLineException e) {
+            writer.println(e.getMessage());
+            executionStatus.setRight(executionStatus.getRight() + 1);
+            LOGGER.debug(COMMAND_LINE_ERROR, e);
+        } catch (final Exception e) {
+            e.printStackTrace(writer);
+            LOGGER.error(COMMAND_LINE_ERROR, e);
+        }
+    }
+
+    /**
+     * Read a logic block, a block of program logic for a policy.
+     * 
+     * @param parameters the parameters to the CLI editor
+     * @param reader the reader to read the logic block from
+     * @param writer the writer to write results and error messages on
+     * @param executionStatus the status of the logic block read
+     * @return the result of the logic block read
+     */
+    private String readLogicBlock(final CommandLineParameters parameters, final BufferedReader reader,
+                    final PrintWriter writer, MutablePair<Result, Integer> executionStatus) {
+        String logicBlock;
+        logicBlock = "";
 
+        while (true) {
             try {
-                // Parse the line into a list of commands and arguments
-                final List<String> commandWords = parser.parse(line, logicBlock);
-
-                // Find the command, if the command is null, then we are simply changing position in
-                // the hierarchy
-                final CommandLineCommand command = findCommand(commandWords);
-                if (command != null) {
-                    // Check the arguments of the command
-                    final TreeMap<String, CommandLineArgumentValue> argumentValues = getArgumentValues(command,
-                                    commandWords);
-
-                    // Execute the command, a FINISHED result means a command causes the loop to
-                    // leave execution
-                    result = executeCommand(command, argumentValues, writer);
-                    if (result.isNok()) {
-                        errorCount++;
-                    }
+                String logicLine = reader.readLine();
+                if (logicLine == null) {
+                    return null;
+                }
+
+                while (logicLine.contains(macroFileTag)) {
+                    logicLine = expandMacroFile(parameters, logicLine);
+                }
+
+                if (parameters.isEchoSet()) {
+                    writer.println(logicLine);
+                }
+
+                if (logicLine.trim().endsWith(logicBlockEndTag)) {
+                    logicBlock += logicLine.replace(logicBlockEndTag, "").trim() + "\n";
+                    return logicBlock;
+                } else {
+                    logicBlock += logicLine + "\n";
                 }
             }
             // Print any error messages from command parsing and finding
             catch (final CommandLineException e) {
                 writer.println(e.getMessage());
-                errorCount++;
+                executionStatus.setRight(executionStatus.getRight() + 1);
                 LOGGER.debug(COMMAND_LINE_ERROR, e);
+                continue;
             } catch (final Exception e) {
                 e.printStackTrace(writer);
                 LOGGER.error(COMMAND_LINE_ERROR, e);
             }
         }
-
-        // Get the output model
-        if (!parameters.isSuppressModelOutputSet()) {
-            final String modelString = modelHandler.writeModelToString(writer);
-
-            if (parameters.checkSetOutputModelFileName()) {
-                TextFileUtils.putStringAsTextFile(modelString, parameters.getOutputModelFileName());
-            } else {
-                System.out.println(modelString);
-            }
-        }
-
-        reader.close();
-        writer.close();
-
-        return errorCount;
     }
 
     /**
@@ -342,8 +381,8 @@ public class CommandLineEditorLoop {
                 throw new CommandLineException(COMMAND + stringAL2String(commandWords) + ": " + " argument \""
                                 + argument.getKey() + "\" not allowed on command");
             } else if (foundArguments.size() > 1) {
-                throw new CommandLineException(COMMAND + stringAL2String(commandWords) + ": " + " argument "
-                                + argument + " matches multiple arguments [" + argumentAL2String(foundArguments) + ']');
+                throw new CommandLineException(COMMAND + stringAL2String(commandWords) + ": " + " argument " + argument
+                                + " matches multiple arguments [" + argumentAL2String(foundArguments) + ']');
             }
 
             // Set the value of the argument, stripping off any quotes
@@ -356,9 +395,8 @@ public class CommandLineEditorLoop {
             // Argument values are null by default so if this argument is not nullable it is
             // mandatory
             if (!argumentValue.isSpecified() && !argumentValue.getCliArgument().isNullable()) {
-                throw new CommandLineException(COMMAND + stringAL2String(commandWords) + ": "
-                                + " mandatory argument \"" + argumentValue.getCliArgument().getArgumentName()
-                                + "\" not specified");
+                throw new CommandLineException(COMMAND + stringAL2String(commandWords) + ": " + " mandatory argument \""
+                                + argumentValue.getCliArgument().getArgumentName() + "\" not specified");
             }
         }
 
@@ -395,7 +433,7 @@ public class CommandLineEditorLoop {
      * @param writer The writer to use for any output from the command
      * @return the result of execution of the command
      */
-    private ApexApiResult executeCommand(final CommandLineCommand command,
+    private Result executeCommand(final CommandLineCommand command,
                     final TreeMap<String, CommandLineArgumentValue> argumentValues, final PrintWriter writer) {
         if (command.isSystemCommand()) {
             return exceuteSystemCommand(command, writer);
@@ -411,7 +449,7 @@ public class CommandLineEditorLoop {
      * @param writer The writer to use for any output from the command
      * @return the result of execution of the command
      */
-    private ApexApiResult exceuteSystemCommand(final CommandLineCommand command, final PrintWriter writer) {
+    private Result exceuteSystemCommand(final CommandLineCommand command, final PrintWriter writer) {
         if ("back".equals(command.getName())) {
             return executeBackCommand();
         } else if ("help".equals(command.getName())) {
@@ -419,7 +457,7 @@ public class CommandLineEditorLoop {
         } else if ("quit".equals(command.getName())) {
             return executeQuitCommand();
         } else {
-            return new ApexApiResult(Result.SUCCESS);
+            return Result.SUCCESS;
         }
     }
 
@@ -428,11 +466,11 @@ public class CommandLineEditorLoop {
      *
      * @return the result of execution of the command
      */
-    private ApexApiResult executeBackCommand() {
+    private Result executeBackCommand() {
         if (keywordNodeDeque.size() > 1) {
             keywordNodeDeque.pop();
         }
-        return new ApexApiResult(Result.SUCCESS);
+        return Result.SUCCESS;
     }
 
     /**
@@ -440,8 +478,8 @@ public class CommandLineEditorLoop {
      *
      * @return the result of execution of the command
      */
-    private ApexApiResult executeQuitCommand() {
-        return new ApexApiResult(Result.FINISHED);
+    private Result executeQuitCommand() {
+        return Result.FINISHED;
     }
 
     /**
@@ -450,11 +488,11 @@ public class CommandLineEditorLoop {
      * @param writer The writer to use for output from the command
      * @return the result of execution of the command
      */
-    private ApexApiResult executeHelpCommand(final PrintWriter writer) {
+    private Result executeHelpCommand(final PrintWriter writer) {
         for (final CommandLineCommand command : keywordNodeDeque.peek().getCommands()) {
             writer.println(command.getHelp());
         }
-        return new ApexApiResult(Result.SUCCESS);
+        return Result.SUCCESS;
     }
 
     /**
index aa74f4b..3eba53d 100644 (file)
@@ -21,6 +21,7 @@
 package org.onap.policy.apex.auth.clieditor;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -31,10 +32,9 @@ import java.util.List;
 public class CommandLineParser {
 
     /**
-     * This method breaks a line of input up into commands, parameters, and arguments. Commands are
-     * standalone words at the beginning of the line, of which there may be multiple Parameters are
-     * single words followed by an '=' character Arguments are single words or a block of quoted
-     * text following an '=' character.
+     * This method breaks a line of input up into commands, parameters, and arguments. Commands are standalone words at
+     * the beginning of the line, of which there may be multiple Parameters are single words followed by an '='
+     * character Arguments are single words or a block of quoted text following an '=' character.
      *
      * <p>Format: command [command....] parameter=argument [parameter = argument]
      *
@@ -46,9 +46,9 @@ public class CommandLineParser {
      */
     public List<String> parse(final String line, final String logicBlock) {
         return checkFormat(
-                mergeArguments(mergeEquals(
-                        splitOnEquals(stripAndSplitWords(mergeQuotes(splitOnChar(stripComments(line), '\"')))))),
-                logicBlock);
+                        mergeArguments(mergeEquals(splitOnEquals(
+                                        stripAndSplitWords(mergeQuotes(splitOnChar(stripComments(line), '\"')))))),
+                        logicBlock);
     }
 
     /**
@@ -67,10 +67,9 @@ public class CommandLineParser {
     }
 
     /**
-     * This method merges an array with separate quotes into an array with quotes delimiting the
-     * start and end of quoted words Example [Humpty ],["],[Dumpty sat on the wall],["],[, Humpty
-     * Dumpty had ],["],["],a ["],[great],["],[ fall] becomes [Humpty ],["Dumpty sat on the
-     * wall"],[, Humpty Dumpty had ],[""],[a],["great"],[ fall].
+     * This method merges an array with separate quotes into an array with quotes delimiting the start and end of quoted
+     * words Example [Humpty ],["],[Dumpty sat on the wall],["],[, Humpty Dumpty had ],["],["],a ["],[great],["],[ fall]
+     * becomes [Humpty ],["Dumpty sat on the wall"],[, Humpty Dumpty had ],[""],[a],["great"],[ fall].
      *
      * @param wordsSplitOnQuotes the words split on quotes
      * @return the merged array list
@@ -78,35 +77,51 @@ public class CommandLineParser {
     private ArrayList<String> mergeQuotes(final ArrayList<String> wordsSplitOnQuotes) {
         final ArrayList<String> wordsWithQuotesMerged = new ArrayList<>();
 
-        for (int i = 0; i < wordsSplitOnQuotes.size();) {
-            if ("\"".equals(wordsSplitOnQuotes.get(i))) {
-                StringBuilder quotedWord = new StringBuilder(wordsSplitOnQuotes.get(i++));
+        int loopWordIndex = 0;
+        for (int wordIndex = 0; wordIndex < wordsSplitOnQuotes.size(); wordIndex = loopWordIndex) {
+            loopWordIndex = mergeQuote(wordsSplitOnQuotes, wordsWithQuotesMerged, wordIndex);
+        }
 
-                for (; i < wordsSplitOnQuotes.size(); i++) {
-                    quotedWord.append(wordsSplitOnQuotes.get(i));
-                    if ("\"".equals(wordsSplitOnQuotes.get(i))) {
-                        i++;
-                        break;
-                    }
-                }
-                String quotedWordToString = quotedWord.toString();
-                if (quotedWordToString.matches("^\".*\"$")) {
-                    wordsWithQuotesMerged.add(quotedWordToString);
-                } else {
-                    throw new CommandLineException("trailing quote found in input " + wordsSplitOnQuotes);
+        return wordsWithQuotesMerged;
+    }
+
+    /**
+     * This method merges the next set of quotes.
+     * 
+     * @param wordsSplitOnQuotes the words split on quotes
+     * @param wordsWithQuotesMerged the merged words
+     * @param wordIndex the current word index
+     * @return the next word index
+     */
+    private int mergeQuote(final ArrayList<String> wordsSplitOnQuotes, final ArrayList<String> wordsWithQuotesMerged,
+                    int wordIndex) {
+
+        if ("\"".equals(wordsSplitOnQuotes.get(wordIndex))) {
+            StringBuilder quotedWord = new StringBuilder(wordsSplitOnQuotes.get(wordIndex++));
+
+            for (; wordIndex < wordsSplitOnQuotes.size(); wordIndex++) {
+                quotedWord.append(wordsSplitOnQuotes.get(wordIndex));
+                if ("\"".equals(wordsSplitOnQuotes.get(wordIndex))) {
+                    wordIndex++;
+                    break;
                 }
+            }
+            String quotedWordToString = quotedWord.toString();
+            if (quotedWordToString.matches("^\".*\"$")) {
+                wordsWithQuotesMerged.add(quotedWordToString);
             } else {
-                wordsWithQuotesMerged.add(wordsSplitOnQuotes.get(i++));
+                throw new CommandLineException("trailing quote found in input " + wordsSplitOnQuotes);
             }
+        } else {
+            wordsWithQuotesMerged.add(wordsSplitOnQuotes.get(wordIndex++));
         }
-
-        return wordsWithQuotesMerged;
+        return wordIndex;
     }
 
     /**
-     * This method splits the words on an array list into an array list where each portion of the
-     * line is split into words by '=', quoted words are ignored Example: aaa = bbb = ccc=ddd=eee =
-     * becomes [aaa ],[=],[bbb ],[=],[ccc],[=],[ddd],[=],[eee ],[=].
+     * This method splits the words on an array list into an array list where each portion of the line is split into
+     * words by '=', quoted words are ignored Example: aaa = bbb = ccc=ddd=eee = becomes [aaa ],[=],[bbb
+     * ],[=],[ccc],[=],[ddd],[=],[eee ],[=].
      *
      * @param words the words
      * @return the merged array list
@@ -132,9 +147,8 @@ public class CommandLineParser {
     }
 
     /**
-     * This method merges an array with separate equals into an array with equals delimiting the
-     * start of words Example: [aaa ],[=],[bbb ],[=],[ccc],[=],[ddd],[=],[eee ],[=] becomes [aaa
-     * ],[= bbb ],[= ccc],[=ddd],[=eee ],[=].
+     * This method merges an array with separate equals into an array with equals delimiting the start of words Example:
+     * [aaa ],[=],[bbb ],[=],[ccc],[=],[ddd],[=],[eee ],[=] becomes [aaa ],[= bbb ],[= ccc],[=ddd],[=eee ],[=].
      *
      * @param wordsSplitOnEquals the words split on equals
      * @return the merged array list
@@ -142,22 +156,27 @@ public class CommandLineParser {
     private ArrayList<String> mergeEquals(final ArrayList<String> wordsSplitOnEquals) {
         final ArrayList<String> wordsWithEqualsMerged = new ArrayList<>();
 
-        for (int i = 0; i < wordsSplitOnEquals.size();) {
+        int loopWordIndex = 0;
+        for (int wordIndex = 0; wordIndex < wordsSplitOnEquals.size(); wordIndex = loopWordIndex) {
+            loopWordIndex = wordIndex;
+
             // Is this a quoted word ?
-            if (wordsSplitOnEquals.get(i).startsWith("\"")) {
-                wordsWithEqualsMerged.add(wordsSplitOnEquals.get(i));
+            if (wordsSplitOnEquals.get(loopWordIndex).startsWith("\"")) {
+                wordsWithEqualsMerged.add(wordsSplitOnEquals.get(loopWordIndex));
                 continue;
             }
 
-            if ("=".equals(wordsSplitOnEquals.get(i))) {
-                if (i < wordsSplitOnEquals.size() - 1 && !wordsSplitOnEquals.get(i + 1).startsWith("=")) {
-                    wordsWithEqualsMerged.add(wordsSplitOnEquals.get(i) + wordsSplitOnEquals.get(i + 1));
-                    i += 2;
+            if ("=".equals(wordsSplitOnEquals.get(loopWordIndex))) {
+                if (loopWordIndex < wordsSplitOnEquals.size() - 1
+                                && !wordsSplitOnEquals.get(loopWordIndex + 1).startsWith("=")) {
+                    wordsWithEqualsMerged.add(
+                                    wordsSplitOnEquals.get(loopWordIndex) + wordsSplitOnEquals.get(loopWordIndex + 1));
+                    loopWordIndex += 2;
                 } else {
-                    wordsWithEqualsMerged.add(wordsSplitOnEquals.get(i++));
+                    wordsWithEqualsMerged.add(wordsSplitOnEquals.get(loopWordIndex++));
                 }
             } else {
-                wordsWithEqualsMerged.add(wordsSplitOnEquals.get(i++));
+                wordsWithEqualsMerged.add(wordsSplitOnEquals.get(loopWordIndex++));
             }
         }
 
@@ -165,8 +184,8 @@ public class CommandLineParser {
     }
 
     /**
-     * This method merges words that start with an '=' character with the previous word if that word
-     * does not start with an '='.
+     * This method merges words that start with an '=' character with the previous word if that word does not start with
+     * an '='.
      *
      * @param words the words
      * @return the merged array list
@@ -197,8 +216,8 @@ public class CommandLineParser {
     }
 
     /**
-     * This method strips all non quoted white space down to single spaces and splits non-quoted
-     * words into separate words.
+     * This method strips all non quoted white space down to single spaces and splits non-quoted words into separate
+     * words.
      *
      * @param words the words
      * @return the array list with white space stripped and words split
@@ -210,32 +229,46 @@ public class CommandLineParser {
             // Is this a quoted word
             if (word.startsWith("\"")) {
                 strippedAndSplitWords.add(word);
-                continue;
+            } else {
+                // Split the word on blanks
+                strippedAndSplitWords.addAll(stripAndSplitWord(word));
             }
+        }
 
-            // Strip white space by replacing all white space with blanks and then removing leading
-            // and trailing blanks
-            word = word.replaceAll("\\s+", " ").trim();
+        return strippedAndSplitWords;
+    }
 
-            if (word.length() == 0) {
-                continue;
-            }
+    /**
+     * Strip and split a word on blanks into an array of words split on blanks.
+     * 
+     * @param word the word to split
+     * @return the array of split words
+     */
+    private Collection<? extends String> stripAndSplitWord(final String word) {
+        final ArrayList<String> strippedAndSplitWords = new ArrayList<>();
 
-            // Split on space characters
-            final String[] splitWords = word.split(" ");
-            for (final String splitWord : splitWords) {
-                strippedAndSplitWords.add(splitWord);
-            }
+        // Strip white space by replacing all white space with blanks and then removing leading
+        // and trailing blanks
+        String singleSpaceWord = word.replaceAll("\\s+", " ").trim();
+
+        if (singleSpaceWord.length() == 0) {
+            return strippedAndSplitWords;
+        }
+
+        // Split on space characters
+        final String[] splitWords = singleSpaceWord.split(" ");
+        for (final String splitWord : splitWords) {
+            strippedAndSplitWords.add(splitWord);
         }
 
         return strippedAndSplitWords;
     }
 
     /**
-     * This method splits a line of text into an array list where each portion of the line is split
-     * into words by a character, with the characters themselves as separate words Example: Humpty
-     * "Dumpty sat on the wall", Humpty Dumpty had ""a "great" fall becomes [Humpty ],["],[Dumpty
-     * sat on the wall],["],[, Humpty Dumpty had ],["],["],a ["],[great],["],[ fall].
+     * This method splits a line of text into an array list where each portion of the line is split into words by a
+     * character, with the characters themselves as separate words Example: Humpty "Dumpty sat on the wall", Humpty
+     * Dumpty had ""a "great" fall becomes [Humpty ],["],[Dumpty sat on the wall],["],[, Humpty Dumpty had ],["],["],a
+     * ["],[great],["],[ fall].
      *
      * @param line the input line
      * @param splitChar the split char
@@ -282,7 +315,7 @@ public class CommandLineParser {
         // The first word must be alphanumeric, that is a command
         if (!commandWords.get(0).matches("^[a-zA-Z0-9]*$")) {
             throw new CommandLineException(
-                    "first command word is not alphanumeric or is not a command: " + commandWords.get(0));
+                            "first command word is not alphanumeric or is not a command: " + commandWords.get(0));
         }
 
         // Now check that we have a sequence of commands at the beginning
@@ -304,7 +337,7 @@ public class CommandLineParser {
                     currentWordPos++;
                 } else {
                     throw new CommandLineException(
-                            "command argument is not properly formed: " + commandWords.get(currentWordPos));
+                                    "command argument is not properly formed: " + commandWords.get(currentWordPos));
                 }
             } else {
                 // Logic block
@@ -313,7 +346,7 @@ public class CommandLineParser {
                     currentWordPos++;
                 } else {
                     throw new CommandLineException(
-                            "command argument is not properly formed: " + commandWords.get(currentWordPos));
+                                    "command argument is not properly formed: " + commandWords.get(currentWordPos));
                 }
             }
         }
index ae2609e..ddd46c8 100644 (file)
@@ -70,7 +70,25 @@ public class ApexApiResult {
          * The method call failed for another reason such as the method call is not implemented yet
          * on the concept on which it was called.
          */
-        OTHER_ERROR
+        OTHER_ERROR;
+
+        /**
+         * Check if a result is OK.
+         * 
+         * @return true if the result is not OK
+         */
+        public static boolean isOk(final Result result) {
+            return result == Result.SUCCESS || result == Result.FINISHED;
+        }
+
+        /**
+         * Check if a result is not OK.
+         * 
+         * @return true if the result is not OK
+         */
+        public static boolean isNok(final Result result) {
+            return !isOk(result);
+        }
     }
 
     private Result result;
@@ -139,7 +157,7 @@ public class ApexApiResult {
      */
     @XmlAttribute(required = true)
     public boolean isOk() {
-        return result == Result.SUCCESS || result == Result.FINISHED;
+        return Result.isOk(result);
     }
 
     /**
@@ -149,7 +167,7 @@ public class ApexApiResult {
      * @return true, if the result indicates the API operation did not succeed
      */
     public boolean isNok() {
-        return !isOk();
+        return Result.isNok(result);
     }
 
     /**