
jason.asSyntax.PlanLibrary Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jason Show documentation
Show all versions of jason Show documentation
Jason is a fully-fledged interpreter for an extended version of AgentSpeak, a BDI agent-oriented logic programming language.
//----------------------------------------------------------------------------
// Copyright (C) 2003 Rafael H. Bordini, Jomi F. Hubner, et al.
//
// 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://www.inf.ufrgs.br/~bordini
// http://www.das.ufsc.br/~jomi
//
//----------------------------------------------------------------------------
package jason.asSyntax;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import jason.JasonException;
import jason.asSyntax.Trigger.TEOperator;
import jason.asSyntax.Trigger.TEType;
import jason.asSyntax.parser.ParseException;
import jason.bb.BeliefBase;
import jason.util.Config;
/** Represents a set of plans used by an agent
@has - plans 0..* Plan
*/
public class PlanLibrary implements Iterable {
/** a MAP from TE to a list of relevant plans */
private Map> relPlans = new ConcurrentHashMap>();
/**
* All plans as defined in the AS code (maintains the order of the plans)
*/
private List plans = new ArrayList();
/** list of plans that have var as TE */
private List varPlans = new ArrayList();
/** A map from labels to plans */
private Map planLabels = new ConcurrentHashMap();
private boolean hasMetaEventPlans = false;
private static AtomicInteger lastPlanLabel = new AtomicInteger(0);
private boolean hasUserKqmlReceived = false;
//private Logger logger = Logger.getLogger(PlanLibrary.class.getName());
private final Object lockPL = new Object();
public Object getLock() {
return lockPL;
}
/**
* Add a new plan written as a String. The source
* normally is "self" or the agent that sent this plan.
* If the PL already has a plan equals to "stPlan", only a
* new source is added.
*
* The plan is added in the end of the PlanLibrary.
*
* @returns the plan just added
* @deprecated parse the plan before (ASSyntax methods) and call add(Plan, ...) methods
*/
public Plan add(StringTerm stPlan, Term tSource) throws ParseException, JasonException {
return add(stPlan, tSource, false);
}
/**
* Add a new plan written as a String. The source
* normally is "self" or the agent that sent this plan.
* If the PL already has a plan equals to "stPlan", only a
* new source is added.
*
* If before is true, the plan will be added in the
* begin of the PlanLibrary; otherwise, it is added in
* the end.
*
* @returns the plan just added
* @deprecated parse the plan before (ASSyntax methods) and call add(Plan, ...) methods
*/
public Plan add(StringTerm stPlan, Term tSource, boolean before) throws ParseException, JasonException {
String sPlan = stPlan.getString();
// remove quotes \" -> "
StringBuilder sTemp = new StringBuilder();
for (int c=0; c before is true, the plan will be added in the
* begin of the PlanLibrary; otherwise, it is added in
* the end.
*
* @returns the plan just added
*/
public Plan add(Plan p, Term source, boolean before) throws JasonException {
synchronized (lockPL) {
int i = plans.indexOf(p);
if (i < 0) {
// add label, if necessary
if (p.getLabel() == null)
p.setLabel(getUniqueLabel());
p.getLabel().addSource(source);
add(p, before);
} else {
p = plans.get(i);
p.getLabel().addSource(source);
}
return p;
}
}
public void add(Plan p) throws JasonException {
add(p,false);
}
private final String kqmlReceivedFunctor = Config.get().getKqmlFunctor();
/**
* Adds a plan into the plan library, either before or after all other
* plans depending on the boolean parameter.
*
* @param p The plan to be added to the plan library
* @param before Whether or not to place the new plan before others
* @throws JasonException
*/
public void add(Plan p, boolean before) throws JasonException {
synchronized (lockPL) {
// test p.label
if (p.getLabel() != null && planLabels.keySet().contains( getStringForLabel(p.getLabel()))) {
// test if the new plan is equal, in this case, just add a source
Plan planInPL = get(p.getLabel());
if (p.equals(planInPL)) {
planInPL.getLabel().addSource(p.getLabel().getSources().get(0));
return;
} else {
throw new JasonException("There already is a plan with label " + p.getLabel());
}
}
// add label, if necessary
if (p.getLabel() == null)
p.setLabel(getUniqueLabel());
// add self source
if (!p.getLabel().hasSource())
p.getLabel().addAnnot(BeliefBase.TSelf);
if (p.getTrigger().getLiteral().getFunctor().equals(kqmlReceivedFunctor)) {
if (! (p.getSrcInfo() != null && "kqmlPlans.asl".equals(p.getSrcInfo().getSrcFile()))) {
hasUserKqmlReceived = true;
}
}
p.setAsPlanTerm(false); // it is not a term anymore
planLabels.put( getStringForLabel(p.getLabel()), p);
Trigger pte = p.getTrigger();
if (pte.getLiteral().isVar() || pte.getLiteral().getNS().isVar()) {
if (before)
varPlans.add(0,p);
else
varPlans.add(p);
// add plan p in all entries
for (List lp: relPlans.values())
if (!lp.isEmpty() && lp.get(0).getTrigger().sameType(pte)) // only add if same type
if (before)
lp.add(0,p);
else
lp.add(p);
} else {
List codesList = relPlans.get(pte.getPredicateIndicator());
if (codesList == null) {
codesList = new ArrayList();
// copy plans from var plans
for (Plan vp: varPlans)
if (vp.getTrigger().sameType(pte))
codesList.add(vp);
relPlans.put(pte.getPredicateIndicator(), codesList);
}
if (before)
codesList.add(0,p);
else
codesList.add(p);
}
if (pte.getOperator() == TEOperator.goalState)
hasMetaEventPlans = true;
if (before)
plans.add(0,p);
else
plans.add(p);
}
}
public void addAll(PlanLibrary pl) throws JasonException {
synchronized (lockPL) {
for (Plan p: pl) {
add(p, false);
}
}
}
public void addAll(List plans) throws JasonException {
synchronized (lockPL) {
for (Plan p: plans) {
add(p, false);
}
}
}
private String getStringForLabel(Atom p) {
if (p.getNS() == Literal.DefaultNS)
return p.getFunctor();
else
return p.getNS()+"::"+p.getFunctor();
}
public boolean hasMetaEventPlans() {
return hasMetaEventPlans;
}
public boolean hasUserKqmlReceivedPlans() {
return hasUserKqmlReceived;
}
/** add a label to the plan */
private Pred getUniqueLabel() {
String l;
do {
l = "l__" + (lastPlanLabel.incrementAndGet());
} while (planLabels.keySet().contains(l));
return new Pred(l);
}
/** return a plan for a label */
public Plan get(String label) {
return get(new Atom(label));
}
/** return a plan for a label */
public Plan get(Atom label) {
return planLabels.get(getStringForLabel(label));
}
public int size() {
return plans.size();
}
public List getPlans() {
return plans;
}
public Iterator iterator() {
return plans.iterator();
}
/** remove all plans */
public void clear() {
planLabels.clear();
plans.clear();
varPlans.clear();
relPlans.clear();
}
/**
* Remove a plan represented by the label pLabel.
* In case the plan has many sources, only the plan's source is removed.
*/
public boolean remove(Atom pLabel, Term source) {
// find the plan
Plan p = get(pLabel);
if (p != null) {
boolean hasSource = p.getLabel().delSource(source);
// if no source anymore, remove the plan
if (hasSource && !p.getLabel().hasSource()) {
remove(pLabel);
}
return true;
}
return false;
}
/** remove the plan with label pLabel */
public Plan remove(Atom pLabel) {
synchronized (lockPL) {
Plan p = planLabels.remove( getStringForLabel(pLabel) );
// remove it from plans' list
plans.remove(p);
if (p.getTrigger().getLiteral().isVar()) {
varPlans.remove(p);
// remove p from all entries and
// clean empty entries
Iterator ipi = relPlans.keySet().iterator();
while (ipi.hasNext()) {
PredicateIndicator pi = ipi.next();
List lp = relPlans.get(pi);
lp.remove(p);
if (lp.isEmpty()) {
ipi.remove();
}
}
} else {
List codesList = relPlans.get(p.getTrigger().getPredicateIndicator());
codesList.remove(p);
if (codesList.isEmpty()) {
// no more plans for this TE
relPlans.remove(p.getTrigger().getPredicateIndicator());
}
}
return p;
}
}
/** @deprecated use hasCandidatePlan(te) instead */
public boolean isRelevant(Trigger te) {
return hasCandidatePlan(te);
}
public boolean hasCandidatePlan(Trigger te) {
if (te == null)
return false;
else
return getCandidatePlans(te) != null;
}
/** @deprecated use getCandidatePlans(te) instead */
public List getAllRelevant(Trigger te) {
return getCandidatePlans(te);
}
public List getCandidatePlans(Trigger te) {
synchronized (lockPL) {
List l = null;
if (te.getLiteral().isVar() || te.getNS().isVar()) { // add all plans!
for (Plan p: this)
if (p.getTrigger().sameType(te)) {
if (l == null)
l = new ArrayList();
l.add(p);
}
} else {
l = relPlans.get(te.getPredicateIndicator());
if ((l == null || l.isEmpty()) && !varPlans.isEmpty() && te != TE_JAG_SLEEPING && te != TE_JAG_AWAKING) { // no rel plan, try varPlan
for (Plan p: varPlans)
if (p.getTrigger().sameType(te)) {
if (l == null)
l = new ArrayList();
l.add(p);
}
}
}
return l; // if no rel plan, have to return null instead of empty list
}
}
public static final Trigger TE_JAG_SLEEPING = new Trigger(TEOperator.add, TEType.achieve, new Atom("jag_sleeping"));
public static final Trigger TE_JAG_AWAKING = new Trigger(TEOperator.add, TEType.achieve, new Atom("jag_awaking"));
public PlanLibrary clone() {
PlanLibrary pl = new PlanLibrary();
try {
synchronized (lockPL) {
for (Plan p: this) {
pl.add((Plan)p.clone(), false);
}
}
} catch (JasonException e) {
e.printStackTrace();
}
return pl;
}
public String toString() {
return plans.toString();
}
/** get as XML */
public Element getAsDOM(Document document) {
Element eplans = (Element) document.createElement("plans");
String lastFunctor = null;
synchronized (lockPL) {
for (Plan p: plans) {
String currentFunctor = p.getTrigger().getLiteral().getFunctor();
if (lastFunctor != null && !currentFunctor.equals(lastFunctor)) {
eplans.appendChild((Element) document.createElement("new-set-of-plans"));
}
lastFunctor = currentFunctor;
eplans.appendChild(p.getAsDOM(document));
}
}
return eplans;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy