package dmg.util.command;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.dcache.util.Args;
import org.dcache.util.cli.CommandExecutor;
import org.dcache.util.cli.CommandScanner;
/**
* Implements the legacy cell shell commands which use reflection
* on method and field names.
*/
public class AcCommandScanner implements CommandScanner
{
private enum FieldType { HELP_HINT, FULL_HELP, ACL }
@Override
public Map<List<String>, ? extends CommandExecutor> scan(Object obj)
{
Map<List<String>,AcCommandExecutor> commands = Maps.newHashMap();
scanMethods(obj, commands);
scanFields(obj, commands);
return commands;
}
/**
* Scan for help fields: fh_(= full help) or hh_(= help hint).
*/
private static void scanFields(Object obj, Map<List<String>, AcCommandExecutor> commands)
{
for (Field field: obj.getClass().getFields()) {
Iterator<String> i =
Splitter.on('_').split(field.getName()).iterator();
FieldType helpMode;
String helpType = i.next();
switch (helpType) {
case "hh":
helpMode = FieldType.HELP_HINT;
break;
case "fh":
helpMode = FieldType.FULL_HELP;
break;
case "acl":
helpMode = FieldType.ACL;
break;
default:
continue;
}
if (!i.hasNext()) {
continue;
}
List<String> name = Lists.newArrayList(i);
AcCommandExecutor command = getCommandExecutor(obj, commands, name);
switch (helpMode) {
case FULL_HELP:
command.setFullHelpField(field);
break;
case HELP_HINT:
command.setHelpHintField(field);
break;
case ACL:
command.setAclField(field);
break;
}
}
}
private static void scanMethods(Object obj, Map<List<String>, AcCommandExecutor> commands)
{
for (Method method: obj.getClass().getMethods()) {
Class<?>[] params = method.getParameterTypes();
//
// check the signature: Args args
//
if (params.length != 1 || !params[0].equals(Args.class)) {
continue;
}
//
// scan ac_.._.._..
//
Iterator<String> i =
Splitter.on('_').split(method.getName()).iterator();
if (!i.next().equals("ac")) {
continue;
}
if (!i.hasNext()) {
continue;
}
String comName = i.next();
if (comName.equals("$")) {
continue;
}
List<String> name = Lists.newArrayList();
name.add(comName);
while (i.hasNext()) {
comName = i.next();
if (comName.equals("$")) {
break;
}
name.add(comName);
}
//
// determine the number of arguments [_$_min[_max]]
//
int minArgs = 0;
int maxArgs = 0;
try {
if (i.hasNext()) {
minArgs = Integer.parseInt(i.next());
if (i.hasNext()) {
maxArgs = Integer.parseInt(i.next());
} else {
maxArgs = minArgs;
}
}
} catch (NumberFormatException e) {
throw new NumberFormatException(method.getName() + ": " + e.getMessage());
}
AcCommandExecutor command = getCommandExecutor(obj, commands, name);
command.setMethod(method, minArgs, maxArgs);
}
}
private static AcCommandExecutor getCommandExecutor(Object obj, Map<List<String>, AcCommandExecutor> commands,
List<String> name)
{
AcCommandExecutor command = commands.get(name);
if (command == null) {
command = new AcCommandExecutor(obj);
commands.put(name, command);
}
return command;
}
}