bdi4jade

Plan dispatch

8/13/2014 3:07:03 PM

Details

diff --git a/bdi-jade/src/bdi4jade/core/Capability.java b/bdi-jade/src/bdi4jade/core/Capability.java
index d7de337..4fe0020 100644
--- a/bdi-jade/src/bdi4jade/core/Capability.java
+++ b/bdi-jade/src/bdi4jade/core/Capability.java
@@ -28,6 +28,7 @@ import java.io.Serializable;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.LinkedList;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.logging.Log;
@@ -205,6 +206,25 @@ public class Capability implements Serializable {
 		resetAgentCapabilities();
 	}
 
+	/**
+	 * Adds the set of plans of this capability that can achieve the given goal
+	 * to a map of candidate plans. It checks its plan library and the part
+	 * capabilities, recursively.
+	 * 
+	 * @param goal
+	 *            the goal to be achieved.
+	 * @param candidatePlansMap
+	 *            the map to which the set of plans that can achieve the goal
+	 *            should be added.
+	 */
+	public void addCandidatePlans(Goal goal,
+			Map<Capability, Set<Plan>> candidatePlansMap) {
+		candidatePlansMap.put(this, planLibrary.getCandidatePlans(goal));
+		for (Capability part : partCapabilities) {
+			part.addCandidatePlans(goal, candidatePlansMap);
+		}
+	}
+
 	final void addIntention(Intention intention) {
 		this.intentions.add(intention);
 	}
