//----------------------------------------------------------------------------
// Copyright (C) 2011 Ingrid Nunes
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// To contact the authors:
// http://inf.ufrgs.br/prosoft/bdi4jade/
//
//----------------------------------------------------------------------------
package bdi4jade.plan;
import jade.lang.acl.ACLMessage;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import bdi4jade.core.Capability;
import bdi4jade.goal.Goal;
import bdi4jade.goal.GoalTemplateFactory;
import bdi4jade.goal.ParallelGoal;
import bdi4jade.goal.SequentialGoal;
import bdi4jade.plan.planbody.ParallelGoalPlanBody;
import bdi4jade.plan.planbody.SequentialGoalPlanBody;
/**
* This class represents the plan library of a capability. It aggregates the
* plans that can be used to achieve goals.
*
* @author Ingrid Nunes
*/
public class PlanLibrary implements Serializable {
private static final long serialVersionUID = 3038533629659859857L;
private Capability capability;
private final Set<Plan> plans;
/**
* The default constructor. It should be only used if persistence frameworks
* are used.
*/
protected PlanLibrary() {
this.plans = new HashSet<Plan>();
}
/**
* Creates a plan library associated with a capability.
*
* @param capability
* the capability with which this plan library is associated.
*/
public PlanLibrary(final Capability capability) {
this(capability, null);
}
/**
* Creates a plan library base associated with a capability and adds the
* plans in the provided set.
*
* @param capability
* the capability with which this plan library is associated.
* @param plans
* the initial plans
*/
public PlanLibrary(final Capability capability, Set<Plan> plans) {
if (capability == null)
throw new NullPointerException("Capability must be not null.");
this.capability = capability;
this.plans = new HashSet<Plan>();
if (plans != null) {
for (Plan plan : plans) {
addPlan(plan);
}
}
addDefaultPlans();
}
/**
* Adds a set of default plans to this library. It adds plans to achieve the
* sequential and parallel goals. This method may be overridden by children
* capabilities.
*/
protected void addDefaultPlans() {
addPlan(new DefaultPlan(
GoalTemplateFactory.goalOfType(SequentialGoal.class),
SequentialGoalPlanBody.class));
addPlan(new DefaultPlan(
GoalTemplateFactory.goalOfType(ParallelGoal.class),
ParallelGoalPlanBody.class));
}
/**
* Adds a plan to the plan library.
*
* @param plan
* the plan to be added.
*/
public void addPlan(Plan plan) {
if (plan.getPlanLibrary() != null) {
plan.getPlanLibrary().removePlan(plan);
}
plan.setPlanLibrary(this);
this.plans.add(plan);
}
/**
* Returns true if there is a plan that can achieve the given goal.
*
* @param goal
* the goal to be checked.
* @return true if a plan can achieve the goal, false otherwise.
*/
public boolean canAchieve(Goal goal) {
for (Plan plan : this.plans) {
if (plan.canAchieve(goal)) {
return true;
}
}
return false;
}
/**
* Returns true if there is a plan that can handle the given message.
*
* @param message
* the message to be checked.
* @return true if a plan can handle the message, false otherwise.
*/
public boolean canHandle(ACLMessage message) {
for (Plan plan : this.plans) {
if (plan.canProcess(message)) {
return true;
}
}
return false;
}
/**
* Returns the set of plans that can achieve the given goal.
*
* @param goal
* the goal to be achieved.
* @return the set of plans that can achieve the goal.
*/
public Set<Plan> getCandidatePlans(Goal goal) {
Set<Plan> plans = new HashSet<Plan>();
for (Plan plan : this.plans) {
if (plan.canAchieve(goal)) {
plans.add(plan);
}
}
return plans;
}
/**
* Returns the capability with which this plan library is associated.
*
* @return the capability.
*/
public Capability getCapability() {
return capability;
}
/**
* Returns the set of plans that are part of this plan library.
*
* @return the plans.
*/
public Set<Plan> getPlans() {
return plans;
}
/**
* Checks if a plan is part of the plan library.
*
* @param plan
* the plan to be checked
* @return true if the plan library contains the plan.
*/
public boolean hasPlan(Plan plan) {
return this.plans.contains(plan);
}
/**
* Removes a plan from the plan library.
*
* @param plan
* the plan to be removed.
* @return true if the plan was removed, false otherwise.
*/
public boolean removePlan(Plan plan) {
boolean removed = this.plans.remove(plan);
if (removed) {
plan.setPlanLibrary(null);
}
return removed;
}
}