SHL-140: Fix 'help' command completion

This commit is contained in:
Eric Bottard
2014-04-18 16:37:23 +02:00
committed by mpollack
parent 91dc7b620a
commit a5eca63002
18 changed files with 205 additions and 119 deletions

View File

@@ -19,7 +19,6 @@ import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
@@ -36,30 +35,33 @@ import org.springframework.util.StopWatch;
* Loads a {@link Shell} using Spring IoC container.
*
* @author Ben Alex (original Roo code)
* @author Mark Pollack
* @author Mark Pollack
* @author David Winterfeldt
*
*
*/
public class Bootstrap {
private final static String[] CONTEXT_PATH = { "classpath*:/META-INF/spring/spring-shell-plugin.xml" };
private static Bootstrap bootstrap;
private static StopWatch sw = new StopWatch("Spring Shell");
private static CommandLine commandLine;
private GenericApplicationContext ctx;
public static void main(String[] args) throws IOException {
sw.start();
ExitShellRequest exitShellRequest;
try {
bootstrap = new Bootstrap(args);
bootstrap = new Bootstrap(args);
exitShellRequest = bootstrap.run();
} catch (RuntimeException t) {
}
catch (RuntimeException t) {
throw t;
} finally {
}
finally {
HandlerUtils.flushAllHandlers(Logger.getLogger(""));
}
@@ -69,59 +71,43 @@ public class Bootstrap {
public Bootstrap() {
this(null, CONTEXT_PATH);
}
public Bootstrap(String[] args) throws IOException {
public Bootstrap(String[] args) throws IOException {
this(args, CONTEXT_PATH);
}
public Bootstrap(String[] args, String[] contextPath) {
try {
commandLine = SimpleShellCommandLineOptions.parseCommandLine(args);
} catch (IOException e) {
throw new ShellException(e.getMessage(), e);
}
}
catch (IOException e) {
throw new ShellException(e.getMessage(), e);
}
ctx = new GenericApplicationContext();
ctx.registerShutdownHook();
configureApplicationContext(ctx);
//built-in commands and converters
configureApplicationContext(ctx);
// built-in commands and converters
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(ctx);
if (commandLine.getDisableInternalCommands()) {
scanner.scan("org.springframework.shell.converters", "org.springframework.shell.plugin.support");
} else {
scanner.scan("org.springframework.shell.commands", "org.springframework.shell.converters", "org.springframework.shell.plugin.support");
scanner.scan("org.springframework.shell.converters", "org.springframework.shell.plugin.support");
}
//user contributed commands
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) ctx);
else {
scanner.scan("org.springframework.shell.commands", "org.springframework.shell.converters",
"org.springframework.shell.plugin.support");
}
// user contributed commands
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(ctx);
reader.loadBeanDefinitions(contextPath);
ctx.refresh();
}
public ApplicationContext getApplicationContext() {
return ctx;
}
private void configureApplicationContext(GenericApplicationContext annctx) {
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.StringConverter.class);
createAndRegisterBeanDefinition(annctx,
org.springframework.shell.converters.AvailableCommandsConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.BigDecimalConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.BigIntegerConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.BooleanConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.CharacterConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.DateConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.DoubleConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.EnumConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.FloatConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.IntegerConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.LocaleConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.LongConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.ShortConverter.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.StaticFieldConverterImpl.class);
createAndRegisterBeanDefinition(annctx, org.springframework.shell.core.JLineShellComponent.class, "shell");
createAndRegisterBeanDefinition(annctx, org.springframework.shell.converters.SimpleFileConverter.class);
annctx.getBeanFactory().registerSingleton("commandLine", commandLine);
}
@@ -132,7 +118,7 @@ public class Bootstrap {
protected void createAndRegisterBeanDefinition(GenericApplicationContext annctx, Class<?> clazz, String name) {
RootBeanDefinition rbd = new RootBeanDefinition();
rbd.setBeanClass(clazz);
DefaultListableBeanFactory bf = (DefaultListableBeanFactory)annctx.getBeanFactory();
DefaultListableBeanFactory bf = (DefaultListableBeanFactory) annctx.getBeanFactory();
if (name != null) {
bf.registerBeanDefinition(name, rbd);
}
@@ -157,11 +143,10 @@ public class Bootstrap {
rooLogger.setLevel(Level.FINE);
}
public ExitShellRequest run() {
String[] commandsToExecuteAndThenQuit = commandLine.getShellCommandsToExecute();
// The shell is used
// The shell is used
JLineShellComponent shell = ctx.getBean("shell", JLineShellComponent.class);
ExitShellRequest exitShellRequest;
@@ -175,7 +160,7 @@ public class Bootstrap {
break;
}
//if all commands were successful, set the normal exit status
// if all commands were successful, set the normal exit status
if (successful) {
exitShellRequest = ExitShellRequest.NORMAL_EXIT;
}
@@ -198,7 +183,7 @@ public class Bootstrap {
}
return exitShellRequest;
}
public JLineShellComponent getJLineShellComponent() {
return ctx.getBean("shell", JLineShellComponent.class);
}

View File

@@ -31,7 +31,7 @@ import org.springframework.stereotype.Component;
* @author Ben Alex
* @author Mark Pollack
* @author Jarred Li
*
*
*/
@Component
public class HelpCommands implements CommandMarker, ApplicationContextAware {
@@ -39,13 +39,15 @@ public class HelpCommands implements CommandMarker, ApplicationContextAware {
private ApplicationContext ctx;
@CliCommand(value = "help", help = "List all commands usage")
public void obtainHelp(@CliOption(key = { "", "command" }, optionContext = "availableCommands", help = "Command name to provide help for") String buffer) {
public void obtainHelp(
@CliOption(key = { "", "command" }, optionContext = "disable-string-converter availableCommands", help = "Command name to provide help for")
String buffer) {
JLineShellComponent shell = ctx.getBean("shell", JLineShellComponent.class);
SimpleParser parser = shell.getSimpleParser();
parser.obtainHelp(buffer);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ctx = applicationContext;
}

View File

@@ -17,39 +17,42 @@ package org.springframework.shell.converters;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.JLineShellComponent;
import org.springframework.shell.core.MethodTarget;
import org.springframework.shell.core.SimpleParser;
import org.springframework.stereotype.Component;
/**
* Available commands converter.
*
*
* @author Ben Alex
* @author Eric Bottard
* @since 1.0
*/
@Component
public class AvailableCommandsConverter implements Converter<String> {
@Autowired
private JLineShellComponent shell;
@Override
public String convertFromText(final String text, final Class<?> requiredType, final String optionContext) {
return text;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return String.class.isAssignableFrom(requiredType) && "availableCommands".equals(optionContext);
return String.class.isAssignableFrom(requiredType) && optionContext.contains("availableCommands");
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
if (target.getTarget() instanceof SimpleParser) {
SimpleParser cmd = (SimpleParser) target.getTarget();
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
// Only include the first word of each command
for (String s : cmd.getEveryCommand()) {
if (s.contains(" ")) {
completions.add(new Completion(s.substring(0, s.indexOf(" "))));
} else {
completions.add(new Completion(s));
}
}
for (String s : shell.getSimpleParser().getEveryCommand()) {
completions.add(new Completion(s));
}
return true;
}

View File

@@ -21,23 +21,29 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link BigDecimal}.
*
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
public class BigDecimalConverter implements Converter<BigDecimal> {
@Override
public BigDecimal convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
return new BigDecimal(value);
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return BigDecimal.class.isAssignableFrom(requiredType);
}

View File

@@ -21,23 +21,29 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link BigInteger}.
*
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
public class BigIntegerConverter implements Converter<BigInteger> {
@Override
public BigInteger convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
return new BigInteger(value);
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return BigInteger.class.isAssignableFrom(requiredType);
}

View File

@@ -20,26 +20,33 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link Boolean}.
*
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
public class BooleanConverter implements Converter<Boolean> {
@Override
public Boolean convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
if ("true".equalsIgnoreCase(value) || "1".equals(value) || "yes".equalsIgnoreCase(value)) {
return true;
} else if ("false".equalsIgnoreCase(value) || "0".equals(value) || "no".equalsIgnoreCase(value)) {
}
else if ("false".equalsIgnoreCase(value) || "0".equals(value) || "no".equalsIgnoreCase(value)) {
return false;
} else {
}
else {
throw new IllegalArgumentException("Cannot convert " + value + " to type Boolean.");
}
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
completions.add(new Completion("true"));
completions.add(new Completion("false"));
completions.add(new Completion("yes"));
@@ -49,6 +56,7 @@ public class BooleanConverter implements Converter<Boolean> {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return Boolean.class.isAssignableFrom(requiredType) || boolean.class.isAssignableFrom(requiredType);
}

View File

@@ -20,23 +20,29 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link Character}.
*
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
public class CharacterConverter implements Converter<Character> {
@Override
public Character convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
return value.charAt(0);
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return Character.class.isAssignableFrom(requiredType) || char.class.isAssignableFrom(requiredType);
}

View File

@@ -24,13 +24,15 @@ import java.util.Locale;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link Date}.
*
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
public class DateConverter implements Converter<Date> {
// Fields
@@ -44,18 +46,23 @@ public class DateConverter implements Converter<Date> {
this.dateFormat = dateFormat;
}
@Override
public Date convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
try {
return dateFormat.parse(value);
} catch (ParseException e) {
}
catch (ParseException e) {
throw new IllegalArgumentException("Could not parse date: " + e.getMessage());
}
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return Date.class.isAssignableFrom(requiredType);
}

View File

@@ -20,23 +20,29 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link Double}.
*
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
public class DoubleConverter implements Converter<Double> {
@Override
public Double convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
return new Double(value);
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return Double.class.isAssignableFrom(requiredType) || double.class.isAssignableFrom(requiredType);
}

View File

@@ -20,41 +20,49 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link Enum}.
*
*
* @author Ben Alex
* @author Alan Stewart
* @since 1.0
*/
@SuppressWarnings("all")
@Component
public class EnumConverter implements Converter<Enum<?>> {
@Override
@SuppressWarnings("unchecked")
public Enum<?> convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
if(!Enum.class.isAssignableFrom(requiredType)) {
return null;
}
Class<Enum> enumClass = (Class<Enum>) requiredType;
return Enum.valueOf(enumClass, value);
if (!Enum.class.isAssignableFrom(requiredType)) {
return null;
}
Class<Enum> enumClass = (Class<Enum>) requiredType;
return Enum.valueOf(enumClass, value);
}
@Override
@SuppressWarnings("unchecked")
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
if(!Enum.class.isAssignableFrom(requiredType)) {
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
if (!Enum.class.isAssignableFrom(requiredType)) {
return false;
}
}
Class<Enum> enumClass = (Class<Enum>) requiredType;
for (Enum<?> enumValue : enumClass.getEnumConstants()) {
String candidate = enumValue.name();
if ("".equals(existingData) || candidate.startsWith(existingData) || existingData.startsWith(candidate) || candidate.toUpperCase().startsWith(existingData.toUpperCase()) || existingData.toUpperCase().startsWith(candidate.toUpperCase())) {
if ("".equals(existingData) || candidate.startsWith(existingData) || existingData.startsWith(candidate)
|| candidate.toUpperCase().startsWith(existingData.toUpperCase())
|| existingData.toUpperCase().startsWith(candidate.toUpperCase())) {
completions.add(new Completion(candidate));
}
}
return true;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return Enum.class.isAssignableFrom(requiredType);
}

View File

@@ -20,23 +20,29 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link Float}.
*
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
public class FloatConverter implements Converter<Float> {
@Override
public Float convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
return new Float(value);
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return Float.class.isAssignableFrom(requiredType) || float.class.isAssignableFrom(requiredType);
}

