bdi4jade
Changes
bdi-jade/src/bdi4jade/util/ReflectionUtils.java 85(+62 -23)
Details
diff --git a/bdi-jade/src/bdi4jade/plan/AbstractPlanBody.java b/bdi-jade/src/bdi4jade/plan/AbstractPlanBody.java
index a00beff..8f53c80 100644
--- a/bdi-jade/src/bdi4jade/plan/AbstractPlanBody.java
+++ b/bdi-jade/src/bdi4jade/plan/AbstractPlanBody.java
@@ -33,9 +33,11 @@ import bdi4jade.belief.BeliefBase;
import bdi4jade.core.Intention;
import bdi4jade.event.GoalEvent;
import bdi4jade.event.GoalFinishedEvent;
+import bdi4jade.exception.ParameterException;
import bdi4jade.exception.PlanInstantiationException;
import bdi4jade.goal.Goal;
import bdi4jade.plan.Plan.EndState;
+import bdi4jade.util.ReflectionUtils;
/**
* This class represents a plan that has been instantiated to be executed.
@@ -301,7 +303,8 @@ public abstract class AbstractPlanBody extends Behaviour implements PlanBody {
* Initializes this plan body. It associates this plan body with a plan
* definition ({@link Plan}) and an {@link Intention}. If this plan body has
* already been initialized, this method throws a
- * {@link PlanInstantiationException}.
+ * {@link PlanInstantiationException}. It also sets up the plan input
+ * parameters based on the goal input parameters.
*
* @param plan
* the plan associated this this plan body.
@@ -318,6 +321,11 @@ public abstract class AbstractPlanBody extends Behaviour implements PlanBody {
}
this.plan = plan;
this.intention = intention;
+ try {
+ ReflectionUtils.setPlanBodyInput(this, intention.getGoal());
+ } catch (ParameterException exc) {
+ throw new PlanInstantiationException(exc);
+ }
}
/**
@@ -330,6 +338,13 @@ public abstract class AbstractPlanBody extends Behaviour implements PlanBody {
if (this.endState != null) {
if (this instanceof OutputPlanBody) {
((OutputPlanBody) this).setGoalOutput(getGoal());
+ } else {
+ try {
+ ReflectionUtils.setPlanBodyOutput(this,
+ intention.getGoal());
+ } catch (ParameterException exc) {
+ // FIXME what to do
+ }
}
dropSubgoals();
}
@@ -342,7 +357,7 @@ public abstract class AbstractPlanBody extends Behaviour implements PlanBody {
public final void start() {
this.intention.getMyAgent().addBehaviour(this);
}
-
+
/**
* Stops the plan body, a {@link Behaviour}, associated with this plan. If
* the body implements the {@link DisposablePlanBody}, it invokes the method
diff --git a/bdi-jade/src/bdi4jade/util/plan/SequentialGoalPlanBody.java b/bdi-jade/src/bdi4jade/util/plan/SequentialGoalPlanBody.java
index 19e3722..496e28d 100644
--- a/bdi-jade/src/bdi4jade/util/plan/SequentialGoalPlanBody.java
+++ b/bdi-jade/src/bdi4jade/util/plan/SequentialGoalPlanBody.java
@@ -31,7 +31,7 @@ import org.apache.commons.logging.LogFactory;
import bdi4jade.annotation.Parameter;
import bdi4jade.event.GoalFinishedEvent;
-import bdi4jade.exception.GoalParameterException;
+import bdi4jade.exception.ParameterException;
import bdi4jade.goal.Goal;
import bdi4jade.goal.GoalStatus;
import bdi4jade.plan.AbstractPlanBody;
@@ -78,7 +78,7 @@ public class SequentialGoalPlanBody extends AbstractPlanBody implements
try {
setNextGoal(this.completedGoals.get(this.completedGoals
.size() - 1), this.currentGoal);
- } catch (GoalParameterException gpe) {
+ } catch (ParameterException gpe) {
log.error(gpe);
gpe.printStackTrace();
setEndState(EndState.FAILED);
@@ -143,7 +143,7 @@ public class SequentialGoalPlanBody extends AbstractPlanBody implements
* setting up the next goal.
*/
protected void setNextGoal(Goal previousGoal, Goal goal)
- throws GoalParameterException {
+ throws ParameterException {
ReflectionUtils.setupParameters(previousGoal, goal);
}
bdi-jade/src/bdi4jade/util/ReflectionUtils.java 85(+62 -23)
diff --git a/bdi-jade/src/bdi4jade/util/ReflectionUtils.java b/bdi-jade/src/bdi4jade/util/ReflectionUtils.java
index 796cf28..bb32dc0 100644
--- a/bdi-jade/src/bdi4jade/util/ReflectionUtils.java
+++ b/bdi-jade/src/bdi4jade/util/ReflectionUtils.java
@@ -29,8 +29,9 @@ import org.apache.commons.logging.LogFactory;
import bdi4jade.annotation.Parameter;
import bdi4jade.annotation.Parameter.Direction;
-import bdi4jade.exception.GoalParameterException;
+import bdi4jade.exception.ParameterException;
import bdi4jade.goal.Goal;
+import bdi4jade.plan.PlanBody;
/**
* @author Ingrid Nunes
@@ -43,9 +44,9 @@ public abstract class ReflectionUtils {
private static final String SETTER_PREFIX = "set";
private static void checkSkipIsOK(Parameter parameter, String msg,
- Exception cause) throws GoalParameterException {
+ Exception cause) throws ParameterException {
if (parameter.mandatory()) {
- GoalParameterException exc = new GoalParameterException(msg, cause);
+ ParameterException exc = new ParameterException(msg, cause);
log.warn(exc);
throw exc;
}
@@ -61,6 +62,15 @@ public abstract class ReflectionUtils {
return true;
}
+ private static boolean isParameterIn(Parameter param, Direction[] directions) {
+ for (Direction dir : directions) {
+ if (dir.equals(param.direction())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
protected static boolean isSetter(Method method) {
if (!method.getName().startsWith(SETTER_PREFIX))
return false;
@@ -81,43 +91,72 @@ public abstract class ReflectionUtils {
+ property.substring(1);
}
+ public static void setPlanBodyInput(PlanBody planBody, Goal goal)
+ throws ParameterException {
+ setupParameters(planBody, new Direction[] { Direction.IN,
+ Direction.INOUT }, goal, new Direction[] { Direction.IN,
+ Direction.INOUT });
+ }
+
+ public static void setPlanBodyOutput(PlanBody planBody, Goal goal)
+ throws ParameterException {
+ setupParameters(goal,
+ new Direction[] { Direction.OUT, Direction.INOUT }, planBody,
+ new Direction[] { Direction.OUT, Direction.INOUT });
+ }
+
public static void setupParameters(Goal goalOut, Goal goalIn)
- throws GoalParameterException {
- for (Method method : goalIn.getClass().getMethods()) {
+ throws ParameterException {
+ setupParameters(goalIn,
+ new Direction[] { Direction.IN, Direction.INOUT }, goalOut,
+ new Direction[] { Direction.OUT, Direction.INOUT });
+ }
+
+ private static void setupParameters(Object obj1, Direction[] dir1,
+ Object obj2, Direction[] dir2) throws ParameterException {
+ for (Method method : obj1.getClass().getMethods()) {
if (method.isAnnotationPresent(Parameter.class)) {
Parameter parameter = method.getAnnotation(Parameter.class);
- if (Direction.OUT.equals(parameter.direction())) {
+ if (!isParameterIn(parameter, dir1)) {
continue;
}
- if (!isGetter(method)) {
+
+ if (!(isGetter(method) || isSetter(method))) {
checkSkipIsOK(parameter, "Method " + method
- + " should be a getter.", null);
+ + " should be a getter or setter.", null);
continue;
}
- String property = methodToPropertyName(GETTER_PREFIX, method);
+ String property = null;
Method setter = null;
- try {
- setter = goalIn.getClass().getMethod(
- propertyToMethodName(SETTER_PREFIX, property),
- method.getReturnType());
- } catch (NoSuchMethodException nsme) {
- checkSkipIsOK(parameter,
- "There is no setter method associated with property "
- + property, nsme);
- continue;
+
+ if (isGetter(method)) {
+ property = methodToPropertyName(GETTER_PREFIX, method);
+ try {
+ setter = obj1.getClass().getMethod(
+ propertyToMethodName(SETTER_PREFIX, property),
+ method.getReturnType());
+ } catch (NoSuchMethodException nsme) {
+ checkSkipIsOK(parameter,
+ "There is no setter method associated with property "
+ + property, nsme);
+ continue;
+ }
+ } else {
+ property = methodToPropertyName(SETTER_PREFIX, method);
+ setter = method;
}
Method getter = null;
try {
- getter = goalOut.getClass().getMethod(
+ getter = obj2.getClass().getMethod(
propertyToMethodName(GETTER_PREFIX, property));
if (!getter.isAnnotationPresent(Parameter.class)
- || Direction.IN.equals(getter.getAnnotation(
- Parameter.class).direction())) {
+ || !isParameterIn(
+ getter.getAnnotation(Parameter.class), dir2)) {
checkSkipIsOK(parameter,
- "There is no output parameter associated with method "
+ "There is no parameter associated with method "
+ method + " name " + property, null);
continue;
}
@@ -129,7 +168,7 @@ public abstract class ReflectionUtils {
}
try {
- setter.invoke(goalIn, getter.invoke(goalOut));
+ setter.invoke(obj1, getter.invoke(obj2));
} catch (Exception exc) {
checkSkipIsOK(parameter, "An unknown error occurrred.", exc);
}
diff --git a/bdi-jade-test/src/bdi4jade/examples/AgentStarter.java b/bdi-jade-test/src/bdi4jade/examples/AgentStarter.java
index a9435d8..db01673 100644
--- a/bdi-jade-test/src/bdi4jade/examples/AgentStarter.java
+++ b/bdi-jade-test/src/bdi4jade/examples/AgentStarter.java
@@ -38,6 +38,9 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.PropertyConfigurator;
+import bdi4jade.examples.helloworld.HelloWorldAgent;
+import bdi4jade.examples.planparameter.HelloWorldParamAgent;
+
/**
* @author ingrid
*
@@ -48,9 +51,10 @@ public class AgentStarter {
static {
agents = new HashMap<String, Agent>();
- // agents.put(HelloWorldAgent.class.getSimpleName(), new
- // HelloWorldAgent());
- agents.put(BDIAgent1.MY_NAME, new BDIAgent1());
+ agents.put(HelloWorldAgent.class.getSimpleName(), new HelloWorldAgent());
+ agents.put(HelloWorldParamAgent.class.getSimpleName(),
+ new HelloWorldParamAgent());
+ // agents.put(BDIAgent1.MY_NAME, new BDIAgent1());
// agents.put(BDIAgent2.MY_NAME, new BDIAgent2());
// agents.put(MyAgent.class.getSimpleName(), new MyAgent());
// agents.put(NestedCapabilitiesAgent.class.getSimpleName(),
diff --git a/bdi-jade-test/src/bdi4jade/examples/planparameter/HelloWorldParamAgent.java b/bdi-jade-test/src/bdi4jade/examples/planparameter/HelloWorldParamAgent.java
new file mode 100644
index 0000000..e2048bd
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/planparameter/HelloWorldParamAgent.java
@@ -0,0 +1,89 @@
+//----------------------------------------------------------------------------
+// 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/~ingridnunes/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.examples.planparameter;
+
+import bdi4jade.annotation.Parameter;
+import bdi4jade.annotation.Parameter.Direction;
+import bdi4jade.core.BDIAgent;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.event.GoalFinishedEvent;
+import bdi4jade.event.GoalListener;
+import bdi4jade.goal.Goal;
+import bdi4jade.plan.SimplePlan;
+
+public class HelloWorldParamAgent extends BDIAgent implements GoalListener {
+
+ public class HelloWorldParamGoal implements Goal {
+
+ private static final long serialVersionUID = -9039447524062487795L;
+
+ private String name;
+ private long time;
+
+ public HelloWorldParamGoal(String name) {
+ this.name = name;
+ }
+
+ @Parameter(direction = Direction.IN)
+ public String getName() {
+ return name;
+ }
+
+ public void setTime(long time) {
+ this.time = time;
+ }
+
+ @Parameter(direction = Direction.OUT)
+ public long getTime() {
+ return time;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " - name: " + name
+ + " / time: " + time;
+ }
+
+ }
+
+ private static final long serialVersionUID = 2712019445290687786L;
+
+ protected void init() {
+ this.getRootCapability()
+ .getPlanLibrary()
+ .addPlan(
+ new SimplePlan(HelloWorldParamGoal.class,
+ HelloWorldParamPlan.class));
+
+ addGoal(new HelloWorldParamGoal("reader"), this);
+ }
+
+ @Override
+ public void goalPerformed(GoalEvent event) {
+ if (event instanceof GoalFinishedEvent) {
+ System.out.println("Hello World Goal Finished! Time: "
+ + event.getGoal());
+ }
+ }
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/planparameter/HelloWorldParamPlan.java b/bdi-jade-test/src/bdi4jade/examples/planparameter/HelloWorldParamPlan.java
new file mode 100644
index 0000000..88c21f2
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/planparameter/HelloWorldParamPlan.java
@@ -0,0 +1,57 @@
+//----------------------------------------------------------------------------
+// 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/~ingridnunes/bdi4jade/
+//
+//----------------------------------------------------------------------------
+
+package bdi4jade.examples.planparameter;
+
+import bdi4jade.annotation.Parameter;
+import bdi4jade.annotation.Parameter.Direction;
+import bdi4jade.plan.AbstractPlanBody;
+import bdi4jade.plan.Plan.EndState;
+
+/**
+ * @author ingridn
+ *
+ */
+public class HelloWorldParamPlan extends AbstractPlanBody {
+
+ private static final long serialVersionUID = -9039447524062487795L;
+
+ private String name;
+ private long time;
+
+ public void action() {
+ System.out.println("Hello, " + name + "!");
+ this.time = System.currentTimeMillis();
+ setEndState(EndState.SUCCESSFULL);
+ }
+
+ @Parameter(direction = Direction.OUT)
+ public long getTime() {
+ return time;
+ }
+
+ @Parameter(direction = Direction.IN)
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}