bdi4jade

Plan/Goal Parameter

4/24/2014 11:06:07 PM

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);
 	}
 
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;
+	}
+
+}