001 package dk.deepthought.sidious.blackboard;
002
003 import java.util.Collection;
004
005 import org.apache.commons.logging.Log;
006 import org.apache.commons.logging.LogFactory;
007
008 import dk.deepthought.sidious.goalhandler.Goal;
009 import dk.deepthought.sidious.planner.Plan;
010 import dk.deepthought.sidious.planner.PlannerEngine;
011 import dk.deepthought.sidious.supportsystem.Adjustable;
012 import dk.deepthought.sidious.supportsystem.PlanRequester;
013 import dk.deepthought.sidious.supportsystem.Repository;
014 import dk.deepthought.sidious.supportsystem.SuperLinkID;
015 import dk.deepthought.sidious.util.SidiousMap;
016
017 /**
018 * This class acts as a blackboard. It facilitates the communication
019 * between the various components of the system.
020 * <p>
021 * The class is implemented as a Singleton.
022 *
023 * @author Deepthought
024 *
025 */
026 public class BlackBoardEngine implements BlackBoard {
027
028 /**
029 * Logger for this class.
030 */
031 private static final Log logger = LogFactory.getLog(BlackBoardEngine.class);
032
033 /**
034 * The instance of the blackboard; to facilitate singleton property.
035 */
036 private static final BlackBoard INSTANCE = new BlackBoardEngine();
037
038 /**
039 * This maps the id of a plan requester to the actual reference.
040 */
041 private final SidiousMap requesterMapping;
042
043 /**
044 * Private constructor; to facilitate singleton property.
045 */
046 private BlackBoardEngine() {
047 requesterMapping = new SidiousMap();
048 if (logger.isDebugEnabled()) {
049 logger.debug("BlackBoardEngine() - initialized");
050 }
051 }
052
053 /**
054 * Returns a reference to the blackboard of the system.
055 * <p>
056 * Note that the blackboard is implemented as a Singleton.
057 *
058 * @return a reference to the blackboard
059 */
060 public static BlackBoard getInstance() {
061 return INSTANCE;
062 }
063
064 /**
065 * TESTING purposes ONLY!!
066 */
067 public void addToMapping(PlanRequester requester) {
068 SuperLinkID id = requester.getID();
069 synchronized (requesterMapping) {
070 PlanRequester put = requesterMapping.put(id, requester);
071 if (put != null) {
072 logger.warn("requestPlan(PlanRequester requester=" + requester
073 + ") - requester already in map");
074 }
075 }
076 }
077
078 /* (non-Javadoc)
079 * @see dk.deepthought.sidious.blackboard.BlackBoard#requestPlan(dk.deepthought.sidious.supportsystem.PlanRequester)
080 */
081 public void requestPlan(PlanRequester requester) {
082 if (requester == null) {
083 logger
084 .error("requestPlan(PlanRequester requester=null) - requester was null");
085 throw new IllegalArgumentException("requester was null");
086 }
087 SuperLinkID id = requester.getID();
088 synchronized (requesterMapping) {
089 PlanRequester put = requesterMapping.put(id, requester);
090 if (put != null) {
091 logger.warn("requestPlan(PlanRequester requester=" + requester
092 + ") - requester already in map");
093 }
094 }
095
096 Repository.getGoalHandler().request(id);
097 if (logger.isDebugEnabled()) {
098 logger.debug("requestPlan(PlanRequester requester=" + requester
099 + ") - requested a plan");
100 }
101 }
102
103 /**
104 * Returns a reference to the plan requester associated with the specified
105 * <code>id</code>.
106 * <p>
107 * If no requester is associated with the specified id, planning for the
108 * specified id is stopped in the PlannerEngine, and <code>null</code> is
109 * returned.
110 *
111 * @see PlannerEngine
112 *
113 * @param id
114 * the id of the requested requester
115 * @return a reference to the specified plan requester, or <code>null</code>
116 * if requester does not exist
117 */
118 public PlanRequester getRequester(SuperLinkID id) {
119 if (id == null) {
120 logger.error("getRequester(SuperLinkID id=null) - not valid id");
121 throw new IllegalArgumentException("null not valid id");
122 }
123 PlanRequester returnPlanRequester = null;
124 synchronized (requesterMapping) {
125 returnPlanRequester = requesterMapping.get(id);
126 }
127 if (returnPlanRequester == null) {
128 logger.error("getRequester(SuperLinkID id=" + id
129 + ") - missing requester");
130 Repository.getPlanner().stop(id);
131 return null;
132 }
133 if (logger.isDebugEnabled()) {
134 logger.debug("getRequester(SuperLinkID id=" + id
135 + ") - return value=" + returnPlanRequester);
136 }
137 return returnPlanRequester;
138 }
139
140 /*
141 * (non-Javadoc)
142 *
143 * @see dk.deepthought.sidious.blackboard.BlackBoard#getAdjustableSetting(dk.deepthought.sidious.supportsystem.SuperLinkID,
144 * dk.deepthought.sidious.supportsystem.SuperLinkID)
145 */
146 public double getAdjustableSetting(SuperLinkID requesterID,
147 SuperLinkID adjustableID) {
148 if (logger.isDebugEnabled()) {
149 logger.debug("getAdjustableSetting(SuperLinkID requesterID="
150 + requesterID + ", SuperLinkID adjustableID="
151 + adjustableID + ") - start");
152 }
153 if (adjustableID == null) {
154 logger
155 .error("getAdjustableSetting(SuperLinkID requesterID="
156 + requesterID
157 + ", SuperLinkID adjustableID=null) - not valid adjustableID");
158
159 throw new IllegalArgumentException("null not valid adjustableID");
160
161 }
162 PlanRequester requester = getRequester(requesterID);
163 if (requester == null) {
164 return 0;
165 }
166 Collection<Adjustable> adjustables = requester.getAdjustables();
167 double returnValue = 0;
168 for (Adjustable adjustable : adjustables) {
169 if (adjustable.getID().equals(adjustableID)) {
170 returnValue = adjustable.getSetting();
171 }
172 }
173
174 if (logger.isDebugEnabled()) {
175 logger.debug("getAdjustableSetting(SuperLinkID requesterID="
176 + requesterID + ", SuperLinkID adjustableID="
177 + adjustableID + ") - end - return value=" + returnValue);
178 }
179 return returnValue;
180 }
181
182 /**
183 * Adds a goal to
184 * @param goal the goal to be added
185 */
186 public void addGoal(Goal goal) {
187 Repository.getPlanner().requestPlan(goal);
188 }
189
190 /**
191 * Adds a plan to the blackboard.
192 * <p>
193 * The requester of the plan is notified that the plan is ready; and is
194 * removed from the queue.
195 *
196 * @param plan
197 * the devised plan
198 */
199 public void addPlan(Plan plan) {
200 SuperLinkID id = plan.getId();
201 synchronized (requesterMapping) {
202 PlanRequester requester = getRequester(id);
203 requester.setPlan(plan);
204 requesterMapping.remove(id);
205 }
206 }
207
208 /* (non-Javadoc)
209 * @see dk.deepthought.sidious.blackboard.BlackBoard#deliverResult(java.lang.Object)
210 */
211 public void deliverResult(Object result) {
212 if (result instanceof Plan) {
213 Plan plan = (Plan) result;
214 addPlan(plan);
215 } else if (result instanceof Goal) {
216 Goal goal = (Goal) result;
217 addGoal(goal);
218 }
219 }
220
221 }
|