001 package dk.deepthought.sidious.planner;
002
003 import java.util.Collection;
004 import java.util.HashMap;
005
006 import org.apache.commons.logging.Log;
007 import org.apache.commons.logging.LogFactory;
008
009 import dk.deepthought.sidious.goalhandler.Goal;
010 import dk.deepthought.sidious.planner.graph.Graph;
011 import dk.deepthought.sidious.services.ServiceEngine;
012 import dk.deepthought.sidious.supportsystem.Adjustable;
013 import dk.deepthought.sidious.supportsystem.Repository;
014 import dk.deepthought.sidious.supportsystem.State;
015 import dk.deepthought.sidious.supportsystem.SuperLinkID;
016 import dk.deepthought.sidious.util.SidiousQueue;
017
018 /**
019 * This class constitutes a Blackboard for the planner. Works as a liaison class
020 * between the <code>{@link GraphFactory}</code> and
021 * <code>{@link Pathfinder}</code>.
022 * <p>
023 * This class holds three <code>SidiousQueue</code> queues for calculating a
024 * plan:
025 * <ol>
026 * <li> extracting state and generating the graph
027 * <li> for processing the pathfinding
028 * <li> for plan generation
029 * </ol>
030 *
031 * @author Deepthought
032 *
033 */
034 public final class PlannerEngine implements Planner {
035
036 // XXX se på strategy pattern for at vælge kvilken pathfinder algoritme der
037 // skal bruges.
038 // Måske mest anvendeligt i spil!
039
040 /**
041 * Logger for this class.
042 */
043 private static final Log logger = LogFactory.getLog(PlannerEngine.class);
044
045 /**
046 * Mapping between id and pathfinder
047 */
048 private final HashMap<SuperLinkID, Pathfinder> idToPathfinder = new HashMap<SuperLinkID, Pathfinder>();
049
050 /**
051 * private singleton instance.
052 */
053 private static final Planner INSTANCE = new PlannerEngine();
054
055 /**
056 * Queue to facilitate generation of the graph.
057 */
058 private SidiousQueue<Goal> graphFactoryQueue = new SidiousQueue<Goal>(
059 "graphFactoryQueue") {
060
061 protected void process(Goal item) {
062 State start = ServiceEngine.getCurrentState();
063 pathfinderQueue.enqueue(GraphFactory.makeGraph(item.getOrigin(),
064 start, item.getGoalState()));
065 }
066 };
067
068 /**
069 * Queue to facilitate the path finding.
070 */
071 private SidiousQueue<Graph> pathfinderQueue = new SidiousQueue<Graph>(
072 "pathfinderQueue") {
073
074 @Override
075 protected void process(Graph item) {
076 Pathfinder p = new AStarAlgorithm();
077 idToPathfinder.put(item.getId(), p);
078 item.getGoalVertex().getState();
079 p.search(item);
080 planGeneratorQueue.enqueue(item);
081 }
082 };
083
084 /**
085 * Queue to handle the generation of a plan from a searched graph.
086 */
087 private SidiousQueue<Graph> planGeneratorQueue = new SidiousQueue<Graph>(
088 "planGeneratorQueue") {
089
090 @Override
091 protected void process(Graph item) {
092 Plan plan = PlanGenerator.generatePlan(item);
093 deliverPlan(plan);
094 }
095 };
096
097 /**
098 * Private constructor, to facilitate singleton.
099 */
100 private PlannerEngine() {
101 }
102
103 /**
104 * Delivers the finished plan to the blackboard.
105 *
106 * @param plan
107 * the finished plan
108 */
109 private void deliverPlan(Plan plan) {
110 Repository.getBlackboard().deliverResult(plan);
111 }
112
113 /**
114 * Returns the adjustables of the specified requester.
115 *
116 * @param requester
117 * the requester
118 * @return the adjustables of the requester
119 */
120 public static Collection<Adjustable> getAdjustables(SuperLinkID requester) {
121 return Repository.getBlackboard().getRequester(requester)
122 .getAdjustables();
123 }
124
125 /*
126 * (non-Javadoc)
127 *
128 * @see dk.deepthought.sidious.planner.Planner#stop(dk.deepthought.sidious.supportsystem.SuperLinkID)
129 */
130 public void stop(SuperLinkID id) {
131 if (logger.isDebugEnabled()) {
132 logger.debug("stop(SuperLinkID id=" + id
133 + ") - attempting to stop planning");
134 }
135 if (idToPathfinder.containsKey(id)) {
136 Pathfinder pathfinder = idToPathfinder.get(id);
137 pathfinder.cancel();
138 idToPathfinder.remove(id);
139 }
140 if (logger.isDebugEnabled()) {
141 logger.debug("stop(SuperLinkID id=" + id + ") - stopped planning");
142 }
143 }
144
145 /*
146 * (non-Javadoc)
147 *
148 * @see dk.deepthought.sidious.planner.Planner#requestPlan(dk.deepthought.sidious.goalhandler.Goal)
149 */
150 public void requestPlan(Goal goal) {
151 if (goal == null) {
152 throw new IllegalArgumentException("null not valid goal");
153 }
154 graphFactoryQueue.enqueue(goal);
155 }
156
157 /**
158 * Returns the singleton instance.
159 *
160 * @return the singleton instance
161 */
162 public static Planner getInstance() {
163 return INSTANCE;
164 }
165
166 }
|