http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/809d64d7/geode-core/src/main/java/org/apache/geode/management/internal/cli/GfshParser.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/GfshParser.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/GfshParser.java index a1d03e4..1583b24 100755 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/GfshParser.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/GfshParser.java @@ -15,49 +15,19 @@ package org.apache.geode.management.internal.cli; import org.apache.commons.lang.StringUtils; -import org.apache.geode.management.cli.CommandProcessingException; -import org.apache.geode.management.internal.cli.exceptions.CliCommandMultiModeOptionException; -import org.apache.geode.management.internal.cli.exceptions.CliCommandOptionException; -import org.apache.geode.management.internal.cli.exceptions.CliException; -import org.apache.geode.management.internal.cli.exceptions.ExceptionHandler; -import org.apache.geode.management.internal.cli.help.format.NewHelp; -import org.apache.geode.management.internal.cli.help.utils.HelpUtils; -import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.modes.CommandModes; -import org.apache.geode.management.internal.cli.modes.CommandModes.CommandMode; -import org.apache.geode.management.internal.cli.parser.Argument; -import org.apache.geode.management.internal.cli.parser.AvailabilityTarget; -import org.apache.geode.management.internal.cli.parser.CommandTarget; -import org.apache.geode.management.internal.cli.parser.GfshMethodTarget; -import org.apache.geode.management.internal.cli.parser.MethodParameter; -import org.apache.geode.management.internal.cli.parser.Option; -import org.apache.geode.management.internal.cli.parser.OptionSet; -import org.apache.geode.management.internal.cli.parser.Parameter; -import org.apache.geode.management.internal.cli.parser.ParserUtils; -import org.apache.geode.management.internal.cli.parser.SyntaxConstants; -import org.apache.geode.management.internal.cli.parser.preprocessor.PreprocessorUtils; -import org.apache.geode.management.internal.cli.parser.preprocessor.TrimmedInput; -import org.apache.geode.management.internal.cli.shell.Gfsh; -import org.apache.geode.management.internal.cli.util.CLIConsoleBufferUtil; -import org.springframework.shell.core.AbstractShell; +import org.springframework.shell.converters.ArrayConverter; +import org.springframework.shell.core.CommandMarker; import org.springframework.shell.core.Completion; import org.springframework.shell.core.Converter; -import org.springframework.shell.core.MethodTarget; import org.springframework.shell.core.Parser; +import org.springframework.shell.core.SimpleParser; import org.springframework.shell.event.ParseResult; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; +import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; import java.util.logging.Logger; +import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -65,1469 +35,214 @@ import java.util.regex.Pattern; * * @since GemFire 7.0 */ -public class GfshParser implements Parser { +public class GfshParser extends SimpleParser { public static final String LINE_SEPARATOR = System.getProperty("line.separator"); - - // Constants used while finding command targets for help - private final static Short EXACT_TARGET = (short) 0; - private final static Short MATCHING_TARGETS = (short) 1; + public static final String OPTION_VALUE_SPECIFIER = "="; + public static final String VALUE_SEPARATOR = ","; + public static final String ARGUMENT_SEPARATOR = "?"; + public static final String OPTION_SEPARATOR = " "; + public static final String SHORT_OPTION_SPECIFIER = "-"; + public static final String LONG_OPTION_SPECIFIER = "--"; + public static final String COMMAND_DELIMITER = ";"; + public static final String CONTINUATION_CHARACTER = "\\"; // Make use of LogWrapper private static final LogWrapper logWrapper = LogWrapper.getInstance(); + //pattern used to split the userinput with whitespaces except in qutoes (single or double) + private static Pattern + PATTERN = + Pattern.compile("([^\\s\"]*)\"([^\"]*)\"|([^\\s']*)'([^']*)'|[^\\s]+"); // private CliStringResourceBundle cliStringBundle; private CommandManager commandManager; - /** * Used for warning messages */ - // TODO Investigating using GemFire logging. - private final Logger consoleLogger; + private Logger consoleLogger; public GfshParser(CommandManager commandManager) { - // cliStringBundle = new - // CliStringResourceBundle("org/apache/geode/management/internal/cli/i18n/CliStringResourceBundle"); this.commandManager = commandManager; + if (CliUtil.isGfshVM()) { consoleLogger = Logger.getLogger(this.getClass().getCanonicalName()); } else { consoleLogger = logWrapper.getLogger(); } - } - - // ///////////////// Parser interface Methods Start ////////////////////////// - // ////////////////////// Implemented Methods //////////////////////////////// - - /** - * Populates a list of completion candidates. See {@link Parser#complete(String, int, List)} for - * details. - * - * @param buffer - * @param cursor - * @param completionCandidates - * - * @return new cursor position - */ - public int complete(String buffer, int cursor, List<String> completionCandidates) { - final List<Completion> candidates = new ArrayList<Completion>(); - final int result = completeAdvanced(buffer, cursor, candidates); - for (final Completion completion : candidates) { - completionCandidates.add(completion.getValue()); - } - return result; - } - /** - * Populates a list of completion candidates. - * - * @param buffer - * @param cursor - * @param completionCandidates - * - * @return new cursor position - */ - public int completeAdvanced(String buffer, int cursor, List<Completion> completionCandidates) { - // Currently, support for auto-completion - // in between is not supported, only if the - // cursor is at the end - - if (cursor <= buffer.length() - 1 - && !PreprocessorUtils.containsOnlyWhiteSpaces(buffer.substring(cursor)) - || (ParserUtils.contains(buffer, SyntaxConstants.COMMAND_DELIMITER))) { - return cursor; + for (CommandMarker command : commandManager.getCommandMarkers()) { + add(command); } - int desiredCursorPosition = 0; - - try { - TrimmedInput simpleTrim = PreprocessorUtils.simpleTrim(buffer); - desiredCursorPosition += simpleTrim.getNoOfSpacesRemoved(); - List<CommandTarget> targets = locateTargets(simpleTrim.getString()); - if (targets.size() > 1) { - String padding = - desiredCursorPosition != 0 ? ParserUtils.getPadding(desiredCursorPosition) : ""; - // This means that what the user has entered matches - // the beginning of many commands - for (CommandTarget commandTarget : targets) { - completionCandidates - .add(new Completion(padding + commandTarget.getGfshMethodTarget().getKey())); - } - } else { - if (targets.size() == 1) { - CommandTarget commandTarget = targets.get(0); - // Only one command matches but we still have to check - // whether the user has properly entered it or not - if (simpleTrim.getString().length() >= commandTarget.getGfshMethodTarget().getKey() - .length()) { - /* int position = */ - return completeParameters(commandTarget, - desiredCursorPosition + commandTarget.getGfshMethodTarget().getKey().length(), - commandTarget.getGfshMethodTarget().getRemainingBuffer(), cursor, - completionCandidates); - /* - * updateCompletionCandidates(completionCandidates, buffer, position); return 0; - */ - } else { - String padding = - desiredCursorPosition != 0 ? ParserUtils.getPadding(desiredCursorPosition) : ""; - // User has still not entered the command name properly, - // we need to populate the completionCandidates list - completionCandidates - .add(new Completion(padding + commandTarget.getGfshMethodTarget().getKey())); - } - } + List<Converter<?>> converters = commandManager.getConverters(); + for (Converter<?> converter : converters) { + if (converter.getClass().isAssignableFrom(ArrayConverter.class)) { + ArrayConverter arrayConverter = (ArrayConverter) converter; + arrayConverter.setConverters(new HashSet<>(converters)); } - - } catch (IllegalArgumentException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } catch (IllegalAccessException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } catch (InvocationTargetException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } catch (RuntimeException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); + add(converter); } - // Returning 0 for exceptions too. This will break the completors' loop in - // jline.ConsoleReader.complete() & will return false - return 0; } - @SuppressWarnings("unused") - private void updateCompletionCandidates(List<Completion> completionCandidates, String buffer, - int position) { - List<Completion> temp = new ArrayList<Completion>(); - while (completionCandidates.size() > 0) { - temp.add(completionCandidates.remove(0)); - } - for (Completion completion : temp) { - completionCandidates.add(new Completion(buffer.substring(0, position) + completion.getValue(), - completion.getFormattedValue(), completion.getHeading(), completion.getOrder())); - } + public static String convertToSimpleParserInput(String userInput) { + List<String> inputTokens = splitUserInput(userInput); + return getSimpleParserInputFromTokens(inputTokens); } - private int completeParameters(CommandTarget commandTarget, int cursorStart, - String remainingBuffer, int cursor, List<Completion> completionCandidates) { - int desiredCursorPosition = cursorStart; - // Factor for remainingBuffer - boolean sizeReduced = false; - // We need to work modify the flow according to the CliException - // generated. For that we will need a reference to the Exception - // CliException reference - CliCommandOptionException coe = null; - OptionSet userOptionSet = null; - try { - // We need to remove the space which separates command from the - // parameters - if (remainingBuffer.length() > 0) { - remainingBuffer = remainingBuffer.substring(1); - sizeReduced = true; - } - - userOptionSet = commandTarget.getOptionParser().parse(remainingBuffer); - } catch (CliException ce) { - if (ce instanceof CliCommandOptionException) { - coe = (CliCommandOptionException) ce; - coe.setCommandTarget(commandTarget); - userOptionSet = coe.getOptionSet(); - } + public static List<String> splitUserInput(String userInput) { + // first split with whitespaces except in quotes + List<String> splitWithWhiteSpaces = new ArrayList<>(); + Matcher m = PATTERN.matcher(userInput); + while (m.find()) { + splitWithWhiteSpaces.add(m.group()); } - // Contains mandatory options which have not been specified - List<Option> mandatoryOptions = new ArrayList<Option>(); - // Contains non-mandatory options which have not been specified - List<Option> unspecifiedOptions = new ArrayList<Option>(); - // First we need a list to create a list of all the options specified - Map<String, Option> optionsPresentMap = new LinkedHashMap<String, Option>(); - if (userOptionSet != null) { - - // Start with the arguments - String argumentSeparator = " "; - for (Argument argument : commandTarget.getOptionParser().getArguments()) { - if (completionCandidates.size() == 0) { - boolean warning = false; - if (userOptionSet.hasArgument(argument)) { - boolean incrementCursor = true; - // Here we need to get all the possible values for this - // argument - if (getAllPossibleValuesForParameter(completionCandidates, argument, - userOptionSet.getValue(argument), commandTarget.getGfshMethodTarget())) { - // Check whether the list of completionCandidates is - // not empty - if (completionCandidates.size() > 0) { - // First check whether the argument value - // matches with any - // of the completionCandidates - if (perfectMatch(completionCandidates, userOptionSet.getValue(argument))) { - // Remove all the completionCandidates - completionCandidates.clear(); - } else { - modifyCompletionCandidates(completionCandidates, argumentSeparator, - userOptionSet.getValue(argument)); - // For this case also we should not - // increment the - // cursorPosition - if (completionCandidates.size() > 0) { - incrementCursor = false; - } - } - } - } else { - // The completion candidates should be cleared if the Converter has - // populated it with some values - completionCandidates.clear(); - } - if (incrementCursor) { - desiredCursorPosition += - userOptionSet.getValue(argument).length() + argumentSeparator.length(); - } - } else { - if (argument.isRequired()) { - // Here the converter will come in handy - // to get suggestion for arguments - if (getAllPossibleValuesForParameter(completionCandidates, argument, null, - commandTarget.getGfshMethodTarget())) { - if (completionCandidates.size() == 0) { - // Enable warning if nothing is returned - warning = true; - } - } else { - // The completion candidates should be cleared if the Converter has - // populated it with some values - completionCandidates.clear(); - warning = true; - } - } else { - boolean checkForPossibleValues = true; - // This means that the argument is not mandatory - // Now here we need to check whether user wants to - // enter an option. - if (endsWithOptionSpecifiers(userOptionSet.getUserInput()) - || hasOptionSpecified(userOptionSet.getUserInput())) { - // This means options have started, and we - // cannot have arguments after options - // So, we just skip checking for possible - // values - checkForPossibleValues = false; - } - // Just try getting the PossibleValues without - // aiming - if (checkForPossibleValues) { - getAllPossibleValuesForParameter(completionCandidates, argument, null, - commandTarget.getGfshMethodTarget()); - } - } - if (completionCandidates.size() > 0) { - modifyCompletionCandidates(completionCandidates, argumentSeparator, (String[]) null); - } - } - if (warning) { - String argMessage = argument.getArgumentName() - + ((argument.getHelp() != null && !argument.getHelp().equals("")) - ? ": " + argument.getHelp() : ""); - logWarning( - CliStrings.format(CliStrings.GFSHPARSER__MSG__REQUIRED_ARGUMENT_0, argMessage)); - return desiredCursorPosition + userOptionSet.getNoOfSpacesRemoved(); - } - } - argumentSeparator = SyntaxConstants.ARGUMENT_SEPARATOR; - } - if (completionCandidates.size() > 0) { - return desiredCursorPosition + userOptionSet.getNoOfSpacesRemoved(); - } - - // Now process options - - boolean warningValueRequired = false; - Option warningOption = null; - - - - for (Option option : commandTarget.getOptionParser().getOptions()) { - if (userOptionSet.hasOption(option)) { - // We are supporting option synonyms, - // so we need to check that here - for (String string : userOptionSet.getSplit()) { - if (string.startsWith(SyntaxConstants.LONG_OPTION_SPECIFIER)) { - // Remove option prefix - string = StringUtils.removeStart(string, SyntaxConstants.LONG_OPTION_SPECIFIER); - // Remove value specifier - string = StringUtils.removeEnd(string, SyntaxConstants.OPTION_VALUE_SPECIFIER); - if (!string.equals("")) { - if (option.getLongOption().equals(string)) { - // This means that user has entered the whole option and - // Increment desiredCursorPostion by the length of the - // option and the option specifier, including space - desiredCursorPosition += - /* space */1 + SyntaxConstants.LONG_OPTION_SPECIFIER.length() - + option.getLongOption().length(); - break; - - } else { - // This is only possible if the user has - // entered one of the synonyms of the options - // which wasn't displayed initially - for (String optionSynonym : option.getSynonyms()) { - if (optionSynonym.equals(string)) { - // This means that what the user has - // entered is actually a - // synonym for the option - desiredCursorPosition += /* space */1 - + SyntaxConstants.LONG_OPTION_SPECIFIER.length() + optionSynonym.length(); - break; - } - } - } - } - } - } - - optionsPresentMap.put(option.getLongOption(), option); - - // For option value - - if (userOptionSet.hasValue(option)) { - String value = userOptionSet.getValue(option); - boolean valueActuallySpecified = false; - - String valueSeparator = SyntaxConstants.VALUE_SEPARATOR; - if (option.getValueSeparator() != null) { - valueSeparator = option.getValueSeparator(); - } - - // JOpt doesn't maintain trailing comma (separator), hence reading it from buffer. - boolean bufferEndsWithValueSeparator = remainingBuffer.endsWith(valueSeparator); - // Check whether the value assigned to the option is - // actually part of the split array or has been - // assigned using the specifiedDefaultValue attribute - - // userOptionElement can be option name or value of that option. - // E.g. "--opt=val" has elements "opt" & "val" - for (String userOptionElement : userOptionSet.getSplit()) { - if (userOptionElement.equals(value) - || (userOptionElement).equals(value + valueSeparator)) { - valueActuallySpecified = true; - } - } - if (!valueActuallySpecified) { - continue; - } - boolean incrementCursor = true; - boolean considerLastValue = false; - int lengthToBeAdded = 0; - int lastIndexOf = 0; - - // This should only be invoked if we don't have any - // completionCandidates beforeHand - if (completionCandidates.size() == 0) { - // Here also we might need to invoke converter to - // get values apt for the option - if (!endsWithOptionSpecifiers(userOptionSet.getUserInput()) - && getAllPossibleValuesForParameter(completionCandidates, option, value, - commandTarget.getGfshMethodTarget())) { - - // If the value returned by getAllPossibleValues - // is the same as that entered by the - // user we need to remove it from the - // completionCandidates and move forward - - String prefix = ""; - String[] split = ParserUtils.splitValues(value, valueSeparator); - - if (completionCandidates.size() > 0) { - if (PreprocessorUtils.isSyntaxValid(value) && bufferEndsWithValueSeparator) { - // This means that the user wants to - // enter more values, - prefix = valueSeparator; - } else if (perfectMatch(completionCandidates, split)) { - // If the user does not want to enter - // more values, and it matches one - // of the values then we do not - // need to suggest anything for - // this option - completionCandidates.clear(); - considerLastValue = true; - } else if (ParserUtils.contains(value, valueSeparator)) { - prefix = valueSeparator; - } else { - incrementCursor = false; - if (value.startsWith(" ")) { - prefix = " "; - } else if (value.startsWith("\n")) { - prefix = "\n"; - } else { - prefix = SyntaxConstants.OPTION_VALUE_SPECIFIER; - } - } - } - modifyCompletionCandidates(completionCandidates, prefix, - bufferEndsWithValueSeparator, split); - if (completionCandidates.size() == 0) { - incrementCursor = true; - considerLastValue = true; - } - } else { - // The completion candidates should be cleared if the Converter has - // populated it with some values - completionCandidates.clear(); - considerLastValue = true; - } - } else { - // Make everything true - considerLastValue = true; - } - // FIX for: 46265 - // if bufferEndsWithValueSeparator, append a valueSeparator to get the real lastIndexOd - // e.g. Let's say remainingBuffer is: cmd --opt1=val1,val2, - // value would be: cmd --opt1=val1,val2 ---> not there's no comma in the end. - // This doesn't give us the real last index of valueSeparator, hence add extra - // valueSeparator. - lastIndexOf = ParserUtils.lastIndexOf( - bufferEndsWithValueSeparator ? value + valueSeparator : value, valueSeparator); - lengthToBeAdded = - value.substring(0, (lastIndexOf > 0 ? lastIndexOf : value.length())).length(); - // Increment desiredCursorPosition - if (incrementCursor) { - desiredCursorPosition += - /* value specifier length */SyntaxConstants.OPTION_VALUE_SPECIFIER.length() - + lengthToBeAdded - + ((considerLastValue) ? value.length() - lengthToBeAdded : 0); - if (value.endsWith(" ") && considerLastValue) { - desiredCursorPosition--; - } - } - if (completionCandidates.size() == 0) { - if (!PreprocessorUtils.isSyntaxValid(value)) { - return desiredCursorPosition + userOptionSet.getNoOfSpacesRemoved(); - } else { - // Check whether the value ends with - // VALUE_SEPARATOR, - // if yes then we need to return - if (value.endsWith(valueSeparator)) { - return desiredCursorPosition + userOptionSet.getNoOfSpacesRemoved(); - } - } - } - } else { - // Here the converter is useful to invoke - // auto-suggestion, get Values from Converter - if (completionCandidates.size() == 0) { - if (getAllPossibleValuesForParameter(completionCandidates, option, null, - commandTarget.getGfshMethodTarget())) { - if (completionCandidates.size() == 0) { - warningValueRequired = true; - } else { - modifyCompletionCandidates(completionCandidates, - SyntaxConstants.OPTION_VALUE_SPECIFIER, new String[] {null}); - } - } else { - // The completion candidates should be cleared if the Converter - // has populated it with some values - completionCandidates.clear(); - warningValueRequired = true; - } - } - } - } else { - - // As we have reached here, the OptionParser was not able to - // detect anything which proves that the option is present - // So, we check with what the user provided and add only - // that to the list of options to prompt for - - for (String userOptString : userOptionSet.getSplit()) { - // Now to determine whether what the user specified was - // an option, we need to check whether it starts - // with an option specifier - if (userOptString.startsWith(SyntaxConstants.LONG_OPTION_SPECIFIER)) { - // Now remove the option specifier part - userOptString = - StringUtils.removeStart(userOptString, SyntaxConstants.LONG_OPTION_SPECIFIER); - if (option.getLongOption().startsWith(userOptString) && !userOptString.equals("") - && !option.getLongOption().equals(userOptString) - && !optionsPresentMap.containsKey(userOptString)) { - - completionCandidates.add(new Completion( - " " + SyntaxConstants.LONG_OPTION_SPECIFIER + option.getLongOption(), - option.getLongOption(), "", 0)); - } else { - for (String optionSynonym : option.getSynonyms()) { - if (optionSynonym.startsWith(userOptString) && !userOptString.equals("") - && !optionSynonym.equals(userOptString)) { - completionCandidates.add( - new Completion(" " + SyntaxConstants.LONG_OPTION_SPECIFIER + optionSynonym, - optionSynonym, "", 0)); - break; - } - } - } - } - } - - if (completionCandidates.size() == 0) { - if (option.isRequired()) { - mandatoryOptions.add(option); - } else { - unspecifiedOptions.add(option); - } - } - } - if (warningValueRequired/* || warningMultipleValuesNotSupported */) { - warningOption = option; - warningValueRequired = false; - } - } - - // Display warning if something not specified - if (warningOption != null) { - String optionMsg = warningOption.getLongOption() - + ((warningOption.getHelp() != null && !warningOption.getHelp().equals("")) - ? ": " + warningOption.getHelp() : ""); - logWarning( - CliStrings.format(CliStrings.GFSHPARSER__MSG__VALUE_REQUIRED_FOR_OPTION_0, optionMsg)); - - desiredCursorPosition += userOptionSet.getNoOfSpacesRemoved(); - completionCandidates - .add(new Completion(SyntaxConstants.OPTION_VALUE_SPECIFIER, "", null, 0)); - return desiredCursorPosition; - } - - } - - // Calculate the cursor position - int newCursor = desiredCursorPosition - + ((userOptionSet != null) ? userOptionSet.getNoOfSpacesRemoved() : 0); - - String subString = remainingBuffer; - if (newCursor != cursorStart) { - int sizedReducedAdj = sizeReduced ? -1 : 0; - int begin = newCursor + sizedReducedAdj - cursorStart; - subString = remainingBuffer.substring(begin).trim(); - } - - // Exception handling - if (coe != null // hasException - && newCursor < cursor // newCursorIsEarlierThanCursor - && completionCandidates.size() == 0 // zeroCompletionCandidates - && !(PreprocessorUtils.containsOnlyWhiteSpaces(subString) // onlyHasWhiteSpaces - || ((subString.endsWith(SyntaxConstants.LONG_OPTION_SPECIFIER) - && subString.startsWith(SyntaxConstants.LONG_OPTION_SPECIFIER)) // isHypenHyphen - || (subString.startsWith(SyntaxConstants.SHORT_OPTION_SPECIFIER) - && subString.endsWith(SyntaxConstants.SHORT_OPTION_SPECIFIER))))) { // isHyphen - - ExceptionHandler.handleException(coe); - return cursor; - } - - // If nothing has been specified for auto-completion then we need to suggest options - if (completionCandidates.size() == 0) { - if (mandatoryOptions.size() > 0) { - - for (Option option : mandatoryOptions) { - completionCandidates.add( - new Completion(" " + SyntaxConstants.LONG_OPTION_SPECIFIER + option.getLongOption(), - option.getLongOption(), "", 0)); - } + List<String> furtherSplitWithEquals = new ArrayList<>(); + for (String token : splitWithWhiteSpaces) { + // if this token has equal sign, split around the first occurrance of it + int indexOfFirstEqual = token.indexOf('='); + if (indexOfFirstEqual < 0) { + furtherSplitWithEquals.add(token); } else { - // As all the mandatory options have been specified we can prompt the - // user for optional options. - unspecifiedOptions = - getUnspecifiedOptionsWithMode(unspecifiedOptions, commandTarget, optionsPresentMap); - for (Option option : unspecifiedOptions) { - completionCandidates.add( - new Completion(" " + SyntaxConstants.LONG_OPTION_SPECIFIER + option.getLongOption(), - option.getLongOption(), "", 0)); - } - } - } - return newCursor; - } - - private List<Option> getUnspecifiedOptionsWithMode(List<Option> unspecifiedOptions, - CommandTarget commandTarget, Map<String, Option> optionsPresentMap) { - - Collection<CommandMode> cmodes = - CommandModes.getInstance().getCommandModes(commandTarget.getCommandName()); - if (cmodes != null) { - List<Option> filteredList = new ArrayList<Option>(); - - // Populate with default options - CommandMode defaultMode = CommandModes.getInstance() - .getCommandMode(commandTarget.getCommandName(), CommandModes.DEFAULT_MODE); - for (String opt : defaultMode.options) { - for (Option option : unspecifiedOptions) { - if (option.getLongOption().equals(opt)) { - filteredList.add(option); - } - } - } - - // Now add options only for detected command mode - boolean leadOptionFound = false; - for (CommandMode cmd : cmodes) { - if (optionsPresentMap.containsKey(cmd.leadOption)) { - leadOptionFound = true; - for (String opt : cmd.options) { - if (!optionsPresentMap.containsKey(opt)) { - for (Option option : unspecifiedOptions) { - if (option.getLongOption().equals(opt)) { - filteredList.add(option); - } - } - } - } - break; - } - } - - if (leadOptionFound) { - return filteredList; - } - - if (optionsPresentMap.isEmpty()) { - // Here return only lead-option of the command-modes - filteredList.clear(); - for (CommandMode cmd2 : cmodes) { - for (Option option2 : unspecifiedOptions) { - if (option2.getLongOption().equals(cmd2.leadOption)) { - filteredList.add(option2); - } - } - } - return filteredList; - } - return unspecifiedOptions; - } else { - return unspecifiedOptions; - } - } - - private void checkOptionSetForValidCommandModes(OptionSet userOptionSet, - CommandTarget commandTarget) throws CliCommandMultiModeOptionException { - CommandModes modes = CommandModes.getInstance(); - Collection<CommandMode> cmodes = modes.getCommandModes(commandTarget.getCommandName()); - - if (cmodes != null) { - CommandMode defaultMode = - modes.getCommandMode(commandTarget.getCommandName(), CommandModes.DEFAULT_MODE); - Map<String, Option> userOptions = new HashMap<String, Option>(); - Map<String, CommandMode> loToModeMap = new HashMap<String, CommandMode>(); - for (Option option : commandTarget.getOptionParser().getOptions()) { - if (userOptionSet.hasOption(option)) { - userOptions.put(option.getLongOption(), option); - } - } - - List<String> leadOptionList = new ArrayList<String>(); - for (CommandMode cmd : cmodes) { - loToModeMap.put(cmd.leadOption, cmd); - if (userOptions.containsKey(cmd.leadOption)) { - leadOptionList.add(cmd.leadOption); - } - - if (leadOptionList.size() > 1) { - - StringBuilder sb = new StringBuilder(); - for (String leadOption : leadOptionList) { - sb.append(loToModeMap.get(leadOption).name).append(","); - } - throw new CliCommandMultiModeOptionException(commandTarget, - userOptions.get(cmd.leadOption), sb.toString(), - CliCommandMultiModeOptionException.MULTIPLE_LEAD_OPTIONS); + String left = token.substring(0, indexOfFirstEqual); + String right = token.substring(indexOfFirstEqual + 1); + if (left.length() > 0) { + furtherSplitWithEquals.add(left); } - } - - if (leadOptionList.size() == 1) { - CommandMode modeDetected = loToModeMap.get(leadOptionList.get(0)); - for (Option opt : userOptions.values()) { - // Check only for non-default options, default options are allowed with any other mode - if (!isDefaultOption(opt.getLongOption(), defaultMode)) { - boolean isOptionFromDetectedMode = false; - if (modeDetected.options.length > 0) { - for (String commandOpt : modeDetected.options) { - if (commandOpt.equals(opt.getLongOption())) { - isOptionFromDetectedMode = true; - } - } - if (!isOptionFromDetectedMode) { - throw new CliCommandMultiModeOptionException(commandTarget, opt, - opt.getLongOption(), - CliCommandMultiModeOptionException.OPTIONS_FROM_MULTIPLE_MODES); - } - } - } + if (right.length() > 0) { + furtherSplitWithEquals.add(right); } } } + return furtherSplitWithEquals; } - private boolean isDefaultOption(String longOption, CommandMode commandMode) { - for (String str : commandMode.options) { - if (longOption.equals(str)) { - return true; - } - } - return false; - } - - private boolean endsWithOptionSpecifiers(String userInput) { - userInput = userInput.trim(); - if (userInput.endsWith(" " + SyntaxConstants.LONG_OPTION_SPECIFIER) - || userInput.endsWith(" " + SyntaxConstants.SHORT_OPTION_SPECIFIER)) { - return true; - } else { - return false; - } - } - - /* - * Verifies whether the userInput has any one of the following: --some-opt --s --some-opt=some-val - * --something-else - */ - private boolean hasOptionSpecified(String userInput) { - userInput = userInput.trim(); - return Pattern.matches("^(.*)(-+)(\\w+)(.*)$", userInput); - } + private static String getSimpleParserInputFromTokens(List<String> tokens) { + // make a copy of the input since we need to do add/remove + List<String> inputTokens = new ArrayList<>(); - private String getSystemProvidedValue(Parameter parameter) { - if (parameter.isSystemProvided()) { - // TODO fetch from system properties - // Assume value is null for now. - return null; - } else { - return null; - } - } + // get the --J arguments from the list of tokens + int firstJIndex = -1; + List<String> jArguments = new ArrayList<>(); - private boolean perfectMatch(List<Completion> completionCandidates, String... argumentValue) { - // Here only the last value should match one of the - // completionCandidates - if (argumentValue.length > 0) { - for (Completion completion : completionCandidates) { - if (completion.getValue().equals(argumentValue[argumentValue.length - 1])) { - return true; + for (int i = 0; i < tokens.size(); i++) { + String token = tokens.get(i); + if ("--J".equals(token)) { + if (firstJIndex < 1) { + firstJIndex = i; } - } - } - return false; - } + i++; - private void modifyCompletionCandidates(List<Completion> completionCandidates, String prefix, - String... existingData) { - modifyCompletionCandidates(completionCandidates, prefix, false, existingData); - } - - private void modifyCompletionCandidates(List<Completion> completionCandidates, String prefix, - boolean endsWithValueSeparator, String... existingData) { - List<Completion> temp = new ArrayList<Completion>(); - while (completionCandidates.size() > 0) { - temp.add(completionCandidates.remove(0)); - } - for (Completion completion : temp) { - boolean includeCompletion = true; - String value = completion.getValue(); - if (existingData != null) { - for (String string : existingData) { - if (string != null) { - // Check whether that value matches any of the - // existingData - // If it matches any one of existing data then we do not - // need to include it in the list of completion - // candidates - if (value.equals(string)) { - includeCompletion = false; - } + if (i < tokens.size()) { + String jArg = tokens.get(i); + if (jArg.charAt(0) == '"' || jArg.charAt(0) == '\'') { + jArg = jArg.substring(1, jArg.length() - 1); } - } - if (includeCompletion) { - if (existingData[existingData.length - 1] != null - && (!value.startsWith(existingData[existingData.length - 1]) - && !endsWithValueSeparator)) { - includeCompletion = false; + if (jArg.length() > 0) { + jArguments.add(jArg); } } - } - if (includeCompletion) { - // Also we only need to check with the last string of - // existingData - // whether the completion value starts with it. - completionCandidates - .add(new Completion(prefix + completion.getValue(), completion.getValue(), "", 0)); - } - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - private boolean getAllPossibleValuesForParameter(List<Completion> completionCandidates, - Parameter parameter, String existingData, GfshMethodTarget gfshMethodTarget) { - Converter<?> converter = parameter.getConverter(); - // Check if any new converter is available which - // satisfies the requirements for this argument - if (converter == null) { - parameter.setConverter( - commandManager.getConverter(parameter.getDataType(), parameter.getContext())); - converter = parameter.getConverter(); - } - // If still we do not have any matching converters, we return - if (converter == null) { - return false; - } else { - // Now pass the getAllPossibleValues function of Converter interface - // all the required parameters - - // Check whether it is a MultipleValueConverter - String valueSeparator = SyntaxConstants.VALUE_SEPARATOR; - if (parameter instanceof Option && ((Option) parameter).getValueSeparator() != null) { - valueSeparator = ((Option) parameter).getValueSeparator(); - } - if (converter instanceof MultipleValueConverter) { - ((MultipleValueConverter) converter).getAllPossibleValues(completionCandidates, - parameter.getDataType(), ParserUtils.splitValues(existingData, valueSeparator), - parameter.getContext(), - new MethodTarget(gfshMethodTarget.getMethod(), gfshMethodTarget.getTarget(), - gfshMethodTarget.getRemainingBuffer(), gfshMethodTarget.getKey())); } else { - converter.getAllPossibleValues(completionCandidates, parameter.getDataType(), existingData, - parameter.getContext(), - new MethodTarget(gfshMethodTarget.getMethod(), gfshMethodTarget.getTarget(), - gfshMethodTarget.getRemainingBuffer(), gfshMethodTarget.getKey())); + inputTokens.add(token); } } - if (completionCandidates.size() > 0) { - return true; - } else { - return false; - } - } - - /** - * - */ - public ParseResult parse(String userInput) { - GfshParseResult parseResult = null; - // First remove the trailing white spaces - userInput = StringUtils.stripEnd(userInput, null); - if ((ParserUtils.contains(userInput, SyntaxConstants.COMMAND_DELIMITER) - && StringUtils.endsWithIgnoreCase(userInput, SyntaxConstants.COMMAND_DELIMITER))) { - userInput = StringUtils.removeEnd(userInput, SyntaxConstants.COMMAND_DELIMITER); - } - - try { - boolean error = false; - CliCommandOptionException coe = null; - List<CommandTarget> targets = locateTargets(ParserUtils.trimBeginning(userInput), false); - if (targets.size() > 1) { - if (userInput.length() > 0) { - handleCondition( - CliStrings.format( - CliStrings.GFSHPARSER__MSG__AMBIGIOUS_COMMAND_0_FOR_ASSISTANCE_USE_1_OR_HINT_HELP, - new Object[] {userInput, AbstractShell.completionKeys}), - CommandProcessingException.COMMAND_NAME_AMBIGUOUS, userInput); - } - } else { - if (targets.size() == 1) { - OptionSet parse = null; - List<MethodParameter> parameters = new ArrayList<MethodParameter>(); - Map<String, String> paramValMap = new HashMap<String, String>(); - CommandTarget commandTarget = targets.get(0); - GfshMethodTarget gfshMethodTarget = commandTarget.getGfshMethodTarget(); - preConfigureConverters(commandTarget); - - try { - parse = commandTarget.getOptionParser().parse(gfshMethodTarget.getRemainingBuffer()); - } catch (CliException ce) { - if (ce instanceof CliCommandOptionException) { - coe = (CliCommandOptionException) ce; - coe.setCommandTarget(commandTarget); - parse = coe.getOptionSet(); - error = true; - } - } - - try { - checkOptionSetForValidCommandModes(parse, commandTarget); - } catch (CliCommandMultiModeOptionException ce) { - error = true; - coe = ce; - } - error = processArguments(parse, commandTarget, paramValMap, parameters, error); - // TODO: next call throws when space before closing " - error = processOptions(parse, commandTarget, paramValMap, parameters, error); - - if (!error) { - Object[] methodParameters = new Object[parameters.size()]; - for (MethodParameter parameter : parameters) { - methodParameters[parameter.getParameterNo()] = parameter.getParameter(); - } - parseResult = - new GfshParseResult(gfshMethodTarget.getMethod(), gfshMethodTarget.getTarget(), - methodParameters, userInput, commandTarget.getCommandName(), paramValMap); - } else { - if (coe != null) { - logWrapper.fine("Handling exception: " + coe.getMessage()); - ExceptionHandler.handleException(coe); // TODO: this eats exception that would make it - // easier to debug GemfireDataCommandsDUnitTest - // ExceptionHandler.handleException() only logs it on console. - // When on member, we need to handle this. - if (!CliUtil.isGfshVM()) { - handleCondition(CliStrings - .format(CliStrings.GFSHPARSER__MSG__INVALID_COMMAND_STRING_0, userInput), coe, - CommandProcessingException.COMMAND_INVALID, userInput); - } - } - } - - } else { - String message = - CliStrings.format(CliStrings.GFSHPARSER__MSG__COMMAND_0_IS_NOT_VALID, userInput); - CommandTarget commandTarget = locateExactMatchingTarget(userInput); - if (commandTarget != null) { - String commandName = commandTarget.getCommandName(); - AvailabilityTarget availabilityIndicator = commandTarget.getAvailabilityIndicator(); - message = CliStrings.format(CliStrings.GFSHPARSER__MSG__0_IS_NOT_AVAILABLE_REASON_1, - new Object[] {commandName, availabilityIndicator.getAvailabilityDescription()}); - } - handleCondition(message, CommandProcessingException.COMMAND_INVALID_OR_UNAVAILABLE, - userInput); + // concatenate the remaining tokens with space + StringBuffer rawInput = new StringBuffer(); + // firstJIndex must be less than or equal to the length of the inputToken + for (int i = 0; i <= inputTokens.size(); i++) { + // stick the --J arguments in the orginal first --J position + if (i == firstJIndex) { + rawInput.append("--J "); + if (jArguments.size() > 0) { + rawInput.append("\"").append(StringUtils.join(jArguments, ",")).append("\" "); } } - } catch (IllegalArgumentException e1) { - logWrapper.warning(CliUtil.stackTraceAsString(e1)); - } catch (IllegalAccessException e1) { - logWrapper.warning(CliUtil.stackTraceAsString(e1)); - } catch (InvocationTargetException e1) { - logWrapper.warning(CliUtil.stackTraceAsString(e1)); - } - return parseResult; - } - - // Pre-configure the converters so that we can test against them when parsing the command line - private void preConfigureConverters(CommandTarget commandTarget) { - for (Option option : commandTarget.getOptionParser().getOptions()) { - Converter<?> converter = option.getConverter(); - if (converter == null) { - option.setConverter(commandManager.getConverter(option.getDataType(), option.getContext())); - converter = option.getConverter(); + // then add the next inputToken + if (i < inputTokens.size()) { + rawInput.append(inputTokens.get(i)).append(" "); } } - for (Argument argument : commandTarget.getOptionParser().getArguments()) { - Converter<?> converter = argument.getConverter(); - if (converter == null) { - argument.setConverter( - commandManager.getConverter(argument.getDataType(), argument.getContext())); - converter = argument.getConverter(); - } - } - } - - private boolean processOptions(OptionSet parse, CommandTarget commandTarget, - Map<String, String> paramValMap, List<MethodParameter> parameters, boolean errorState) { - boolean error = errorState; - for (Option option : commandTarget.getOptionParser().getOptions()) { - String value = null; - if (parse.hasOption(option)) { - if (parse.hasValue(option)) { - value = parse.getValue(option); - } - if (value == null) { - handleCondition( - CliStrings.format(CliStrings.GFSHPARSER__MSG__VALUE_REQUIRED_FOR_OPTION_0, - option.getLongOption()), - CommandProcessingException.OPTION_VALUE_REQUIRED, option.getLongOption()); - logWrapper.fine("Value required for Parameter " + option.getLongOption()); - error = true; - } - } else { - if (option.isRequired()) { - handleCondition( - CliStrings.format(CliStrings.GFSHPARSER__MSG__COMMAND_OPTION_0_IS_REQUIRED_USE_HELP, - option.getLongOption()), - CommandProcessingException.REQUIRED_OPTION_MISSING, option.getLongOption()); - logWrapper.fine("Required Parameter " + option.getLongOption()); - error = true; - } else { - // Try to get the unspecifiedDefaultValue for the - // option - value = option.getUnspecifiedDefaultValue(); - if (value == null) { - // Now try the system provide value - value = getSystemProvidedValue(option); - } - } - } - - String valueSeparator = SyntaxConstants.VALUE_SEPARATOR; - if (option.getValueSeparator() != null) { - valueSeparator = option.getValueSeparator(); - } - - Object object = getConversionObject(option.getConverter(), value, option.getDataType(), - option.getContext(), valueSeparator); - // Check if conversion fails - if (value != null && object == null) { - handleCondition( - CliStrings.format(CliStrings.GFSHPARSER__MSG__VALUE_0_IS_NOT_APPLICABLE_FOR_1, - new Object[] {value.trim(), option.getLongOption()}), - CommandProcessingException.OPTION_VALUE_INVALID, option.getLongOption() + "=" + value); - logWrapper - .fine("Value \"" + value.trim() + "\" is not applicable for " + option.getLongOption()); - error = true; - } - parameters.add(new MethodParameter(object, option.getParameterNo())); - paramValMap.put(option.getLongOption(), value); - } - return error; + return rawInput.toString().trim(); } - private boolean processArguments(OptionSet parse, CommandTarget commandTarget, - Map<String, String> paramValMap, List<MethodParameter> parameters, boolean errorState) { - boolean error = errorState; - for (Argument argument : commandTarget.getOptionParser().getArguments()) { - String value = null; + @Override + public ParseResult parse(String userInput) { + String rawInput = convertToSimpleParserInput(userInput); - if (parse.hasArgument(argument)) { - value = parse.getValue(argument); - } else { - if (argument.isRequired()) { - handleCondition( - CliStrings.format(CliStrings.GFSHPARSER__MSG__COMMAND_ARGUMENT_0_IS_REQUIRED_USE_HELP, - argument.getArgumentName()), - CommandProcessingException.REQUIRED_ARGUMENT_MISSING, argument.getArgumentName()); - logWrapper.fine("Required Argument " + argument.getArgumentName()); - error = true; - } else { - // try to get unspecifiedDefaultValue for - // the argument - value = argument.getUnspecifiedDefaultValue(); - if (value == null) { - // Now try the system provided value - value = getSystemProvidedValue(argument); - } - } + // User SimpleParser to parse the input + ParseResult result = super.parse(rawInput); - } - - Object conversionObject = getConversionObject(argument.getConverter(), value, - argument.getDataType(), argument.getContext(), SyntaxConstants.VALUE_SEPARATOR); - if (value != null && conversionObject == null) { - handleCondition( - CliStrings.format(CliStrings.GFSHPARSER__MSG__VALUE_0_IS_NOT_APPLICABLE_FOR_1, - new Object[] {value.trim(), argument.getArgumentName()}), - CommandProcessingException.ARGUMENT_INVALID, argument.getArgumentName() + "=" + value); - logWrapper.fine("Value '" + value.trim() + "' not applicable for argument: " - + argument.getArgumentName()); - error = true; - } else { - parameters.add(new MethodParameter(conversionObject, argument.getParameterNo())); - paramValMap.put(argument.getArgumentName(), value); - } + if (result != null) { + return new GfshParseResult(result.getMethod(), result.getInstance(), result.getArguments(), + userInput); } - return error; - } - @SuppressWarnings({"rawtypes", "unchecked"}) - private Object getConversionObject(Converter<?> converter, String string, Class<?> dataType, - String context, String valueSeparator) { - - try { - if (converter != null && converter instanceof MultipleValueConverter) { - return ((MultipleValueConverter) converter).convertFromText( - ParserUtils.splitValues(((string != null) ? string.trim() : null), valueSeparator), - dataType, context); - } - - // Remove outer single or double quotes if found - boolean hasDoubleQuotes = string.startsWith("\"") && string.endsWith("\""); - boolean hasSingleQuotes = string.startsWith("\'") && string.endsWith("\'"); - - while (string != null && (hasDoubleQuotes || hasSingleQuotes)) { - string = string.substring(1, string.length() - 1); - hasDoubleQuotes = string.startsWith("\"") && string.endsWith("\""); - hasSingleQuotes = string.startsWith("\'") && string.endsWith("\'"); - } - - if (converter != null) { - return converter.convertFromText((string != null) ? string.trim() : null, dataType, - context); - } - - // TODO consider multiple value case for primitives - if (string != null) { - if (String.class.isAssignableFrom(dataType)) { - return string.trim(); - } else if (Byte.class.isAssignableFrom(dataType) || byte.class.isAssignableFrom(dataType)) { - return Integer.parseInt(string); - } else if (Short.class.isAssignableFrom(dataType) - || short.class.isAssignableFrom(dataType)) { - return Integer.parseInt(string); - } else if (Boolean.class.isAssignableFrom(dataType) - || boolean.class.isAssignableFrom(dataType)) { - return Integer.parseInt(string); - } else if (Integer.class.isAssignableFrom(dataType) - || int.class.isAssignableFrom(dataType)) { - return Integer.parseInt(string); - } else if (Long.class.isAssignableFrom(dataType) || long.class.isAssignableFrom(dataType)) { - return Long.parseLong(string); - } else if (Float.class.isAssignableFrom(dataType) - || float.class.isAssignableFrom(dataType)) { - return Float.parseFloat(string); - } else if (Double.class.isAssignableFrom(dataType) - || double.class.isAssignableFrom(dataType)) { - return Double.parseDouble(string); - } else if (Character.class.isAssignableFrom(dataType) - || char.class.isAssignableFrom(dataType)) { - if (string.length() == 1) { - string.charAt(0); - } else { - // FIXME Use a constant here - return '0'; - } - } - } - } catch (Exception e) { - // TODO add logging - // Do nothing, just return null - } return null; } - private List<CommandTarget> locateTargets(String userInput) - throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - return locateTargets(userInput, true); - } - + @Override + public int completeAdvanced(String userInput, int cursor, final List<Completion> candidates) { + cursor = userInput.length(); + List<String> inputTokens = splitUserInput(userInput); + String lastToken = inputTokens.get(inputTokens.size() - 1); - private List<CommandTarget> locateTargets(String userInput, boolean matchIncomplete) - throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - List<CommandTarget> commandTargets = new ArrayList<CommandTarget>(); - Map<String, CommandTarget> commands = commandManager.getCommands(); - // Now we need to locate the CommandTargets from the entries in the map - for (String commandName : commands.keySet()) { - if (userInput.startsWith(commandName)) { - // This means that the user has entered the command - CommandTarget commandTarget = commands.get(commandName); - if (isAvailable(commandTarget, commandName)) { - String remainingBuffer = StringUtils.removeStart(userInput, commandName); - if (remainingBuffer.length() == 0 || remainingBuffer.startsWith(" ") - || remainingBuffer.startsWith(GfshParser.LINE_SEPARATOR)) { - // We need to duplicate with a new MethodTarget as this - // parser will be used in a concurrent execution environment - if (!commandTargets.contains(commandTarget)) { - // This test is necessary as the command may have similar - // synonyms or which are prefix for the command - commandTargets.add(commandTarget.duplicate(commandName, remainingBuffer)); - } - } - } - } else if (matchIncomplete && commandName.startsWith(userInput)) { - // This means that the user is yet to enter the command properly - CommandTarget commandTarget = commands.get(commandName); - if (isAvailable(commandTarget, commandName)) { - // We need to duplicate with a new MethodTarget as this - // parser will be used in a concurrent execution environment - if (!commandTargets.contains(commandTarget)) { - // This test is necessary as the command may have similar - // synonyms or which are prefix for the command - commandTargets.add(commandTarget.duplicate(commandName)); - } - } - } + // trying to get candidates using the converted input and the candidateBeginAt cursor position + String buffer = getSimpleParserInputFromTokens(inputTokens); + int candidateBeginAt = buffer.length() - lastToken.length(); + List<Completion> potentials = getCandidates(buffer, candidateBeginAt); + if (potentials.size() == 0 && !lastToken.startsWith("--")) { + // if last token is not an option, add "--" to it and retry + candidateBeginAt = buffer.length() + 1; + potentials = getCandidates(buffer + " --", candidateBeginAt); + } else if (potentials.size() == 1 && potentials.get(0).getValue().equals(lastToken)) { + // if the candidate is exactly the same as the last token, add a space to it and retry + potentials = getCandidates(buffer + " ", candidateBeginAt); } - return commandTargets; - } - - // TODO - Abhishek - create an inner CommandTargetLocater instead of multiple - // methods like these. - private CommandTarget locateExactMatchingTarget(final String userInput)// exact matching - throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - CommandTarget commandTarget = null; - - Map<String, CommandTarget> commandTargetsMap = commandManager.getCommands(); - // Reverse sort the command names because we should start from longer names - // E.g. Consider commands "A", "A B" & user input as "A B --opt1=val1" - // In this case, "A B" is the most probable match & should be matched first - // which can be achieved by reversing natural order of sorting. - Set<String> commandNamesReverseSorted = new TreeSet<String>(Collections.reverseOrder()); - commandNamesReverseSorted.addAll(commandTargetsMap.keySet()); - // Now we need to locate the CommandTargets from the entries in the map - for (final String commandName : commandNamesReverseSorted) { - if (userInput.startsWith(commandName) && commandWordsMatch(userInput, commandName)) { - // This means that the user has entered the command & name matches exactly - commandTarget = commandTargetsMap.get(commandName); - if (commandTarget != null) { - String remainingBuffer = StringUtils.removeStart(userInput, commandName); - commandTarget = commandTarget.duplicate(commandName, remainingBuffer); - break; - } + // If we have a candidate, need to determine what's the returned cursor should be + if (potentials.size() > 0) { + // usually we want to begin the cursor at candidateBeginCursor, but since we consolidated + // --J options into one, and added quotes around we need to consider the length difference + // between userInput and the converted input + cursor = candidateBeginAt + (userInput.trim().length() - buffer.length()); + // our cursor can't be further than whatever user has typed in + if (cursor > userInput.length()) { + cursor = userInput.length(); } } - return commandTarget; - } - - private static boolean commandWordsMatch(final String userInput, final String commandName) { - boolean commandWordsMatch = true; - - String[] commandNameWords = commandName.split(" "); - String[] userInputWords = userInput.split(" "); - // commandName is fixed & hence should have less or same number of words as - // the user input. E.g. "create disk-store" should match with - // "create disk-store --name=xyz" but not with "create disk store" - if (commandNameWords.length <= userInputWords.length) { - // if both have length zero, words can be considered to be matching. - for (int i = 0; i < commandNameWords.length; i++) { - if (!commandNameWords[i].equals(userInputWords[i])) { - commandWordsMatch = false; - break; - } - } - } else { - commandWordsMatch = false; - } - - return commandWordsMatch; - } - - - private Map<String, CommandTarget> getRequiredCommandTargets(Set<String> requiredCommands) { - Map<String, CommandTarget> existingCommands = commandManager.getCommands(); - Map<String, CommandTarget> requiredCommandsMap = existingCommands; - - if (requiredCommands != null && !requiredCommands.isEmpty()) { - requiredCommandsMap = new TreeMap<String, CommandTarget>(); - for (String commandName : requiredCommands) { - CommandTarget commandTarget = existingCommands.get(commandName); - if (commandTarget != null) { - requiredCommandsMap.put(commandName, commandTarget); - } - } - } - - return requiredCommandsMap; - } - - private Map<Short, List<CommandTarget>> findMatchingCommands(String userSpecifiedCommand, - Set<String> requiredCommands) - throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - - Map<String, CommandTarget> existingCommands = getRequiredCommandTargets(requiredCommands); - CommandTarget exactCommandTarget = existingCommands.get(userSpecifiedCommand); - - // 1. First find exactly matching commands. - List<CommandTarget> exactCommandTargets = Collections.emptyList(); - if (exactCommandTarget != null) { - // This means that the user has entered the command - // NOTE: we are not skipping synonym here. - exactCommandTargets = Collections.singletonList(exactCommandTarget); - } - - // 2. Now find command names that start with 'userSpecifiedCommand' - List<CommandTarget> possibleCommandTargets = new ArrayList<CommandTarget>(); - // Now we need to locate the CommandTargets from the entries in the map - for (Map.Entry<String, CommandTarget> entry : existingCommands.entrySet()) { - CommandTarget commandTarget = entry.getValue(); - String commandName = commandTarget.getCommandName(); - // This check is done to remove commands that are synonyms as - // CommandTarget.getCommandName() will return name & not a synonym - if (entry.getKey().equals(commandName)) { - if (commandName.startsWith(userSpecifiedCommand) - && !commandTarget.equals(exactCommandTarget)) { - // This means that the user is yet to enter the command properly - possibleCommandTargets.add(commandTarget); - } - } - } - - Map<Short, List<CommandTarget>> commandTargetsArr = new HashMap<Short, List<CommandTarget>>(); - commandTargetsArr.put(EXACT_TARGET, exactCommandTargets); - commandTargetsArr.put(MATCHING_TARGETS, possibleCommandTargets); - return commandTargetsArr; - } - - - private boolean isAvailable(CommandTarget commandTarget, String commandName) - throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { - AvailabilityTarget availabilityIndicator = commandTarget.getAvailabilityIndicator(); - if (availabilityIndicator == null) { - availabilityIndicator = commandManager.getAvailabilityIndicator(commandName); - commandTarget.setAvailabilityIndicator(availabilityIndicator); - } - return commandTarget.isAvailable(); - } - - public List<String> obtainHelpCommandNames(String userInput) { - List<String> commandNames = new ArrayList<String>(); - - try { - if (userInput == null) { - userInput = ""; - } - - List<CommandTarget> commandTargets = new ArrayList<CommandTarget>(); - Map<Short, List<CommandTarget>> matchingCommandsMap = findMatchingCommands(userInput, null); - commandTargets.addAll(matchingCommandsMap.get(EXACT_TARGET)); - commandTargets.addAll(matchingCommandsMap.get(MATCHING_TARGETS)); - - for (CommandTarget commandTarget : commandTargets) { - commandNames.add(commandTarget.getCommandName()); - } - } catch (IllegalArgumentException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } catch (IllegalAccessException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } catch (InvocationTargetException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } - - return commandNames; - } - - public String obtainHelp(String userInput, Set<String> commandNames) { - final boolean withinShell = commandNames == null || commandNames.isEmpty(); - final String appName = withinShell ? "" : HelpUtils.EXE_PREFIX_FOR_EXTERNAL_HELP; - - StringBuilder helpText = new StringBuilder(); - try { - if (userInput == null) { - userInput = ""; - } - - Map<Short, List<CommandTarget>> matchingCommandsMap = - findMatchingCommands(userInput, commandNames); - List<CommandTarget> exactCommandTargets = matchingCommandsMap.get(EXACT_TARGET); - List<CommandTarget> matchingCommandTargets = matchingCommandsMap.get(MATCHING_TARGETS); - matchingCommandsMap.clear(); - - if (exactCommandTargets.isEmpty() && matchingCommandTargets.isEmpty()) { - // No matching commands - helpText.append(CliStrings.GFSHPARSER__MSG__NO_MATCHING_COMMAND) - .append(GfshParser.LINE_SEPARATOR); - } else { - if (exactCommandTargets.size() == 1) { - helpText.append(obtainCommandSpecificHelp(exactCommandTargets.get(0), withinShell)); - if (!matchingCommandTargets.isEmpty()) { - helpText.append(GfshParser.LINE_SEPARATOR); - helpText.append(CliStrings - .format(CliStrings.GFSHPARSER__MSG__OTHER_COMMANDS_STARTING_WITH_0_ARE, userInput)); - for (int i = 0; i < matchingCommandTargets.size(); i++) { - CommandTarget commandTarget = matchingCommandTargets.get(i); - helpText.append(commandTarget.getCommandName()); - if (i < matchingCommandTargets.size() - 1) { - helpText.append(", "); - } - } - helpText.append(GfshParser.LINE_SEPARATOR); - } - } else { - List<CommandTarget> commandTargets = new ArrayList<CommandTarget>(); - commandTargets.addAll(exactCommandTargets); - commandTargets.addAll(matchingCommandTargets); - for (CommandTarget commandTarget : commandTargets) { - String availability = commandTarget.isAvailable() ? HelpUtils.HELP__COMMAND_AVAILABLE - : HelpUtils.HELP__COMMAND_NOTAVAILABLE; - // Many matching commands, provide one line description - helpText.append(commandTarget.getCommandName()); - if (withinShell) { - helpText.append(" (").append(availability).append(")"); - } - helpText.append(GfshParser.LINE_SEPARATOR); - helpText.append(Gfsh.wrapText(commandTarget.getCommandHelp(), 1)) - .append(GfshParser.LINE_SEPARATOR); - } - helpText.append(GfshParser.LINE_SEPARATOR); - - if (withinShell) { - helpText - .append(Gfsh.wrapText( - CliStrings.format( - CliStrings.GFSHPARSER__MSG__USE_0_HELP_COMMAND_TODISPLAY_DETAILS, appName), - 0)) - .append(GfshParser.LINE_SEPARATOR); - helpText.append(Gfsh.wrapText( - CliStrings.format(CliStrings.GFSHPARSER__MSG__HELP_CAN_ALSO_BE_OBTAINED_BY_0_KEY, - AbstractShell.completionKeys), - 0)); - } - } - } - } catch (IllegalArgumentException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } catch (IllegalAccessException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } catch (InvocationTargetException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } - return helpText.toString(); - } - - private String obtainCommandSpecificHelp(CommandTarget commandTarget, boolean withinShell) { - NewHelp newHelp = HelpUtils.getNewHelp(commandTarget, withinShell); - return newHelp.toString(); + candidates.addAll(potentials); + return cursor; } - public List<String> getCommandNames(String string) { - List<String> commandNames = new ArrayList<String>(); - try { - if (string == null) { - string = ""; - } - List<CommandTarget> locateTargets = locateTargets(string); - for (CommandTarget commandTarget : locateTargets) { - String key = commandTarget.getGfshMethodTarget().getKey(); - if (key.startsWith(string)) { - commandNames.add(key); - } - } - } catch (IllegalArgumentException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } catch (IllegalAccessException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } catch (InvocationTargetException e) { - logWrapper.warning(CliUtil.stackTraceAsString(e)); - } - return commandNames; - } - - // ///////////////// Parser interface Methods End ////////////////////////// + /** + * @param buffer use the buffer to find the completion candidates + * @param candidateBeginAt strip the found candidates from this position + * + * Note the cursor maynot be the size the buffer + */ + public List<Completion> getCandidates(String buffer, int candidateBeginAt) { + List<Completion> candidates = new ArrayList<>(); - private void handleCondition(String message, int errorType, Object errorData) { - this.handleCondition(message, null, errorType, errorData); - } + // always pass the buffer length as the cursor position for simplicity purpose + super.completeAdvanced(buffer, buffer.length(), candidates); - private void handleCondition(String message, Throwable th, int errorType, Object errorData) { - if (CliUtil.isGfshVM()) { - logWarning(message); // TODO - Abhishek add throwable if debug is ON - } else { - if (th != null) { - throw new CommandProcessingException(message + ": " + th.getMessage(), errorType, - errorData); + // stripp off the beginning part of the candidates from the cursor point + // starting from the end, since we need to remove and add + for (int i = candidates.size() - 1; i >= 0; i--) { + Completion candidate = candidates.remove(i); + // we only need the part after the current cursor + String suggest = candidate.getValue().substring(candidateBeginAt); + // this suggested value usually ends with a space because it's assuming it's using + // "--option argment" format. trim the ending space so that we can easily add the "="sign + if (suggest.endsWith(" ")) { + suggest = suggest.substring(0, suggest.length() - 1); } - throw new CommandProcessingException(message, errorType, errorData); - } - } - - private void logWarning(String message) { - if (canLogToConsole()) { - consoleLogger - .warning(CLIConsoleBufferUtil.processMessegeForExtraCharactersFromConsoleBuffer(message)); - } else { - Gfsh.println(message); + candidates.add(new Completion(suggest)); } + return candidates; } - private boolean canLogToConsole() { - Gfsh gfsh = Gfsh.getCurrentInstance(); - return gfsh != null && !gfsh.isHeadlessMode() && consoleLogger != null; - } - - // private void logInfo(String message) { - // if (consoleLogger != null) { - // consoleLogger.info(message); - // } else { - // Gfsh.println(message); - // } - // } }
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/809d64d7/geode-core/src/main/java/org/apache/geode/management/internal/cli/Launcher.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/Launcher.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/Launcher.java index fc0427e..7dd42c4 100755 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/Launcher.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/Launcher.java @@ -14,22 +14,19 @@ */ package org.apache.geode.management.internal.cli; -import java.io.IOException; -import java.io.PrintStream; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import org.apache.geode.internal.GemFireVersion; import org.apache.geode.internal.PureJavaMode; import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.parser.SyntaxConstants; import org.apache.geode.management.internal.cli.shell.Gfsh; import org.apache.geode.management.internal.cli.shell.GfshConfig; import org.apache.geode.management.internal.cli.shell.jline.GfshHistory; - import org.springframework.shell.core.ExitShellRequest; +import java.io.IOException; +import java.io.PrintStream; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import joptsimple.OptionException; import joptsimple.OptionParser; import joptsimple.OptionSet; @@ -84,28 +81,14 @@ public final class Launcher { private static final String MSG_INVALID_COMMAND_OR_OPTION = "Invalid command or option : {0}." + GfshParser.LINE_SEPARATOR + "Use 'gfsh help' to display additional information."; - private final Set<String> allowedCommandLineCommands; - private final OptionParser commandLineParser; - private StartupTimeLogHelper startupTimeLogHelper; - static { // See 47325 System.setProperty(PureJavaMode.PURE_MODE_PROPERTY, "true"); } - public static void main(final String[] args) { - // first check whether required dependencies exist in the classpath - // should we start without tomcat/servlet jars? - String nonExistingDependency = CliUtil.cliDependenciesExist(true); - if (nonExistingDependency != null) { - System.err.println("Required (" + nonExistingDependency - + ") libraries not found in the classpath. gfsh can't start."); - return; - } - - Launcher launcher = new Launcher(); - System.exit(launcher.parseCommandLine(args)); - } + private final Set<String> allowedCommandLineCommands; + private final OptionParser commandLineParser; + private StartupTimeLogHelper startupTimeLogHelper; protected Launcher() { this.startupTimeLogHelper = new StartupTimeLogHelper(); @@ -138,6 +121,20 @@ public final class Launcher { this.commandLineParser.posixlyCorrect(false); } + public static void main(final String[] args) { + // first check whether required dependencies exist in the classpath + // should we start without tomcat/servlet jars? + String nonExistingDependency = CliUtil.cliDependenciesExist(true); + if (nonExistingDependency != null) { + System.err.println("Required (" + nonExistingDependency + + ") libraries not found in the classpath. gfsh can't start."); + return; + } + + Launcher launcher = new Launcher(); + System.exit(launcher.parseCommandLine(args)); + } + private int parseCommandLineCommand(final String... args) { Gfsh gfsh = null; try { @@ -253,7 +250,7 @@ public final class Launcher { } private int parseCommandLine(final String... args) { - if (args.length > 0 && !args[0].startsWith(SyntaxConstants.SHORT_OPTION_SPECIFIER)) { + if (args.length > 0 && !args[0].startsWith(GfshParser.SHORT_OPTION_SPECIFIER)) { return parseCommandLineCommand(args); } @@ -290,8 +287,6 @@ public final class Launcher { "Commands may be any that are available from the interactive gfsh prompt. " + "For commands that require a Manager to complete, the first command in the list must be \"connect\".", 1)); - stream.println(GfshParser.LINE_SEPARATOR + "AVAILABLE COMMANDS"); - stream.print(gfsh.obtainHelp("", this.allowedCommandLineCommands)); stream.println("EXAMPLES"); stream.println("gfsh"); stream.println(Gfsh.wrapText("Start GFSH in interactive mode.", 1)); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/809d64d7/geode-core/src/main/java/org/apache/geode/management/internal/cli/annotation/CliArgument.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/annotation/CliArgument.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/annotation/CliArgument.java deleted file mode 100644 index e20e731..0000000 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/annotation/CliArgument.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.geode.management.internal.cli.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.shell.core.Converter; -import org.springframework.shell.core.annotation.CliCommand; - -/** - * Annotation for Argument of a Command - * - * @since GemFire 7.0 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PARAMETER) -public @interface CliArgument { - - /** - * @return name of the argument, useful during help and warning messages - */ - String name(); - - /** - * @return a help message for this option (the default is a blank String, which means there is no - * help) - */ - String help() default ""; - - /** - * @return true if this argument must be specified one way or the other by the user (defaults to - * false) - */ - boolean mandatory() default false; - - /** - * Returns a string providing context-specific information (e.g. a comma-delimited set of - * keywords) to the {@link Converter} that handles the annotated parameter's type. - * <p> - * For example, if a method parameter "thing" of type "Thing" is annotated as follows: - * - * <pre> - * <code>@CliArgument(..., argumentContext = "foo,bar", ...) Thing thing</code> - * </pre> - * - * ... then the {@link Converter} that converts the text entered by the user into an instance of - * Thing will be passed "foo,bar" as the value of the <code>optionContext</code> parameter in its - * public methods. This allows the behaviour of that Converter to be individually customised for - * each {@link CliArgument} of each {@link CliCommand}. - * - * @return a non-<code>null</code> string (can be empty) - */ - String argumentContext() default ""; - - /** - * @return if true, the user cannot specify this option and it is provided by the shell - * infrastructure (defaults to false) - */ - boolean systemProvided() default false; - - /** - * @return the default value to use if this argument is unspecified by the user (defaults to - * __NULL__, which causes null to be presented to any non-primitive parameter) - */ - String unspecifiedDefaultValue() default "__NULL__"; -} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/809d64d7/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GfshHelpCommands.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GfshHelpCommands.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GfshHelpCommands.java index 1d1b28e..efb5c83 100644 --- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GfshHelpCommands.java +++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GfshHelpCommands.java @@ -15,27 +15,14 @@ package org.apache.geode.management.internal.cli.commands; import org.apache.geode.management.cli.CliMetaData; -import org.apache.geode.management.cli.ConverterHint; -import org.apache.geode.management.cli.Result; -import org.apache.geode.management.internal.cli.CommandManager; import org.apache.geode.management.internal.cli.GfshParser; -import org.apache.geode.management.internal.cli.annotation.CliArgument; -import org.apache.geode.management.internal.cli.help.CliTopic; import org.apache.geode.management.internal.cli.i18n.CliStrings; -import org.apache.geode.management.internal.cli.result.CompositeResultData; -import org.apache.geode.management.internal.cli.result.CompositeResultData.SectionResultData; -import org.apache.geode.management.internal.cli.result.ResultBuilder; import org.apache.geode.management.internal.cli.shell.Gfsh; import org.springframework.shell.core.CommandMarker; import org.springframework.shell.core.annotation.CliCommand; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; +import org.springframework.shell.core.annotation.CliOption; /** - * - * * @since GemFire 7.0 */ public class GfshHelpCommands implements CommandMarker { @@ -46,55 +33,53 @@ public class GfshHelpCommands implements CommandMarker { @CliCommand(value = CliStrings.HELP, help = CliStrings.HELP__HELP) @CliMetaData(shellOnly = true, relatedTopic = {CliStrings.TOPIC_GEODE_HELP}) - public Result obtainHelp( - @CliArgument(name = CliStrings.HELP__COMMAND, argumentContext = CliStrings.PARAM_CONTEXT_HELP, - help = CliStrings.HELP__COMMAND__HELP) String commandString) { - return ResultBuilder.createInfoResult(getGfsh().obtainHelp(commandString, null)); + public void obtainHelp( + @CliOption(key = {"", + "command"}, optionContext = "disable-string-converter availableCommands", help = "Command name to provide help for") + String buffer) { + ((GfshParser) (getGfsh().getParser())).obtainHelp(buffer); } - - - @CliCommand(value = CliStrings.HINT, help = CliStrings.HINT__HELP) - @CliMetaData(shellOnly = true, relatedTopic = {CliStrings.TOPIC_GEODE_HELP}) - public Result hint( - @CliArgument(name = CliStrings.HINT__TOPICNAME, argumentContext = ConverterHint.HINTTOPIC, - help = CliStrings.HINT__TOPICNAME) String topicName) { - Result result = null; - CommandManager commandManager = CommandManager.getExisting(); - if (commandManager == null) { - result = - ResultBuilder.createShellClientErrorResult(CliStrings.HINT__MSG__SHELL_NOT_INITIALIZED); - } else { - StringBuilder builder = new StringBuilder(); - if (topicName == null) { - builder.append(CliStrings.HINT__MSG__TOPICS_AVAILABLE).append(GfshParser.LINE_SEPARATOR); - Set<String> topicNameSet = commandManager.getTopicNames(); - for (String topic : topicNameSet) { - builder.append(topic).append(GfshParser.LINE_SEPARATOR); - } - result = ResultBuilder.createInfoResult(builder.toString()); - } else { - CliTopic topic = commandManager.getTopic(topicName); - if (topic == null) { - result = ResultBuilder - .createInfoResult(CliStrings.format(CliStrings.HINT__MSG__UNKNOWN_TOPIC, topicName)); - } else { - CompositeResultData compositeResultData = ResultBuilder.createCompositeResultData(); - SectionResultData commandHelpSection = - compositeResultData.addSection("Commands And Help"); - compositeResultData.setHeader(topic.getOneLinerDescription()); - Map<String, String> commandsNameHelp = topic.getCommandsNameHelp(); - Set<Entry<String, String>> entries = commandsNameHelp.entrySet(); - - for (Entry<String, String> entry : entries) { - commandHelpSection.addData(entry.getKey(), entry.getValue()); - } - - result = ResultBuilder.buildResult(compositeResultData); - } - } - } - - return result; - } +// +// @CliCommand(value = CliStrings.HINT, help = CliStrings.HINT__HELP) +// @CliMetaData(shellOnly = true, relatedTopic = {CliStrings.TOPIC_GEODE_HELP}) +// public Result hint( +// @CliArgument(name = CliStrings.HINT__TOPICNAME, argumentContext = ConverterHint.HINTTOPIC, +// help = CliStrings.HINT__TOPICNAME) String topicName) { +// Result result = null; +// CommandManager commandManager = CommandManager.getExisting(); +// if (commandManager == null) { +// return +// ResultBuilder.createShellClientErrorResult(CliStrings.HINT__MSG__SHELL_NOT_INITIALIZED); +// } +// +// StringBuilder builder = new StringBuilder(); +// if (topicName == null) { +// builder.append(CliStrings.HINT__MSG__TOPICS_AVAILABLE).append(GfshParser.LINE_SEPARATOR); +// Set<String> topicNameSet = commandManager.getTopicNames(); +// for (String topic : topicNameSet) { +// builder.append(topic).append(GfshParser.LINE_SEPARATOR); +// } +// result = ResultBuilder.createInfoResult(builder.toString()); +// } else { +// CliTopic topic = commandManager.getTopic(topicName); +// if (topic == null) { +// result = ResultBuilder +// .createInfoResult(CliStrings.format(CliStrings.HINT__MSG__UNKNOWN_TOPIC, topicName)); +// } else { +// CompositeResultData compositeResultData = ResultBuilder.createCompositeResultData(); +// SectionResultData commandHelpSection = +// compositeResultData.addSection("Commands And Help"); +// compositeResultData.setHeader(topic.getOneLinerDescription()); +// Map<String, String> commandsNameHelp = topic.getCommandsNameHelp(); +// Set<Entry<String, String>> entries = commandsNameHelp.entrySet(); +// +// for (Entry<String, String> entry : entries) { +// commandHelpSection.addData(entry.getKey(), entry.getValue()); +// } +// +// result = ResultBuilder.buildResult(compositeResultData); +// } +// } +// } }