View File

@@ -5,23 +5,29 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link Integer}.
*
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
public class IntegerConverter implements Converter<Integer> {
@Override
public Integer convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
return new Integer(value);
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return Integer.class.isAssignableFrom(requiredType) || int.class.isAssignableFrom(requiredType);
}

View File

@@ -21,33 +21,40 @@ import java.util.Locale;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link Locale}. Supports locales
* with ISO-639 (ie 'en') or a combination of ISO-639 and
* {@link Converter} for {@link Locale}. Supports locales with ISO-639 (ie 'en') or a combination of ISO-639 and
* ISO-3166 (ie 'en_AU').
*
*
* @author Stefan Schmidt
* @since 1.1
*/
@Component
public class LocaleConverter implements Converter<Locale> {
@Override
public Locale convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
if (value.length() == 2) {
// In case only a simpele ISO-639 code is provided we use that code also for the country (ie 'de_DE')
return new Locale(value, value.toUpperCase());
} else if (value.length() == 5) {
}
else if (value.length() == 5) {
String[] split = value.split("_");
return new Locale(split[0], split[1]);
} else {
}
else {
return null;
}
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return Locale.class.isAssignableFrom(requiredType);
}

View File

@@ -20,23 +20,29 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link Long}.
*
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
public class LongConverter implements Converter<Long> {
@Override
public Long convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
return new Long(value);
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return Long.class.isAssignableFrom(requiredType) || long.class.isAssignableFrom(requiredType);
}