@@ -229,14 +249,25 @@ public class Capability implements Serializable {
 
 	/**
 	 * Checks if this capability has a plan that can process the given message.
+	 * It checks the plan library of this capabilities and, if cannot handle it,
+	 * it checks part capabilities, recursively.
 	 * 
 	 * @param msg
 	 *            the message to be checked.
 	 * @return true if this capability has at least a plan that can process the
 	 *         message.
 	 */
-	public boolean canProcess(ACLMessage msg) {
-		return this.planLibrary.canHandle(msg);
+	public boolean canHandle(ACLMessage msg) {
+		if (planLibrary.canHandle(msg)) {
+			return true;
+		} else {
+			for (Capability part : partCapabilities) {
+				if (part.canHandle(msg)) {
+					return true;
+				}
+			}
+		}
+		return false;
 	}
 
 	/**
diff --git a/bdi-jade/src/bdi4jade/core/GoalUpdateSet.java b/bdi-jade/src/bdi4jade/core/GoalUpdateSet.java
index 416a899..8d06df7 100644
--- a/bdi-jade/src/bdi4jade/core/GoalUpdateSet.java
+++ b/bdi-jade/src/bdi4jade/core/GoalUpdateSet.java
@@ -70,7 +70,7 @@ public class GoalUpdateSet {
 		private GoalDescription(Intention intention) {
 			this.goal = intention.getGoal();
 			this.status = intention.getStatus();
-			this.dispatcher = intention.getOwner();
+			this.dispatcher = intention.getDispatcher();
 			this.intention = intention;
 		}
 
diff --git a/bdi-jade/src/bdi4jade/core/Intention.java b/bdi-jade/src/bdi4jade/core/Intention.java
index c277fe5..0722bc1 100644
--- a/bdi-jade/src/bdi4jade/core/Intention.java
+++ b/bdi-jade/src/bdi4jade/core/Intention.java
@@ -56,16 +56,16 @@ import bdi4jade.plan.planbody.PlanBody;
 public class Intention {
 
 	private PlanBody currentPlan;
-	private final Capability owner;
+	private final Capability dispatcher;
 	private final Set<Plan> executedPlans;
 	private final Goal goal;
+	private final List<GoalListener> goalListeners;
 	private final Log log;
 	private final BDIAgent myAgent;
 	private boolean noLongerDesired;
-	private final Capability dispatcher;
+	private final Set<Capability> owners;
 	private boolean unachievable;
 	private boolean waiting;
-	private final List<GoalListener> goalListeners;
 
 	/**
 	 * Creates a new intention. It is associated with an agent and the goal that
@@ -102,19 +102,41 @@ public class Intention {
 		this.executedPlans = new HashSet<>();
 		this.currentPlan = null;
 		this.dispatcher = dispatcher;
-		this.owner = null; // TODO
+		this.owners = new HashSet<>(); // TODO
 		this.goalListeners = new LinkedList<>();
 	}
 
 	/**
+	 * Adds a listener to be notified when about goal events.
+	 * 
+	 * @param goalListener
+	 *            the listener to be notified.
+	 */
+	public void addGoalListener(GoalListener goalListener) {
+		synchronized (goalListeners) {
+			goalListeners.add(goalListener);
+		}
+	}
+
+	/**
 	 * Dispatches a new plan to try to achieve the intention goal. It looks for
 	 * plans that can achieve the goal that were not already tried and then
 	 * starts the plan. If all possible plans were already executed, the
 	 * intention is set to unachievable.
 	 */
 	private synchronized void dispatchPlan() {
-		// FIXME
-		Map<Capability, Set<Plan>> options = getCanAchievePlans();
+		Map<Capability, Set<Plan>> options = new HashMap<>();
+
+		if (owners.isEmpty()) {
+			for (Capability capability : myAgent.getAggregatedCapabilities()) {
+				capability.addCandidatePlans(goal, options);
+			}
+		} else {
+			for (Capability capability : owners) {
+				capability.addCandidatePlans(goal, options);
+			}
+		}
+
 		for (Set<Plan> plans : options.values()) {
 			plans.removeAll(executedPlans);
 		}
@@ -167,34 +189,12 @@ public class Intention {
 	}
 
 	/**
-	 * Returns all plans from the capabilities that can achieve the goal. If the
-	 * goal is associated with a capability, only the capability and its
-	 * children capabilities will be searched. Otherwise, all plan libraries
-	 * will be considered.
+	 * Returns the capability that dispatched this goal.
 	 * 
-	 * @return the set of plans that can achieve the goal.
+	 * @return the dispatcher.
 	 */
-	private Map<Capability, Set<Plan>> getCanAchievePlans() {
-		Map<Capability, Set<Plan>> plans = new HashMap<>();
-		if (dispatcher == null) {
-			for (Capability capability : myAgent.getAggregatedCapabilities()) {
-				Set<Plan> capabilityPlans = new HashSet<>();
-				getCanAchievePlans(capabilityPlans, capability);
-				plans.put(capability, capabilityPlans);
-			}
-		} else {
-			Set<Plan> capabilityPlans = new HashSet<>();
-			getCanAchievePlans(capabilityPlans, dispatcher);
-			plans.put(dispatcher, capabilityPlans);
-		}
-		return plans;
-	}
-
-	private void getCanAchievePlans(final Set<Plan> plans, Capability capability) {
-		plans.addAll(capability.getPlanLibrary().canAchievePlans(goal));
-		for (Capability child : capability.getPartCapabilities()) {
-			getCanAchievePlans(plans, child);
-		}
+	public Capability getDispatcher() {
+		return dispatcher;
 	}
 
 	/**
@@ -207,30 +207,30 @@ public class Intention {
 	}
 
 	/**
-	 * Returns the agent associated with this intention.
+	 * Returns all goal listeners.
 	 * 
-	 * @return the myAgent.
+	 * @return the goalListeners.
 	 */
-	public BDIAgent getMyAgent() {
-		return myAgent;
+	public List<GoalListener> getGoalListeners() {
+		return goalListeners;
 	}
 
 	/**
-	 * Returns the capability that owns this goal.
+	 * Returns the agent associated with this intention.
 	 * 
-	 * @return the owner.
+	 * @return the myAgent.
 	 */
-	public Capability getOwner() {
-		return owner;
+	public BDIAgent getMyAgent() {
+		return myAgent;
 	}
 
 	/**
-	 * Returns the capability that dispatched this goal.
+	 * Returns the set of capabilities that own this goal.
 	 * 
-	 * @return the dispatcher.
+	 * @return the owners.
 	 */
-	public Capability getDispatcher() {
-		return dispatcher;
+	public Set<Capability> getOwners() {
+		return owners;
 	}
 
 	/**
@@ -291,6 +291,19 @@ public class Intention {
 	}
 
 	/**
+	 * Removes a goal listener, so it will not be notified about the goal events
+	 * anymore.
+	 * 
+	 * @param goalListener
+	 *            the goal listener to be removed.
+	 */
+	public void removeGoalListener(GoalListener goalListener) {
+		synchronized (goalListeners) {
+			goalListeners.remove(goalListener);
+		}
+	}
+
+	/**
 	 * Makes this intention starts to try to achieve the goal. It changes the
 	 * goal status from {@link GoalStatus#WAITING} or
 	 * {@link GoalStatus#PLAN_FAILED} to {@link GoalStatus#TRYING_TO_ACHIEVE}.
@@ -315,38 +328,4 @@ public class Intention {
 		}
 	}
 
-	/**
-	 * Adds a listener to be notified when about goal events.
-	 * 
-	 * @param goalListener
-	 *            the listener to be notified.
-	 */
-	public void addGoalListener(GoalListener goalListener) {
-		synchronized (goalListeners) {
-			goalListeners.add(goalListener);
-		}
-	}
-
-	/**
-	 * Returns all goal listeners.
-	 * 
-	 * @return the goalListeners.
-	 */
-	public List<GoalListener> getGoalListeners() {
-		return goalListeners;
-	}
-
-	/**
-	 * Removes a goal listener, so it will not be notified about the goal events
-	 * anymore.
-	 * 
-	 * @param goalListener
-	 *            the goal listener to be removed.
-	 */
-	public void removeGoalListener(GoalListener goalListener) {
-		synchronized (goalListeners) {
-			goalListeners.remove(goalListener);
-		}
-	}
-
 }
diff --git a/bdi-jade/src/bdi4jade/message/BDIAgentMsgReceiver.java b/bdi-jade/src/bdi4jade/message/BDIAgentMsgReceiver.java
index 9af0b7a..4e414d9 100644
--- a/bdi-jade/src/bdi4jade/message/BDIAgentMsgReceiver.java
+++ b/bdi-jade/src/bdi4jade/message/BDIAgentMsgReceiver.java
@@ -67,7 +67,7 @@ public class BDIAgentMsgReceiver extends MsgReceiver {
 			Set<Capability> capabilities = new HashSet<Capability>();
 			for (Capability capability : getMyAgent()
 					.getAggregatedCapabilities()) {
-				if (capability.canProcess(msg)) {
+				if (capability.canHandle(msg)) {
 					capabilities.add(capability);
 				}
 			}
diff --git a/bdi-jade/src/bdi4jade/plan/PlanLibrary.java b/bdi-jade/src/bdi4jade/plan/PlanLibrary.java
index e08394c..855d5ba 100644
--- a/bdi-jade/src/bdi4jade/plan/PlanLibrary.java
+++ b/bdi-jade/src/bdi4jade/plan/PlanLibrary.java
@@ -120,47 +120,36 @@ public class PlanLibrary implements Serializable {
 	}
 
 	/**
-	 * Returns the set of plans that can achieve the given goal. It checks this
-	 * plan library and the plan library of the part capabilities, recursively.
+	 * Returns true if there is a plan that can handle the given message.
 	 * 
-	 * @param goal
-	 *            the goal to be achieved.
-	 * @return the set of plans that can achieve the goal.
+	 * @param message
+	 *            the message to be checked.
+	 * @return true if a plan can handle the message, false otherwise.
 	 */
-	public Set<Plan> canAchievePlans(Goal goal) {
-		Set<Plan> plans = new HashSet<Plan>();
+	public boolean canHandle(ACLMessage message) {
 		for (Plan plan : this.plans) {
-			if (plan.canAchieve(goal)) {
-				plans.add(plan);
+			if (plan.canProcess(message)) {
+				return true;
 			}
 		}
-		for (Capability child : capability.getPartCapabilities()) {
-			plans.addAll(child.getPlanLibrary().canAchievePlans(goal));
-		}
-		return plans;
+		return false;
 	}
 
 	/**
-	 * Returns true if there is a plan that can process the given message. It
-	 * checks this plan library and the plan library of the part capabilities,
-	 * recursively.
+	 * Returns the set of plans that can achieve the given goal.
 	 * 
-	 * @param message
-	 *            the message to be checked.
-	 * @return true if a plan can process the message, false otherwise.
+	 * @param goal
+	 *            the goal to be achieved.
+	 * @return the set of plans that can achieve the goal.
 	 */
-	public boolean canHandle(ACLMessage message) {
+	public Set<Plan> getCandidatePlans(Goal goal) {
+		Set<Plan> plans = new HashSet<Plan>();
 		for (Plan plan : this.plans) {
-			if (plan.canProcess(message)) {
-				return true;
-			}
-		}
-		for (Capability part : capability.getPartCapabilities()) {
-			if (part.getPlanLibrary().canHandle(message)) {
-				return true;
+			if (plan.canAchieve(goal)) {
+				plans.add(plan);
 			}
 		}
-		return false;
+		return plans;
 	}
 
 	/**