View Javadoc

1   package org.lsst.ccs.command;
2   
3   import org.lsst.ccs.command.annotations.Command;
4   
5   import java.lang.annotation.Annotation;
6   import java.lang.reflect.Method;
7   import java.util.Collection;
8   import java.util.HashMap;
9   import java.util.Map;
10  
11  /**
12   * This class consists of a CommandDictionary plus a map of which methods should
13   * be called as a result of each command. It does not require a reference to any
14   * particular object, just a class.
15   *
16   * Note that since this object is not a CommandSet, the utilities for combining
17   * and working with CommandSets cannot be used with this class.
18   *
19   * @author tonyj
20   */
21  // change history: bamade added implements to new interface LocalCommandDictionary
22  public class CommandDictionaryBuilder implements LocalCommandDictionary {
23  
24  	private MethodBasedCommandDictionary dict;
25  	private final Map<DictionaryCommand, Method> methods = new HashMap<>();
26  
27  	/**
28  	 * Build a command dictionary for the given class.
29  	 *
30  	 * @param klass The class to build the dictionary from
31  	 */
32  	CommandDictionaryBuilder(Class klass) {
33  		init(klass);
34  	}
35  
36  	/**
37  	 * Get the command dictionary.
38  	 *
39  	 * @return The command dictionary.
40  	 */
41  	public Dictionary getCommandDictionary() {
42  		return dict;
43  	}
44  
45  	/**
46  	 * Find the method which should be invoked as a result of a particular
47  	 * command.
48  	 *
49  	 * @param command The command to be invoked
50  	 * @return The method to be called to invoke the command, or
51  	 * <code>null</code> if the command is not known.
52  	 */
53  	public Method getMethod(BasicCommand command) {
54  	    //todo: note by bernard .. the way I use it we are doing twice the findCommand!!!
55  		// so I added the method below
56  		DictionaryCommand dc = dict.findCommand(command);
57  		if (dc == null) {
58  			return null;
59  		}
60  		return methods.get(dc);
61  	}
62  
63  	/***
64  	 * Finds a <TT>Method</TT> which is linked to a <TT>DictionaryCommand</TT>.
65  	 * @param dc a dictionary command that should be extracted from the current <TT>Dicionary</TT>
66  	 * @return The method to be called to invoke the command, or
67  	 * <code>null</code> if the command is not known.
68  	 */
69  	public Method getMethod(DictionaryCommand dc) {
70  		if (dc == null) {
71  			return null;
72  		}
73  		return methods.get(dc);
74  	}
75  
76  
77      private static Method[] arrayModel = new Method[0] ;
78      /*
79      * return the list of methods that are commands
80       */
81      public Collection<Method> getMethods() {
82           return methods.values() ;
83      }
84  
85  	private void init(Class targetClass) {
86  		dict = new MethodBasedCommandDictionary();
87  		for (Method targetMethod : targetClass.getMethods()) {
88  			Method annotatedMethod = getAnnotationWithInheritance(targetMethod, Command.class);
89  			if (annotatedMethod != null) {
90  				Command annotation = annotatedMethod.getAnnotation(Command.class);
91  				if (annotation != null) {
92  					MethodBasedDictionaryCommand dc = new MethodBasedDictionaryCommand(annotatedMethod, annotation);
93  					dict.add(dc);
94  					methods.put(dc, targetMethod);
95  				}
96  			}
97  		}
98  	}
99  
100 	/**
101 	 * Java does not currently support inheritance of method annotations
102 	 * (only Class annotations). This method works around this be searching
103 	 * for annotations for a particular method on super classes.
104 	 *
105 	 * @param method The method on which to search
106 	 * @param annotationClass The annotation subclass to search for
107 	 * @return The annotated method if found, or <code>null</code> if not
108 	 * found
109 	 */
110 	private static <T extends Annotation> Method getAnnotationWithInheritance(Method method, Class<T> annotationClass) {
111 		for (;;) {
112 			T annotation = method.getAnnotation(annotationClass);
113 			if (annotation != null) {
114 				return method;
115 			}
116 			Class superClass = method.getDeclaringClass().getSuperclass();
117 			if (superClass == null) {
118 				break;
119 			}
120 			try {
121 				method = superClass.getMethod(method.getName(), method.getParameterTypes());
122 			} catch (NoSuchMethodException ex) {
123 				break;
124 			}
125 		}
126 		return null;
127 	}
128 }