View File

@@ -20,23 +20,29 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link Short}.
*
*
* @author Stefan Schmidt
* @since 1.0
*/
@Component
public class ShortConverter implements Converter<Short> {
@Override
public Short convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
return new Short(value);
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return Short.class.isAssignableFrom(requiredType) || short.class.isAssignableFrom(requiredType);
}

View File

@@ -19,10 +19,12 @@ import java.io.File;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.shell.core.Shell;
import org.springframework.stereotype.Component;
//@Component
@Component
public class SimpleFileConverter extends FileConverter {
@Autowired private Shell shell;
@Autowired
private Shell shell;
@Override
protected File getWorkingDirectory() {

View File

@@ -24,26 +24,28 @@ import java.util.Map;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* A simple {@link Converter} for those classes which provide public static fields to represent possible
* textual values.
*
* A simple {@link Converter} for those classes which provide public static fields to represent possible textual values.
*
* @author Stefan Schmidt
* @author Ben Alex
* @since 1.0
*/
@Component
public class StaticFieldConverterImpl implements StaticFieldConverter {
// Fields
private final Map<Class<?>,Map<String,Field>> fields = new HashMap<Class<?>,Map<String,Field>>();
private final Map<Class<?>, Map<String, Field>> fields = new HashMap<Class<?>, Map<String, Field>>();
@Override
public void add(final Class<?> clazz) {
Assert.notNull(clazz, "A class to provide conversion services is required");
Assert.isNull(fields.get(clazz), "Class '" + clazz + "' is already registered for completion services");
Map<String,Field> ffields = new HashMap<String, Field>();
Map<String, Field> ffields = new HashMap<String, Field>();
for (Field field : clazz.getFields()) {
int modifier = field.getModifiers();
if (Modifier.isStatic(modifier) && Modifier.isPublic(modifier)) {
@@ -54,16 +56,18 @@ public class StaticFieldConverterImpl implements StaticFieldConverter {
fields.put(clazz, ffields);
}
@Override
public void remove(final Class<?> clazz) {
Assert.notNull(clazz, "A class that was providing conversion services is required");
fields.remove(clazz);
}
@Override
public Object convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
if (!StringUtils.hasText(value)) {
return null;
}
Map<String,Field> ffields = fields.get(requiredType);
Map<String, Field> ffields = fields.get(requiredType);
if (ffields == null) {
return null;
}
@@ -83,13 +87,17 @@ public class StaticFieldConverterImpl implements StaticFieldConverter {
}
try {
return f.get(null);
} catch (Exception ex) {
throw new IllegalStateException("Unable to acquire field '" + value + "' from '" + requiredType.getName() + "'", ex);
}
catch (Exception ex) {
throw new IllegalStateException("Unable to acquire field '" + value + "' from '" + requiredType.getName()
+ "'", ex);
}
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
Map<String,Field> ffields = fields.get(requiredType);
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
Map<String, Field> ffields = fields.get(requiredType);
if (ffields == null) {
return true;
}
@@ -99,6 +107,7 @@ public class StaticFieldConverterImpl implements StaticFieldConverter {
return true;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return fields.get(requiredType) != null;
}

View File

@@ -20,24 +20,31 @@ import java.util.List;
import org.springframework.shell.core.Completion;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.stereotype.Component;
/**
* {@link Converter} for {@link String}.
*
*
* @author Ben Alex
* @since 1.0
*/
@Component
public class StringConverter implements Converter<String> {
@Override
public String convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
return value;
}
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) {
@Override
public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType,
final String existingData, final String optionContext, final MethodTarget target) {
return false;
}
@Override
public boolean supports(final Class<?> requiredType, final String optionContext) {
return String.class.isAssignableFrom(requiredType) && (optionContext == null || !optionContext.contains("disable-string-converter"));
return String.class.isAssignableFrom(requiredType)
&& (optionContext == null || !optionContext.contains("disable-string-converter"));
}
}