1 package cz.cuni.amis.pogamut.sposh.ut2004;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationTargetException;
5 import java.util.Collections;
6 import java.util.Set;
7
8 import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
9 import cz.cuni.amis.pogamut.sposh.context.Context;
10 import cz.cuni.amis.pogamut.sposh.context.IUT2004Context;
11 import cz.cuni.amis.pogamut.sposh.engine.PoshEngine;
12 import cz.cuni.amis.pogamut.sposh.exceptions.StateInstantiationException;
13 import cz.cuni.amis.pogamut.sposh.executor.IAction;
14 import cz.cuni.amis.pogamut.sposh.executor.ISense;
15 import cz.cuni.amis.pogamut.sposh.executor.IWorkExecutor;
16 import cz.cuni.amis.pogamut.sposh.executor.StateAction;
17 import cz.cuni.amis.pogamut.sposh.executor.StateSense;
18 import cz.cuni.amis.pogamut.sposh.executor.StateWorkExecutor;
19 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
20 import java.io.IOException;
21 import java.util.*;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 @AgentScoped
46 public abstract class StateSposhLogicController<BOT extends UT2004Bot, CONTEXT extends IUT2004Context> extends SposhLogicController<BOT, StateWorkExecutor> {
47
48
49 protected CONTEXT context;
50
51
52
53
54
55
56 @Override
57 public void initializeController(BOT bot) {
58 super.initializeController(bot);
59 context = createContext();
60
61 getWorkExecutor();
62 }
63
64
65 @Override
66 public void finishControllerInitialization() {
67 super.finishControllerInitialization();
68 context.finishInitialization();
69 }
70
71
72
73
74
75 public final CONTEXT getContext() {
76 return context;
77 }
78
79
80
81
82
83
84
85
86
87 protected void customPrimitiveInstantiation(StateWorkExecutor executor, Set<String> actions, Set<String> senses) {
88
89 }
90
91
92
93
94
95
96 private Class getActionClass(String actionName) {
97 try {
98 return Class.forName(actionName);
99 } catch (ClassNotFoundException ex) {
100 throw new StateInstantiationException("Unable to find state class for action \"" + actionName + "\"", ex);
101 }
102 }
103
104
105
106
107
108
109 private Class getSenseClass(String senseName) {
110 try {
111 return Class.forName(senseName);
112 } catch (ClassNotFoundException ex) {
113 throw new StateInstantiationException("Unable to find state class for sense \"" + senseName + "\"", ex);
114 }
115 }
116
117
118
119
120
121
122
123
124 private <T> T instantiatePrimitive(Class<T> cls) {
125 String name = cls.getName();
126 try {
127 Constructor primitiveConstructor = null;
128 Constructor<?>[] constructors = cls.getConstructors();
129 for (Constructor<?> constructor : constructors) {
130 Class[] constructorParameters = constructor.getParameterTypes();
131 if (constructorParameters.length != 1) {
132 continue;
133 }
134 if (constructorParameters[0].isAssignableFrom(this.getContext().getClass())) {
135 primitiveConstructor = constructor;
136 }
137 }
138 if (primitiveConstructor == null) {
139 throw new StateInstantiationException("Primitive \"" + name + "\" doesn't have a constructor that has exactly one parameter of class " + this.getContext().getClass().getName());
140 }
141 return (T) primitiveConstructor.newInstance(this.getContext());
142 } catch (InstantiationException ex) {
143 throw new StateInstantiationException("Unable to instantiate primitive \"" + name + "\" (" + ex.getMessage() + ")", ex);
144 } catch (IllegalAccessException ex) {
145 throw new StateInstantiationException("Illegal access protection for primitive \"" + name + "\"", ex);
146 } catch (IllegalArgumentException ex) {
147 throw new StateInstantiationException("Primitive \"" + name + "\" doesn't accept bot class (" + this.bot.getClass().getName() + ") in the constructor.", ex);
148 } catch (InvocationTargetException ex) {
149 throw new StateInstantiationException("Constructor of primitive \"" + name + "\" has thrown an exception (" + ex.getMessage() + ")", ex);
150 }
151 }
152
153 private Set<String> getActionNames() {
154 Set<String> actionNames = new HashSet<String>();
155 for (PoshEngine engine : getEngines()) {
156 Set<String> engineActions = engine.getPlan().getActionsNames();
157 actionNames.addAll(engineActions);
158 }
159 return actionNames;
160 }
161
162 private Set<String> getSensesNames() {
163 Set<String> senseNames = new HashSet<String>();
164 for (PoshEngine engine : getEngines()) {
165 Set<String> engineSenses = engine.getPlan().getSensesNames();
166 senseNames.addAll(engineSenses);
167 }
168 return senseNames;
169 }
170
171 @Override
172 protected StateWorkExecutor createWorkExecutor() {
173 StateWorkExecutor executor = new StateWorkExecutor(bot.getLogger().getCategory(SPOSH_LOG_CATEGORY));
174
175
176 Set<String> actions = getActionNames();
177 Set<String> senses = getSensesNames();
178
179
180 for (String senseName : senses) {
181 if (actions.contains(senseName))
182 throw new StateInstantiationException("List of senses and " + senseName);
183 }
184
185
186
187 customPrimitiveInstantiation(executor, Collections.unmodifiableSet(actions), Collections.unmodifiableSet(senses));
188
189
190 for (String name : actions) {
191 if (executor.isNameUsed(name)) {
192 throw new StateInstantiationException("Action instantiation: Primitive with name \"" + name + "\" is already in has already used in the executor.");
193 }
194 Class<IAction> cls = getActionClass(name);
195 IAction action = instantiatePrimitive(cls);
196 executor.addAction(name, action);
197 }
198 for (String name : senses) {
199 if (executor.isNameUsed(name)) {
200 throw new StateInstantiationException("Sense instantiation: Primitive with name \"" + name + "\" is already in has already used in the executor.");
201 }
202 Class<ISense> cls = getSenseClass(name);
203 ISense sense = instantiatePrimitive(cls);
204 executor.addSense(name, sense);
205 }
206
207 return executor;
208 }
209
210
211
212
213
214
215
216
217 @Override
218 protected List<String> getPlans() throws IOException {
219 return Arrays.asList(getPlan());
220 }
221
222
223
224
225
226
227
228
229
230 protected abstract String getPlan() throws IOException;
231
232
233
234
235
236 protected abstract CONTEXT createContext();
237 }