View Javadoc

1   package org.lsst.ccs.command;
2   
3   import org.lsst.ccs.command.annotations.Argument;
4   import org.lsst.ccs.command.annotations.Command;
5   
6   import java.lang.annotation.Annotation;
7   import java.lang.reflect.Method;
8   import java.util.Arrays;
9   
10  /**
11   * An implementation of DictionaryCommand based on a single annotated method.
12   *
13   * @author turri
14   */
15  class MethodBasedDictionaryCommand implements DictionaryCommand {
16  
17      private final String description;
18      private final String[] aliases;
19      private final DictionaryArgument[] params;
20      private final Command.CommandType type;
21      private final String name;
22      private final boolean hasVarArgs;
23      private final int level;
24  
25      /**
26       * Create a command definition from a method and associated annotation.
27       *
28       * @param annotatedMethod     The method providing the command implementation
29       * @param annotation The annotation on the method
30       */
31      MethodBasedDictionaryCommand(Method annotatedMethod, Command annotation) {
32          this.description = annotation.description();
33          this.aliases = splitAliases(annotation.alias());
34          this.type = annotation.type();
35          this.name = annotation.name().isEmpty() ? annotatedMethod.getName() : annotation.name();
36          this.hasVarArgs = annotatedMethod.isVarArgs();
37          this.level = annotation.level();
38  
39          Class[] types = annotatedMethod.getParameterTypes();
40          Annotation[][] parAnnotations = annotatedMethod.getParameterAnnotations();
41  
42          params = new MethodBasedDictionaryArgument[types.length];
43  
44          for (int i = 0; i < types.length; i++) {
45  
46              String parName = "arg" + i;
47              String parDescription = "";
48              for (Annotation a : parAnnotations[i]) {
49                  if (a instanceof Argument) {
50                      Argument paramAnnotation = (Argument) a;
51                      parName = paramAnnotation.name().isEmpty() ? parName : paramAnnotation.name();
52                      parDescription = paramAnnotation.description();
53                      break;
54                  }
55              }
56              Class parameterType = hasVarArgs && i == types.length - 1 ? types[i].getComponentType() : types[i];
57              params[i] = new MethodBasedDictionaryArgument(parName, parameterType, parDescription);
58          }
59  
60  
61      }
62  
63      @Override
64      public String getDescription() {
65          return description;
66      }
67  
68      @Override
69      public String[] getAliases() {
70          return aliases;
71      }
72  
73      @Override
74      public DictionaryArgument[] getArguments() {
75          return params;
76      }
77  
78      @Override
79      public Command.CommandType getType() {
80          return type;
81      }
82  
83      @Override
84      public String getCommandName() {
85          return name;
86      }
87  
88      @Override
89      public boolean isVarArgs() {
90          return hasVarArgs;
91      }
92  
93      @Override
94      public int getLevel() {
95          return level;
96      }
97      
98      /**
99       * Test if value matches this command (either the command itself or one if
100      * its aliases).
101      *
102      * @param value The value to test
103      * @return <code>true</code> if the value matches
104      */
105     @Override
106     public boolean matchesCommandOrAlias(String value) {
107         if (name.equals(value)) {
108             return true;
109         }
110         for (String alias : aliases) {
111             if (alias.equals(value)) {
112                 return true;
113             }
114         }
115         return false;
116     }
117 
118     private String[] splitAliases(String alias) {
119         return alias.length() > 0 ? alias.split("\\s?,\\s?") : NO_ALIASES;
120     }
121 
122     @Override
123     public String toString() {
124         return "MethodBasedDictionaryCommand{" +
125                 "description='" + description + '\'' +
126                 ", aliases=" + Arrays.toString(aliases) +
127                 ", params=" + Arrays.toString(params) +
128                 ", type=" + type +
129                 ", name='" + name + '\'' +
130                 ", hasVarArgs=" + hasVarArgs +
131                 '}';
132     }
133 }