
org.jsimpledb.cli.cmd.AbstractCommand Maven / Gradle / Ivy
Show all versions of jsimpledb-cli Show documentation
/*
* Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
*/
package org.jsimpledb.cli.cmd;
import com.google.common.base.Preconditions;
import java.util.EnumSet;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jsimpledb.SessionMode;
import org.jsimpledb.cli.CliSession;
import org.jsimpledb.cli.ParamParser;
import org.jsimpledb.parse.FieldTypeParser;
import org.jsimpledb.parse.ObjIdParser;
import org.jsimpledb.parse.ObjTypeParser;
import org.jsimpledb.parse.ParseSession;
import org.jsimpledb.parse.Parser;
import org.jsimpledb.parse.expr.ExprParser;
import org.jsimpledb.util.ParseContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Superclass of all CLI commands.
*
* @see Command
*/
public abstract class AbstractCommand implements Parser {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
protected final String name;
protected final ParamParser paramParser;
// Constructors
/**
* Constructor.
*
* @param spec {@link ParamParser} spec string, possibly containing custom type names (see {@link #getParser getParser()})
*/
protected AbstractCommand(String spec) {
Preconditions.checkArgument(spec != null, "null spec");
final Matcher matcher = Pattern.compile("([^\\s]+)(\\s+(.*))?").matcher(spec);
if (!matcher.matches())
throw new IllegalArgumentException("invalid command specification `" + spec + "'");
this.name = matcher.group(1);
final String paramSpec = matcher.group(3);
this.paramParser = new ParamParser(paramSpec != null ? paramSpec : "") {
@Override
protected Parser> getParser(String typeName) {
try {
return super.getParser(typeName);
} catch (IllegalArgumentException e) {
return AbstractCommand.this.getParser(typeName);
}
}
};
}
// Command stuff
/**
* Get the name of this command.
*
* @return command name
*/
public String getName() {
return this.name;
}
/**
* Get command usage string.
*
*
* The implementation in {@link AbstractCommand} delegates to {@link ParamParser#getUsage ParamParser.getUsage()}.
*
*
* @return command usage string
*/
public String getUsage() {
return this.paramParser.getUsage(this.name);
}
/**
* Get summarized help (typically a single line).
*
* @return one line command summary
*/
public abstract String getHelpSummary();
/**
* Get expanded help (typically multiple lines).
*
*
* The implementation in {@link AbstractCommand} delegates to {@link #getHelpSummary getHelpSummary()}.
*
*
* @return detailed command description
*/
public String getHelpDetail() {
return this.getHelpSummary();
}
/**
* Get the {@link SessionMode}(s) supported by this instance.
*
*
* The implementation in {@link AbstractCommand} introspects the {@link Command @Command} annotation on
* this instance's class; if not present, an exception is thrown.
*
*
* @return set of supported {@link SessionMode}s
*/
public EnumSet getSessionModes() {
final Command annotation = this.getClass().getAnnotation(Command.class);
if (annotation == null)
throw new UnsupportedOperationException("no @Command annotation found on " + this.getClass());
final EnumSet set = EnumSet.noneOf(SessionMode.class);
for (SessionMode sessionMode : annotation.modes())
set.add(sessionMode);
return set;
}
/**
* Parse command line and return command action.
*
*
* The implementation in {@link AbstractCommand} parses the parameters and delegates to {@link #getAction} with the result.
*
*
* @param session CLI session
* @param ctx input to parse
* @param complete false if parse is "for real", true if only for tab completion calculation
* @return action to perform for the parsed command
* @throws org.jsimpledb.parse.ParseException if parse fails, or if {@code complete} is true and there are valid completions
* @throws org.jsimpledb.parse.ParseException if parameters are invalid
*/
@Override
public CliSession.Action parse(ParseSession session, ParseContext ctx, boolean complete) {
return this.getAction((CliSession)session, ctx, complete, this.paramParser.parse(session, ctx, complete));
}
/**
* Process command line parameters and return action.
*
* @param session CLI session
* @param ctx input to parse
* @param complete false if parse is "for real", true if only for tab completion calculation
* @param params parsed parameters indexed by name
* @return action to perform for the parsed command
* @throws org.jsimpledb.parse.ParseException if parse fails, or if {@code complete} is true and there are valid completions
* @throws org.jsimpledb.parse.ParseException if parameters are invalid
*/
public abstract CliSession.Action getAction(CliSession session, ParseContext ctx, boolean complete, Map params);
/**
* Convert parameter spec type name into a {@link Parser}. Used for custom type names not supported by {@link ParamParser}.
*
*
* The implementation in {@link AbstractCommand} supports all {@link org.jsimpledb.core.FieldType}s registered with the
* database, {@code type} for an object type name (returns {@link Integer}), and {@code objid} for an object ID
* (returns {@link org.jsimpledb.core.ObjId}).
*
*
* @param typeName parameter type name
* @return parser for parameters of the specified type
*/
protected Parser> getParser(String typeName) {
Preconditions.checkArgument(typeName != null, "null typeName");
if (typeName.equals("type"))
return new ObjTypeParser();
if (typeName.equals("objid"))
return new ObjIdParser();
if (typeName.equals("expr"))
return new ExprParser();
return FieldTypeParser.getFieldTypeParser(typeName);
}
}