1 package cz.cuni.amis.pogamut.sposh;
2
3 import java.lang.reflect.Method;
4 import java.util.ArrayList;
5 import java.util.List;
6
7 import cz.cuni.amis.pogamut.sposh.executor.ActionResult;
8
9
10 /**
11 * Base class for definitions of senses and acts of SPOSH bot.
12 * <p/>
13 * User will implement actions and senses used in the plan by deriving this
14 * class and by creating senses and actions for SPOSH plan in following fashion:
15 * <p>
16 * actions are methods annotated with @SPOSHAction annotation. Name of method is
17 * arbitrary and return type should one of the standard ones (String + numbers).
18 * SPOSH engine will use toString() method for the return values of user defined
19 * classes (probably), but because there are some issues with jython-java
20 * interaction, it may produce some weird bugs.
21 * <ul>
22 * <li>in plan file: shoot</li>
23 * <li>in behaviour: @SPOSHAction public void shoot()</li>
24 * </ul>
25 * Sense is a method returning value annotated with @SPOSHSense. Name and return
26 * restrictions are similar to action.
27 * <ul>
28 * <li>in plan file: hear</li>
29 * <li>in behaviour: @SPOSHSense public boolean hearNoise()</li>
30 * </ul>
31 *
32 * For simplest action see {@link JavaBehaviour#doNothing()} or sense {@link JavaBehaviour#fail()}.
33 *
34 * The actions can utilize log, that is available through {@code log} member of class
35 * (it is a {@link AgentLogger} of the SPOSH bot.
36 *
37 * This basic class (as well all derived ones) implements following actions
38 * <ul>
39 * <li>doNothing</li>
40 * </ul>
41 * and senses
42 * <ul>
43 * <li>fail</li>
44 * <li>succeed</li>
45 * </ul>
46 *
47 * @author Honza
48 * @author Jimmy
49 */
50 public class JavaBehaviour<AGENT> {
51
52 private String name = "behaviour";
53 private String[] actions = null;
54 private String[] senses = null;
55 protected AGENT bot = null;
56
57 //
58 // 2nd CHANGE (ubrani parametru IAgentLogger)
59 //
60
61 /**
62 * Create new behaviour.
63 * @param name Name of behaviour so it is easy to distinguish between
64 * different behaviours classes in the log and error messages
65 * @param bot Class of the bot that this behaviour is serving.
66 * Used by sense and actions for gathering info and manipulation of the bot.
67 */
68 public JavaBehaviour(String name, AGENT bot) {
69 this.name = name;
70 this.bot = bot;
71 this.getActions();
72 this.getSenses();
73 }
74
75 /**
76 * Get name of the behaviour specified in the constructor.
77 * @return Name of the behaviour
78 */
79 public String getName() {
80 return this.name;
81 }
82
83 /**
84 * Returns list of actions that are declared in the behaviour class. Search
85 * for the actions is performed only on first execution of method.
86 * <p>
87 * Use Java Reflection API to search through the methods for methods
88 * with annotations @SPOSHActions and return list of strings
89 * that contains the methods.
90 * @return list with names of actions methods
91 */
92 public String[] getActions() {
93 if (this.actions != null) {
94 return this.actions;
95 }
96
97 Method methods[] = this.getClass().getMethods();
98 List<String> result = new ArrayList<String>();
99
100 for (Method method : methods) {
101 if (method.isAnnotationPresent(SPOSHAction.class)) {
102 result.add(method.getName());
103 }
104 }
105 this.actions = result.toArray(new String[0]);
106 return this.actions;
107 }
108
109 /**
110 * Returns list of senses that are declared in the behaviour class. Search
111 * for the senses is performed only on first execution of method.
112 * <p>
113 * Use Java Reflection API to search through the methods for methods
114 * with annotations @SPOSHSense and return list of strings
115 * that contains the methods.
116 * @return list with names of sense methods
117 */
118 public String[] getSenses() {
119 if (this.senses != null) {
120 return this.senses;
121 }
122 Method methods[] = this.getClass().getMethods();
123 List<String> result = new ArrayList<String>();
124 for (Method method : methods) {
125 if (method.isAnnotationPresent(SPOSHSense.class)) {
126 result.add(method.getName());
127 }
128 }
129 this.senses = result.toArray(new String[0]);
130 return this.senses;
131 }
132
133 /**
134 * Standard action that has to be implemented everywhere. Sleep for 250ms.
135 * @return true
136 */
137 @SPOSHAction
138 public ActionResult doNothing() {
139 try {
140 Thread.sleep(50);
141 } catch (InterruptedException e) {
142 }
143 return ActionResult.FINISHED;
144 }
145
146 /**
147 * Standard sense that has to be implemented everywhere.
148 * @return false
149 */
150 @SPOSHSense
151 public boolean fail() {
152 return false;
153 }
154
155 /**
156 * Standard sense that has to be implemented everywhere.
157 * @return true
158 */
159 @SPOSHSense
160 public boolean succeed() {
161 return true;
162 }
163
164 /**
165 * Method that is triggered every time the plan for executor is evaluated. It is triggered right before the plan evaluation.
166 */
167 public void logicBeforePlan() {
168 }
169
170 /**
171 * Method that is triggered every time the plan for executor is evaluated. It is triggered right after the plan evaluation.
172 */
173 public void logicAfterPlan() {
174 }
175
176 /**
177 * Returns underlying AGENT instance.
178 * @return
179 */
180 public AGENT getBot() {
181 return bot;
182 }
183
184 }