bdi4jade

Changes

Details

diff --git a/bdi-jade-extensions/.classpath b/bdi-jade-extensions/.classpath
index 42c9295..8451364 100644
--- a/bdi-jade-extensions/.classpath
+++ b/bdi-jade-extensions/.classpath
@@ -1,11 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/bdi-jade"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
+		<attributes>
+			<attribute name="module" value="true"/>
+		</attributes>
+	</classpathentry>
 	<classpathentry kind="lib" path="/bdi-jade/lib/commons-logging-1.1.3.jar"/>
 	<classpathentry kind="lib" path="/bdi-jade/lib/jade-4.3.2.jar"/>
 	<classpathentry kind="lib" path="/bdi-jade/lib/log4j-1.2.17.jar"/>
 	<classpathentry kind="lib" path="lib/weka.jar"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/bdi-jade"/>
+	<classpathentry kind="lib" path="lib/mongo-java-driver-3.9.1.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/bdi-jade-extensions/lib/commons-codec-1.14.jar b/bdi-jade-extensions/lib/commons-codec-1.14.jar
new file mode 100644
index 0000000..49ffa9b
Binary files /dev/null and b/bdi-jade-extensions/lib/commons-codec-1.14.jar differ
diff --git a/bdi-jade-extensions/lib/mongo-java-driver-3.9.1.jar b/bdi-jade-extensions/lib/mongo-java-driver-3.9.1.jar
new file mode 100644
index 0000000..b792545
Binary files /dev/null and b/bdi-jade-extensions/lib/mongo-java-driver-3.9.1.jar differ
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/remediation/goal/CauseFactorStatus.java b/bdi-jade-extensions/src/bdi4jade/extension/remediation/goal/CauseFactorStatus.java
index 3ce3bef..ca7360f 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/remediation/goal/CauseFactorStatus.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/remediation/goal/CauseFactorStatus.java
@@ -27,6 +27,7 @@ public class CauseFactorStatus {
 	}
 
 	public PredicateGoal<?> generateAchievementGoal() {
+		System.out.println("generateAchievementGoal: " + this.fact.getPredicate() + "<" + !this.fact.getValue() + ">");
 		this.achievementGoal = new PredicateGoal(this.fact.getPredicate(), !this.fact.getValue());
 		return (PredicateGoal<?>) this.achievementGoal;
 	}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/remediation/graph/CauseEffectKnowledgeModel.java b/bdi-jade-extensions/src/bdi4jade/extension/remediation/graph/CauseEffectKnowledgeModel.java
index 6f7dc2f..827c6b1 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/remediation/graph/CauseEffectKnowledgeModel.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/remediation/graph/CauseEffectKnowledgeModel.java
@@ -6,7 +6,6 @@ import java.util.Map;
 import bdi4jade.belief.TransientBelief;
 import bdi4jade.extension.remediation.logics.Fact;
 import bdi4jade.extension.remediation.logics.Predicate;
-import bdi4jade.goal.BeliefValueGoal;
 import bdi4jade.goal.Goal;
 import bdi4jade.goal.PredicateGoal;
 
@@ -38,5 +37,9 @@ public class CauseEffectKnowledgeModel extends TransientBelief<String, Map<Fact,
 	public boolean isEffect(Fact fact) {
 		return getValue().containsKey(fact);
 	}
+	
+	public boolean removeCauseEffectRelationship(CauseEffectRelationship causes) {
+		return this.getValue().remove(causes.getEffect()) != null;
+	}
 
 }
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/remediation/graph/TransientCauseEffectRelationship.java b/bdi-jade-extensions/src/bdi4jade/extension/remediation/graph/TransientCauseEffectRelationship.java
new file mode 100644
index 0000000..60d24c4
--- /dev/null
+++ b/bdi-jade-extensions/src/bdi4jade/extension/remediation/graph/TransientCauseEffectRelationship.java
@@ -0,0 +1,15 @@
+package bdi4jade.extension.remediation.graph;
+
+import bdi4jade.extension.remediation.logics.Fact;
+
+/*
+ * A temporary CauseEffectRelationship that is removed from a Cause Effect Model after being consulted once.
+ */
+
+public class TransientCauseEffectRelationship extends CauseEffectRelationship {
+
+	public TransientCauseEffectRelationship(Fact effect) {
+		super(effect);
+	}
+
+}
diff --git a/bdi-jade-extensions/src/bdi4jade/extension/remediation/reasoning/RemediationOptionGenerationFunction.java b/bdi-jade-extensions/src/bdi4jade/extension/remediation/reasoning/RemediationOptionGenerationFunction.java
index 44adc8e..9cdd151 100644
--- a/bdi-jade-extensions/src/bdi4jade/extension/remediation/reasoning/RemediationOptionGenerationFunction.java
+++ b/bdi-jade-extensions/src/bdi4jade/extension/remediation/reasoning/RemediationOptionGenerationFunction.java
@@ -21,6 +21,7 @@ import bdi4jade.extension.remediation.goal.CauseFactorStatus;
 import bdi4jade.extension.remediation.graph.AlternativeCauseSet;
 import bdi4jade.extension.remediation.graph.CauseEffectKnowledgeModel;
 import bdi4jade.extension.remediation.graph.CauseEffectRelationship;
+import bdi4jade.extension.remediation.graph.TransientCauseEffectRelationship;
 import bdi4jade.extension.remediation.logics.Fact;
 import bdi4jade.extension.remediation.logics.Predicate;
 import bdi4jade.extension.undo.GoalAchievementMetadata;
@@ -86,6 +87,12 @@ public class RemediationOptionGenerationFunction extends RevertingOptionGenerati
 			if (cep == null && cer != null) {
 				cep = new CauseEffectProblem((PredicateGoal<?>) goal, cer, capability.getMyAgent(), parentGoal);
 				causeEffectProblems.put(cep.getEffectGoal(), cep);
+				
+				// TODO Maybe this snippet should not be here.
+				// Here we guarantee that a temporary cause effect relationship will be removed after investigated.
+				if(cer instanceof TransientCauseEffectRelationship) {
+					getCauseEffectKnowledgeModel().removeCauseEffectRelationship(cer);
+				}
 
 				// Here a new goal achievement metadata is created
 				if (this.capability instanceof RemediationCapability) {
@@ -108,7 +115,7 @@ public class RemediationOptionGenerationFunction extends RevertingOptionGenerati
 			}
 
 			// Algorithm 1 - lines 18-35
-			if (cep.getEffectGoalStatus() != null) {
+			if (cep.getEffectGoalStatus() != null && !cep.getCauseFactorStatus().isEmpty()) {
 				if (knownCause(cep, cep.getCauseEffectRelationship())) {
 
 					// Reversion trigger is updated with current cause factor predicates
@@ -160,6 +167,10 @@ public class RemediationOptionGenerationFunction extends RevertingOptionGenerati
 		super.generateGoals(goalUpdateSet);
 	}
 
+	public Map<Goal, CauseEffectProblem> getCauseEffectProblems() {
+		return this.causeEffectProblems;
+	}
+	
 	private Boolean knownCause(CauseEffectProblem cep, CauseEffectRelationship cer) {
 		for (CauseFactorStatus cf : cep.getCauseFactorStatus()) {
 			if (cf.getInitialStatus() == null) {
diff --git a/bdi-jade-test/.classpath b/bdi-jade-test/.classpath
index 018dcc4..634df7d 100644
--- a/bdi-jade-test/.classpath
+++ b/bdi-jade-test/.classpath
@@ -1,11 +1,17 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/bdi-jade"/>
-	<classpathentry kind="lib" path="/bdi-jade/lib/jade-4.3.2.jar"/>
-	<classpathentry kind="lib" path="/bdi-jade/lib/commons-logging-1.1.3.jar"/>
-	<classpathentry kind="lib" path="/bdi-jade/lib/log4j-1.2.17.jar"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/bdi-jade-extensions"/>
-	<classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/bdi-jade"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/bdi-jade-extensions"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
+		<attributes>
+			<attribute name="module" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="lib" path="/bdi-jade/lib/jade-4.3.2.jar"/>
+	<classpathentry kind="lib" path="/bdi-jade/lib/commons-logging-1.1.3.jar"/>
+	<classpathentry kind="lib" path="/bdi-jade/lib/log4j-1.2.17.jar"/>
+	<classpathentry kind="lib" path="/bdi-jade-extensions/lib/mongo-java-driver-3.9.1.jar"/>
+	<classpathentry kind="lib" path="/bdi-jade-extensions/lib/commons-codec-1.14.jar"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/CauseAnalysisCapability.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/CauseAnalysisCapability.java
new file mode 100644
index 0000000..df44ecb
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/CauseAnalysisCapability.java
@@ -0,0 +1,200 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import bdi4jade.annotation.Belief;
+import bdi4jade.core.BDIAgent;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.domain.predicate.Abnormal;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousCommunication;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousComponent;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousLink;
+import bdi4jade.examples.interactionprotocol.goal.ChangeServiceProviderGoal;
+import bdi4jade.examples.interactionprotocol.goal.ProvideAnomalousProbabilityGoal;
+import bdi4jade.examples.interactionprotocol.goal.ProvideServiceGoal;
+import bdi4jade.examples.interactionprotocol.goal.RequestServiceGoal;
+import bdi4jade.examples.interactionprotocol.goal.VerifyAbnormalBehaviourGoal;
+import bdi4jade.examples.interactionprotocol.goal.VerifySuspiciousComponentGoal;
+import bdi4jade.examples.interactionprotocol.plan.ChangeServiceProviderPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.NormalizeCommunicationPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.NotifyAnomalousComponentPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.ProvideAnomalousProbabilityPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.ProvideServicePlanBody;
+import bdi4jade.examples.interactionprotocol.plan.RepairLinkPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.RequestServicePlanBody;
+import bdi4jade.examples.interactionprotocol.plan.SelfHealingPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.VerifyInternalOrExternalCausePlanBody;
+import bdi4jade.examples.interactionprotocol.plan.VerifySuspiciousComponentPlanBody;
+import bdi4jade.extension.remediation.RemediationCapability;
+import bdi4jade.goal.GoalTemplateFactory;
+import bdi4jade.plan.DefaultPlan;
+import bdi4jade.plan.Plan;
+import bdi4jade.reasoning.DefaultBeliefRevisionStrategy;
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class CauseAnalysisCapability extends RemediationCapability {
+
+	private static final long serialVersionUID = 1643352181891539109L;
+
+	// Beliefs
+	@Belief
+	private Map<Service, ArrayList<Service>> myServices;
+	@Belief
+	private Map<Service, Integer> serviceCost;
+	@Belief
+	private Map<Service, Component> currentProviders;
+	@Belief
+	private Map<String, Integer> knownAgents;
+	@Belief
+	private ArrayList<Component> unavailableProviders;
+	@Belief
+	private Boolean failure;
+
+	// Plans
+	@bdi4jade.annotation.Plan
+	private Plan verifyInternalOrExternalCausePlan;
+	@bdi4jade.annotation.Plan
+	private Plan verifySuspiciousComponentPlan;
+	@bdi4jade.annotation.Plan
+	private Plan selfHealingPlan;
+	@bdi4jade.annotation.Plan
+	private Plan normalizeCommunicationPlan;
+	@bdi4jade.annotation.Plan
+	private Plan changeServiceProviderPlan;
+	@bdi4jade.annotation.Plan
+	private Plan notifyAnomalyPlan;
+	@bdi4jade.annotation.Plan
+	private Plan repairLinkPlan;
+	@bdi4jade.annotation.Plan
+	private Plan provideServicePlan;
+	@bdi4jade.annotation.Plan
+	private Plan requestServicePlan;
+	@bdi4jade.annotation.Plan
+	private Plan provideAnomalousProbabilityPlan;
+
+	public CauseAnalysisCapability(BDIAgent agent, Map<Service, ArrayList<Service>> myServices,
+			HashMap<String, Integer> knownAgents) {
+		super(agent);
+		this.myServices = myServices;
+		this.serviceCost = new HashMap<Service, Integer>();
+		this.knownAgents = knownAgents;
+		this.unavailableProviders = new ArrayList<>();
+		this.failure = false;
+		this.currentProviders = new HashMap<Service, Component>();
+		initializePlans();
+		setBeliefRevisionStrategy(new MyBeliefRevisionStrategy());
+	}
+
+	public ArrayList<Service> getMyServices() {
+		ArrayList<Service> services = new ArrayList<Service>(this.myServices.keySet());
+		return services;
+	}
+
+	public ArrayList<Service> getMyServiceDependences(Service service) {
+		if (this.myServices.containsKey(service)) {
+			return this.myServices.get(service);
+		}
+		return new ArrayList<Service>();
+	}
+
+	public void setCurrentProviders(Map<Service, Component> currentProviders) {
+		this.currentProviders = currentProviders;
+	}
+
+	public void setServiceCost(Service service, Integer cost) {
+		this.serviceCost.put(service, cost);
+	}
+
+	public Map<Service, Integer> getServiceCost() {
+		return this.serviceCost;
+	}
+
+	private void initializePlans() {
+		this.verifyInternalOrExternalCausePlan = new DefaultPlan(VerifyAbnormalBehaviourGoal.class,
+				VerifyInternalOrExternalCausePlanBody.class);
+		this.selfHealingPlan = new DefaultPlan(GoalTemplateFactory.hasBeliefOfTypeWithValue(Abnormal.class, false),
+				SelfHealingPlanBody.class);
+		this.normalizeCommunicationPlan = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfTypeWithValue(AnomalousCommunication.class, false),
+				NormalizeCommunicationPlanBody.class);
+		this.changeServiceProviderPlan = new DefaultPlan(ChangeServiceProviderGoal.class,
+				ChangeServiceProviderPlanBody.class);
+		this.verifySuspiciousComponentPlan = new DefaultPlan(VerifySuspiciousComponentGoal.class,
+				VerifySuspiciousComponentPlanBody.class);
+		this.repairLinkPlan = new DefaultPlan(GoalTemplateFactory.hasBeliefOfTypeWithValue(AnomalousLink.class, false),
+				RepairLinkPlanBody.class);
+		this.notifyAnomalyPlan = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfTypeWithValue(AnomalousComponent.class, false),
+				NotifyAnomalousComponentPlanBody.class);
+		this.provideServicePlan = new DefaultPlan(ProvideServiceGoal.class, ProvideServicePlanBody.class);
+		this.requestServicePlan = new DefaultPlan(GoalTemplateFactory.goalOfType(RequestServiceGoal.class),
+				RequestServicePlanBody.class);
+		this.provideAnomalousProbabilityPlan = new DefaultPlan(ProvideAnomalousProbabilityGoal.class,
+				ProvideAnomalousProbabilityPlanBody.class);
+	}
+
+	class MyBeliefRevisionStrategy extends DefaultBeliefRevisionStrategy {
+
+		private MessageTemplate mtNotification;
+		private MessageTemplate mtServiceRequest;
+		private MessageTemplate mtProbabilityRequest;
+
+		@Override
+		public void reviewBeliefs() {
+			super.reviewBeliefs();
+
+			this.mtNotification = MessageTemplate.MatchPerformative(ACLMessage.INFORM_REF);
+			ACLMessage notificationMsg = getMyAgent().receive(mtNotification);
+			if (notificationMsg != null) {
+				getMyAgent().addGoal(new VerifyAbnormalBehaviourGoal(notificationMsg));
+			}
+
+			this.mtServiceRequest = MessageTemplate.MatchPerformative(ACLMessage.REQUEST);
+			ACLMessage serviceRequestMsg = getMyAgent().receive(mtServiceRequest);
+			if (serviceRequestMsg != null) {
+				Service service = new Service(serviceRequestMsg.getContent());
+				if (myServices.containsKey(service)) {
+					getMyAgent().addGoal(new ProvideServiceGoal(serviceRequestMsg));
+				}
+			}
+
+			this.mtProbabilityRequest = MessageTemplate.MatchPerformative(ACLMessage.QUERY_IF);
+			ACLMessage probabilityRequestMsg = getMyAgent().receive(mtProbabilityRequest);
+			if (probabilityRequestMsg != null) {
+				getMyAgent().addGoal(new ProvideAnomalousProbabilityGoal(probabilityRequestMsg));
+			}
+		}
+
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/dao/TraceDAO.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/dao/TraceDAO.java
new file mode 100644
index 0000000..a4385e4
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/dao/TraceDAO.java
@@ -0,0 +1,175 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.dao;
+
+import java.util.ArrayList;
+
+import org.bson.Document;
+
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.Filters;
+import com.mongodb.client.model.Sorts;
+
+import bdi4jade.examples.interactionprotocol.Trace;
+import bdi4jade.examples.interactionprotocol.TraceDatabase;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class TraceDAO {
+
+	private static final String SENDER = "sender";
+	private static final String RECEIVER = "receiver";
+	private static final String SERVICE = "service";
+	private static final String CID = "cid";
+	private static final String PARENT_CID = "parentCid";
+	private static final String SENT_AT = "sentAt";
+	private static final String RECEIVED_AT = "receivedAt";
+	private static final String VALUE = "value";
+	private static final String TRACES_COLLECTION = "traces";
+
+	private MongoDatabase db;
+
+	public TraceDAO(String dbName) {
+		this.db = TraceDatabase.getInstance().getDatabase(dbName);
+	}
+
+	public void dropCollection() {
+		MongoCollection<Document> traces = getCollection();
+		traces.drop();
+	}
+
+	public void addTrace(Trace trace) {
+		MongoCollection<Document> traces = getCollection();
+		Document item = new Document(TraceDAO.SENDER, trace.getSender()).append(TraceDAO.RECEIVER, trace.getReceiver())
+				.append(TraceDAO.SERVICE, trace.getService()).append(TraceDAO.CID, trace.getCid())
+				.append(TraceDAO.PARENT_CID, trace.getParentCid()).append(TraceDAO.SENT_AT, trace.getSentAt());
+		traces.insertOne(item);
+	}
+
+	public void updateTrace(Trace trace) {
+		MongoCollection<Document> traces = getCollection();
+		traces.updateOne(
+				Filters.and(Filters.eq(TraceDAO.SENDER, trace.getSender()),
+						Filters.eq(TraceDAO.RECEIVER, trace.getReceiver()), Filters.eq(TraceDAO.CID, trace.getCid())),
+				new Document("$set", new Document(TraceDAO.RECEIVED_AT, trace.getReceivedAt()).append(TraceDAO.VALUE,
+						trace.getValue())));
+	}
+
+	public ArrayList<Trace> getTracesOfProvidedByBefore(String service, String provider, String parentCid) {
+		MongoCollection<Document> traces = getCollection();
+		Document doc = traces.find(Filters.and(Filters.eq(TraceDAO.PARENT_CID, parentCid), Filters.eq(TraceDAO.SERVICE, service),
+				Filters.eq(TraceDAO.RECEIVER, provider))).first();
+		Long receivedAt = doc.getLong(TraceDAO.RECEIVED_AT);
+
+		FindIterable<Document> findIterable = traces.find(Filters.and(Filters.eq(TraceDAO.SERVICE, service),
+				Filters.eq(TraceDAO.RECEIVER, provider), Filters.lte(TraceDAO.RECEIVED_AT, receivedAt)));
+		
+		ArrayList<Trace> traceList = new ArrayList<Trace>();
+		for (Document document : findIterable) {
+			traceList.add(getTraceInstance(document));
+		}
+		
+		return traceList;
+	}
+
+	public ArrayList<Trace> getTracesByCID(String cid) {
+		MongoCollection<Document> traces = getCollection();
+		FindIterable<Document> findIterable = traces.find(Filters.eq(TraceDAO.CID, cid));
+		ArrayList<Trace> traceList = new ArrayList<Trace>();
+		for (Document document : findIterable) {
+			traceList.add(getTraceInstance(document));
+		}
+		return traceList;
+	}
+
+	public ArrayList<Trace> getTracesByParentCID(String parentCid) {
+		MongoCollection<Document> traces = getCollection();
+		FindIterable<Document> findIterable = traces.find(Filters.eq(TraceDAO.PARENT_CID, parentCid));
+		ArrayList<Trace> traceList = new ArrayList<Trace>();
+		for (Document document : findIterable) {
+			traceList.add(getTraceInstance(document));
+		}
+		return traceList;
+	}
+
+	public ArrayList<Trace> getTracesByServiceAndProvider(String service, String provider) {
+		MongoCollection<Document> traces = getCollection();
+		FindIterable<Document> findIterable = traces.find(Filters.and(Filters.eq(TraceDAO.SERVICE, service),
+				Filters.eq(TraceDAO.RECEIVER, provider), Filters.exists(TraceDAO.RECEIVED_AT)))
+				.sort(Sorts.ascending(TraceDAO.RECEIVED_AT));
+		ArrayList<Trace> traceList = new ArrayList<Trace>();
+		for (Document document : findIterable) {
+			traceList.add(getTraceInstance(document));
+		}
+		return traceList;
+	}
+
+	public ArrayList<Trace> getTracesByCIDAndProvider(String cid, String provider) {
+		MongoCollection<Document> traces = getCollection();
+		FindIterable<Document> findIterable = traces
+				.find(Filters.and(Filters.eq(TraceDAO.CID, cid), Filters.eq(TraceDAO.RECEIVER, provider)));
+		ArrayList<Trace> traceList = new ArrayList<Trace>();
+		for (Document document : findIterable) {
+			traceList.add(getTraceInstance(document));
+		}
+		return traceList;
+	}
+
+	public ArrayList<Trace> getTracesByParentCIDAndProvider(String parentCid, String provider) {
+		MongoCollection<Document> traces = getCollection();
+		FindIterable<Document> findIterable = traces
+				.find(Filters.and(Filters.eq(TraceDAO.PARENT_CID, parentCid), Filters.eq(TraceDAO.RECEIVER, provider)));
+		ArrayList<Trace> traceList = new ArrayList<Trace>();
+		for (Document document : findIterable) {
+			traceList.add(getTraceInstance(document));
+		}
+		return traceList;
+	}
+
+	public String getCIDByParentCIDAndProviderAndService(String parentCid, String provider, String service) {
+		MongoCollection<Document> traces = getCollection();
+		FindIterable<Document> findIterable = traces.find(Filters.and(Filters.eq(TraceDAO.PARENT_CID, parentCid),
+				Filters.eq(TraceDAO.RECEIVER, provider), Filters.eq(TraceDAO.SERVICE, service)));
+		Document document = findIterable.first();
+		return (String) document.get(TraceDAO.CID);
+	}
+
+	private MongoCollection<Document> getCollection() {
+		return this.db.getCollection(TraceDAO.TRACES_COLLECTION);
+	}
+
+	private Trace getTraceInstance(Document document) {
+		Trace trace = new Trace(document.getString(TraceDAO.SENDER), document.getString(TraceDAO.RECEIVER),
+				document.getString(TraceDAO.SERVICE), document.getString(TraceDAO.CID),
+				document.getString(TraceDAO.PARENT_CID));
+		trace.setSentAt(document.getLong(TraceDAO.SENT_AT));
+		trace.setReceivedAt(document.getLong(TraceDAO.RECEIVED_AT));
+		trace.setValue(document.getString(TraceDAO.VALUE));
+		return trace;
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Communication.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Communication.java
new file mode 100644
index 0000000..4dd0de5
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Communication.java
@@ -0,0 +1,84 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain;
+
+import java.io.Serializable;
+
+import jade.content.Concept;
+import jade.content.ContentElement;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class Communication implements Serializable, Concept, ContentElement {
+
+	private static final long serialVersionUID = -3011235813999398006L;
+
+	private Component component;
+	private Service service;
+	
+	
+	public Communication(Component component, Service service) {
+		this.component = component;
+		this.service = service;
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if (obj instanceof Communication) {
+			Communication communication = (Communication) obj;
+			return this.component.equals(communication.component) && this.service.equals(communication.service);
+		}
+		return false;
+	}
+
+	public Component getComponent() {
+		return component;
+	}
+	
+	public Service getService() {
+		return service;
+	}
+
+	@Override
+	public int hashCode() {
+		if (component != null && service != null) {
+			return component.hashCode() + service.hashCode();
+		}
+		return 0;
+	}
+
+	public void setComponent(Component component) {
+		this.component = component;
+	}
+	
+	public void setService(Service service) {
+		this.service = service;
+	}
+
+	@Override
+	public String toString() {
+		return "Communication<" + service + ", " + component + ">";
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Component.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Component.java
new file mode 100644
index 0000000..60c4336
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Component.java
@@ -0,0 +1,73 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain;
+
+import java.io.Serializable;
+
+import jade.content.Concept;
+import jade.content.ContentElement;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class Component implements Serializable, Concept, ContentElement {
+	
+	private static final long serialVersionUID = 2336016887215657247L;
+	
+	public static final String NAME = "COMPONENT";
+	
+	private String id;
+	
+	public Component(String id) {
+		this.id = id;
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if (obj instanceof Component) {
+			Component component = (Component) obj;
+			return this.id.equals(component.id);
+		}
+		return false;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	@Override
+	public int hashCode() {
+		return id == null ? 0 : id.hashCode();
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	@Override
+	public String toString() {
+		return id;
+	}
+	
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Conversation.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Conversation.java
new file mode 100644
index 0000000..9a31741
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Conversation.java
@@ -0,0 +1,70 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain;
+
+import java.io.Serializable;
+
+import jade.content.Concept;
+import jade.content.ContentElement;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class Conversation implements Serializable, Concept, ContentElement 	{
+
+	private static final long serialVersionUID = 3190370626776592028L;
+
+	private String id;
+	
+	public Conversation(String id) {
+		this.id = id;
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if (obj instanceof Conversation) {
+			Conversation conversation = (Conversation) obj;
+			return this.id.equals(conversation.id);
+		}
+		return false;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	@Override
+	public int hashCode() {
+		return id == null ? 0 : id.hashCode();
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	@Override
+	public String toString() {
+		return id;
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Link.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Link.java
new file mode 100644
index 0000000..aebd373
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Link.java
@@ -0,0 +1,95 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain;
+
+import java.io.Serializable;
+
+import jade.content.Concept;
+import jade.content.ContentElement;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class Link implements Serializable, Concept, ContentElement {
+	
+	private static final long serialVersionUID = -2648113421244668177L;
+	
+	private Component from;
+	private Component to;
+	private Service service;
+	
+	public Link(Component from, Component to, Service service) {
+		this.from = from;
+		this.to = to;
+		this.service = service;
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if (obj instanceof Link) {
+			Link link = (Link) obj;
+			if (this.service.equals(link.service)) {
+				return ((this.from.equals(link.from) && this.to.equals(link.to)) || (this.from.equals(link.to) && this.to.equals(link.from)));
+			}
+		}
+		return false;
+	}
+
+	public Component getFrom() {
+		return from;
+	}
+	
+	public Component getTo() {
+		return to;
+	}
+	
+	public Service getService() {
+		return service;
+	}
+
+	@Override
+	public int hashCode() {
+		if (from != null && to != null && service != null) {
+			return from.hashCode() + to.hashCode() + service.hashCode();
+		}
+		return 0;
+	}
+
+	public void setFrom(Component from) {
+		this.from = from;
+	}
+	
+	public void setTo(Component to)  {
+		this.to = to;
+	}
+	
+	public void setService(Service service) {
+		this.service = service;
+	}
+
+	@Override
+	public String toString() {
+		return from + "->" + to + "[" + service.getId() + "]";
+	}
+}
\ No newline at end of file
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/LinkMonitor.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/LinkMonitor.java
new file mode 100644
index 0000000..38f8ee4
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/LinkMonitor.java
@@ -0,0 +1,47 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain;
+
+import java.util.ArrayList;
+
+public class LinkMonitor {
+
+	private ArrayList<Link> anomalousLinks;
+	private static LinkMonitor instance;
+
+	private LinkMonitor() {
+		this.anomalousLinks = new ArrayList<Link>();
+	}
+
+	public static synchronized LinkMonitor getInstance() {
+		if (instance == null) {
+			instance = new LinkMonitor();
+		}
+		return instance;
+	}
+
+	public ArrayList<Link> getAnomalousLinks() {
+		return this.anomalousLinks;
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/Abnormal.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/Abnormal.java
new file mode 100644
index 0000000..c6b78eb
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/Abnormal.java
@@ -0,0 +1,40 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain.predicate;
+
+import bdi4jade.examples.interactionprotocol.domain.Conversation;
+import bdi4jade.extension.remediation.logics.UnaryPredicate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class Abnormal extends UnaryPredicate<Conversation> {
+
+	private static final long serialVersionUID = 8950818159503842949L;
+	public static final String NAME = "ABNORMAL";
+
+	public Abnormal(Conversation conversation) {
+		super(conversation);
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/AnomalousCommunication.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/AnomalousCommunication.java
new file mode 100644
index 0000000..a29f0a2
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/AnomalousCommunication.java
@@ -0,0 +1,40 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain.predicate;
+
+import bdi4jade.examples.interactionprotocol.domain.Communication;
+import bdi4jade.extension.remediation.logics.UnaryPredicate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class AnomalousCommunication extends UnaryPredicate<Communication> {
+
+	private static final long serialVersionUID = 3487439592649863435L;
+
+	public AnomalousCommunication(Communication communication) {
+		super(communication);
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/AnomalousComponent.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/AnomalousComponent.java
new file mode 100644
index 0000000..22e6a6a
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/AnomalousComponent.java
@@ -0,0 +1,41 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain.predicate;
+
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Conversation;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.extension.remediation.logics.TernaryPredicate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class AnomalousComponent extends TernaryPredicate<Component, Service, Conversation> {
+
+	private static final long serialVersionUID = 8830607990682070885L;
+
+	public AnomalousComponent(Component component, Service service, Conversation conversation) {
+		super(component, service, conversation);
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/AnomalousLink.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/AnomalousLink.java
new file mode 100644
index 0000000..6c75d2c
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/AnomalousLink.java
@@ -0,0 +1,39 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain.predicate;
+
+import bdi4jade.examples.interactionprotocol.domain.Link;
+import bdi4jade.extension.remediation.logics.UnaryPredicate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class AnomalousLink extends UnaryPredicate<Link> {
+
+	private static final long serialVersionUID = 7464604713387606364L;
+
+	public AnomalousLink(Link link) {
+		super(link);
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/ViolatedRequirementOn.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/ViolatedRequirementOn.java
new file mode 100644
index 0000000..d6305fe
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/predicate/ViolatedRequirementOn.java
@@ -0,0 +1,43 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain.predicate;
+
+import bdi4jade.examples.interactionprotocol.domain.Conversation;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.extension.remediation.logics.BinaryPredicate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class ViolatedRequirementOn extends BinaryPredicate<Service, Conversation> {
+	
+	private static final long serialVersionUID = 4711948107223122915L;
+	public static final String TRUE = "VIOLATED_REQUIREMENT";
+	public static final String FALSE = "NON_VIOLATED_REQUIREMENT";
+
+	public ViolatedRequirementOn(Service service, Conversation conversation) {
+		super(service, conversation);
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Service.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Service.java
new file mode 100644
index 0000000..cb79b3d
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/domain/Service.java
@@ -0,0 +1,73 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.domain;
+
+import java.io.Serializable;
+
+import jade.content.Concept;
+import jade.content.ContentElement;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class Service implements Serializable, Concept, ContentElement {
+
+	private static final long serialVersionUID = -1339301571194419358L;
+	
+	public static final String NAME = "SERVICE";
+	public static final String COST = "COST";
+	
+	private String id;
+	
+	public Service(String id) {
+		this.id = id;
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if (obj instanceof Service) {
+			Service service = (Service) obj;
+			return this.id.equals(service.id);
+		}
+		return false;
+	}
+
+	public String getId() {
+		return id;
+	}
+
+	@Override
+	public int hashCode() {
+		return id == null ? 0 : id.hashCode();
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	@Override
+	public String toString() {
+		return id;
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/dummy/DummyCapability.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/dummy/DummyCapability.java
new file mode 100644
index 0000000..c510452
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/dummy/DummyCapability.java
@@ -0,0 +1,137 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.dummy;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import bdi4jade.annotation.Belief;
+import bdi4jade.core.Capability;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.goal.ProvideServiceGoal;
+import bdi4jade.examples.interactionprotocol.goal.RequestServiceGoal;
+import bdi4jade.examples.interactionprotocol.goal.VerifyAbnormalBehaviourGoal;
+import bdi4jade.examples.interactionprotocol.plan.DoNothingPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.ProvideServicePlanBody;
+import bdi4jade.examples.interactionprotocol.plan.RequestServicePlanBody;
+import bdi4jade.goal.GoalTemplateFactory;
+import bdi4jade.plan.DefaultPlan;
+import bdi4jade.plan.Plan;
+import bdi4jade.reasoning.DefaultBeliefRevisionStrategy;
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class DummyCapability extends Capability {
+
+	private static final long serialVersionUID = 7925397404457745783L;
+
+	// Beliefs
+	@Belief
+	private Map<Service, ArrayList<Service>> myServices;
+	@Belief
+	private Map<Service, Integer> serviceCost;
+	@Belief
+	private Map<Service, Component> currentProviders;
+	@Belief
+	private ArrayList<Component> unavailableProviders;
+	@Belief
+	private Boolean failure;
+	
+	@bdi4jade.annotation.Plan
+	private Plan provideServicePlan;
+	@bdi4jade.annotation.Plan
+	private Plan requestServicePlan;
+	@bdi4jade.annotation.Plan
+	private Plan doNothingPlan;
+	
+	public DummyCapability(Map<Service, ArrayList<Service>> myServices) {
+		this.myServices = myServices;
+		this.serviceCost = new HashMap<Service, Integer>();
+		this.unavailableProviders = new ArrayList<>();
+		this.failure = false;
+		this.currentProviders = new HashMap<Service, Component>();
+		
+		this.provideServicePlan = new DefaultPlan(ProvideServiceGoal.class, ProvideServicePlanBody.class);
+		this.requestServicePlan = new DefaultPlan(GoalTemplateFactory.goalOfType(RequestServiceGoal.class),
+				RequestServicePlanBody.class);
+		this.doNothingPlan = new DefaultPlan(VerifyAbnormalBehaviourGoal.class, DoNothingPlanBody.class);
+		
+		setBeliefRevisionStrategy(new DummyBeliefRevisionStrategy());
+	}
+	
+	public ArrayList<Service> getMyServices() {
+		ArrayList<Service> services = new ArrayList<Service>(this.myServices.keySet());
+		return services;
+	}
+
+	public ArrayList<Service> getMyServiceDependences(Service service) {
+		if (this.myServices.containsKey(service)) {
+			return this.myServices.get(service);
+		}
+		return new ArrayList<Service>();
+	}
+
+	public void setCurrentProviders(Map<Service, Component> currentProviders) {
+		this.currentProviders = currentProviders;
+	}
+
+	public void setServiceCost(Service service, Integer cost) {
+		this.serviceCost.put(service, cost);
+	}
+
+	public Map<Service, Integer> getServiceCost() {
+		return this.serviceCost;
+	}
+	
+	class DummyBeliefRevisionStrategy extends DefaultBeliefRevisionStrategy {
+		
+		private MessageTemplate mtNotification;
+		private MessageTemplate mtServiceRequest;
+		
+		@Override
+		public void reviewBeliefs() {
+			super.reviewBeliefs();
+			
+			this.mtNotification = MessageTemplate.MatchPerformative(ACLMessage.INFORM_REF);
+			ACLMessage notificationMsg = getMyAgent().receive(mtNotification);
+			if (notificationMsg != null) {
+				getMyAgent().addGoal(new VerifyAbnormalBehaviourGoal(notificationMsg));
+			}
+			
+			this.mtServiceRequest = MessageTemplate.MatchPerformative(ACLMessage.REQUEST);
+			ACLMessage serviceRequestMsg = getMyAgent().receive(mtServiceRequest);
+			if (serviceRequestMsg != null) {
+				Service service = new Service(serviceRequestMsg.getContent());
+				if (myServices.containsKey(service)) {
+					getMyAgent().addGoal(new ProvideServiceGoal(serviceRequestMsg));
+				}
+			}
+		}
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/dummy/DummyServiceProvider.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/dummy/DummyServiceProvider.java
new file mode 100644
index 0000000..c571dea
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/dummy/DummyServiceProvider.java
@@ -0,0 +1,98 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.dummy;
+
+import java.util.ArrayList;
+
+import bdi4jade.core.Capability;
+import bdi4jade.core.SingleCapabilityAgent;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import jade.domain.DFService;
+import jade.domain.FIPAException;
+import jade.domain.FIPAAgentManagement.DFAgentDescription;
+import jade.domain.FIPAAgentManagement.Property;
+import jade.domain.FIPAAgentManagement.ServiceDescription;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class DummyServiceProvider extends SingleCapabilityAgent {
+
+	private static final long serialVersionUID = -4507912243488870315L;
+
+	private String customName;
+
+	public DummyServiceProvider(String customName) {
+		super();
+		this.customName = customName;
+	}
+
+	public DummyServiceProvider(String customName, Capability capability) {
+		super(capability);
+		this.customName = customName;
+	}
+
+	public String getCustomName() {
+		return customName;
+	}
+
+	public void register() {
+		DummyCapability capability = (DummyCapability) this.getCapability();
+		ArrayList<Service> services = capability.getMyServices();
+
+		DFAgentDescription dfd = new DFAgentDescription();
+		dfd.setName(this.getAID());
+		
+		for (Service service : services) {
+			ServiceDescription sd = new ServiceDescription();
+			sd.setType(service.getId());
+			sd.setName(service.getId());
+
+			Property property = new Property();
+			property.setName(Service.COST);
+			
+			int cost = capability.getServiceCost().get(service);
+			property.setValue(String.valueOf(cost));
+
+			sd.addProperties(property);
+			dfd.addServices(sd);
+		}
+		try {
+			DFService.register(this, dfd);
+		} catch (FIPAException fe) {
+			fe.printStackTrace();
+		}
+	}
+
+	@Override
+	protected void takeDown() {
+		try {
+			DFService.deregister(this);
+		} catch (FIPAException fe) {
+			fe.printStackTrace();
+		}
+		System.out.println("Deregistering from Yellow Page Services.");
+		super.takeDown();
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/DummyRunner.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/DummyRunner.java
new file mode 100644
index 0000000..8d6765e
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/DummyRunner.java
@@ -0,0 +1,361 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.experiment;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.log4j.PropertyConfigurator;
+
+import bdi4jade.core.SingleCapabilityAgent;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.event.GoalListener;
+import bdi4jade.examples.interactionprotocol.MonitorMetricsCapability;
+import bdi4jade.examples.interactionprotocol.dao.TraceDAO;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Link;
+import bdi4jade.examples.interactionprotocol.domain.LinkMonitor;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.dummy.DummyCapability;
+import bdi4jade.examples.interactionprotocol.dummy.DummyServiceProvider;
+import bdi4jade.examples.interactionprotocol.goal.MonitorMetricsGoal;
+import jade.BootProfileImpl;
+import jade.core.ProfileImpl;
+import jade.wrapper.AgentContainer;
+import jade.wrapper.AgentController;
+import jade.wrapper.PlatformController;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class DummyRunner implements GoalListener {
+
+	public static final int ITERATIONS = 100;
+
+	private ProfileImpl bootProfile;
+	private jade.core.Runtime runtime;
+	private PlatformController controller;
+
+	private ArrayList<DummyServiceProvider> dummyProviders;
+	private SingleCapabilityAgent client;
+
+	private int failurePoint;
+	private int iteration;
+
+	public DummyRunner() {
+		this.failurePoint = 50;
+		this.iteration = 0;
+		List<String> params = new ArrayList<String>();
+		params.add("-gui");
+		params.add("-detect-main:false");
+
+		this.bootProfile = new BootProfileImpl(params.toArray(new String[0]));
+		this.runtime = jade.core.Runtime.instance();
+		this.controller = runtime.createMainContainer(bootProfile);
+
+		this.dummyProviders = initializeProviderAgents();
+		initializeClientAgent();
+
+		HashMap<Service, ArrayList<Service>> serviceDependences = initializeServiceDependenceList();
+
+		setAgentCapabilitiesAndServices(this.dummyProviders, serviceDependences);
+
+		for (DummyServiceProvider providers : this.dummyProviders) {
+			providers.register();
+		}
+
+		setInitialCurrentProviders(this.dummyProviders);
+	}
+
+	public static void main(String[] args) {
+		PropertyConfigurator.configure(ExperimentRunner1.class.getResource("log4j.properties"));
+		DummyRunner runner = new DummyRunner();
+		runner.run();
+	}
+
+	public void run() {
+		try {
+			Thread.sleep(2000);
+			client.addGoal(new MonitorMetricsGoal(), this);
+
+			this.iteration++;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void goalPerformed(GoalEvent event) {
+		if (event.getStatus().isFinished() && event.getGoal() instanceof MonitorMetricsGoal) {
+			if (iteration < ITERATIONS) {
+				if (iteration == failurePoint) {
+
+					/*
+					 * DummyServiceProvider agent = dummyProviders.get(4);
+					 * 
+					 * @SuppressWarnings("unchecked") Belief<String, Boolean> failure =
+					 * (Belief<String, Boolean>) agent.getCapability().getBeliefBase()
+					 * .getBelief("failure"); failure.setValue(true);
+					 * System.out.println("Setting failure to " + agent.getLocalName());
+					 */
+
+					Link link = new Link(new Component("AGENT0"), new Component("AGENT4"), new Service("SERVICE2"));
+					LinkMonitor.getInstance().getAnomalousLinks().add(link);
+					System.out.println("Setting failure to link: " + link);
+
+				}
+
+				run();
+			} else {
+				System.out.println("Iterations finished!!");
+			}
+		}
+	}
+
+	private ArrayList<DummyServiceProvider> initializeProviderAgents() {
+		System.out.println("Initializing 31 service providers...");
+		ArrayList<DummyServiceProvider> agents = new ArrayList<>();
+
+		try {
+			for (int i = 0; i < 31; i++) {
+				DummyServiceProvider agent = new DummyServiceProvider("AGENT" + i);
+				agents.add(agent);
+				AgentController ac = ((AgentContainer) controller).acceptNewAgent(agent.getCustomName(), agent);
+				ac.start();
+				setupDB(agent);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		System.out.println("Provider agents initialized!");
+		return agents;
+	}
+
+	private void initializeClientAgent() {
+		System.out.println("Initializing client agent...");
+		this.client = new SingleCapabilityAgent();
+		try {
+			AgentController ac = ((AgentContainer) controller).acceptNewAgent("CLIENT", this.client);
+			ac.start();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		System.out.println("Client agent initalized!");
+	}
+
+	private HashMap<Service, ArrayList<Service>> initializeServiceDependenceList() {
+		System.out.println("Creating service dependence list for 10 services...");
+		HashMap<Service, ArrayList<Service>> dependenceList = new HashMap<>();
+		for (int i = 0; i < 3; i++) {
+			Service service = new Service("SERVICE" + i);
+			ArrayList<Service> serviceDependences = new ArrayList<Service>();
+			serviceDependences.add(new Service("SERVICE" + (2 * i + 1)));
+			serviceDependences.add(new Service("SERVICE" + (2 * i + 2)));
+			dependenceList.put(service, serviceDependences);
+		}
+
+		for (int i = 3, j = 1; i < 7; i++, j--) {
+			Service service = new Service("SERVICE" + i);
+			ArrayList<Service> serviceDependences = new ArrayList<Service>();
+			serviceDependences.add(new Service("SERVICE" + (2 * i + j)));
+			dependenceList.put(service, serviceDependences);
+		}
+
+		return dependenceList;
+	}
+
+	private void setAgentCapabilitiesAndServices(ArrayList<DummyServiceProvider> providers,
+			HashMap<Service, ArrayList<Service>> serviceDependences) {
+
+		setClientAgentCapability();
+
+		System.out.println("Setting provider agent capabilities...");
+
+		DummyServiceProvider a0 = providers.get(0);
+		HashMap<Service, ArrayList<Service>> myServices = new HashMap<Service, ArrayList<Service>>();
+		Service s0 = new Service("SERVICE0");
+		myServices.put(s0, serviceDependences.get(s0));
+		DummyCapability capability = new DummyCapability(myServices);
+		capability.setServiceCost(s0, 0);
+		a0.setCapability(capability);
+
+		int agentCounter = 1;
+
+		for (int i = 1; i < 11; i++) {
+			for (int j = 0; j < 3; j++) {
+				DummyServiceProvider provider = providers.get(agentCounter);
+				Service service = new Service("SERVICE" + i);
+
+				myServices = new HashMap<Service, ArrayList<Service>>();
+				ArrayList<Service> dependences = new ArrayList<Service>();
+				if (serviceDependences.get(service) != null) {
+					dependences = serviceDependences.get(service);
+				}
+				myServices.put(service, dependences);
+				capability = new DummyCapability(myServices);
+				capability.setServiceCost(service, agentCounter);
+
+				provider.setCapability(capability);
+				agentCounter++;
+			}
+		}
+		System.out.println("Provider agent capabilities initialized!");
+
+	}
+
+	private void setClientAgentCapability() {
+		System.out.println("Setting client agent capability...");
+		this.client.setCapability(new MonitorMetricsCapability());
+		System.out.println("Client agent capability initialized!");
+	}
+
+	private void setInitialCurrentProviders(ArrayList<DummyServiceProvider> providers) {
+		DummyServiceProvider agent = providers.get(0);
+		DummyCapability capability = (DummyCapability) agent.getCapability();
+		HashMap<Service, Component> currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE1"), new Component("AGENT1"));
+		currentProviders.put(new Service("SERVICE2"), new Component("AGENT4"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(1);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE3"), new Component("AGENT7"));
+		currentProviders.put(new Service("SERVICE4"), new Component("AGENT10"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(2);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE3"), new Component("AGENT8"));
+		currentProviders.put(new Service("SERVICE4"), new Component("AGENT11"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(3);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE3"), new Component("AGENT9"));
+		currentProviders.put(new Service("SERVICE4"), new Component("AGENT12"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(4);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE5"), new Component("AGENT13"));
+		currentProviders.put(new Service("SERVICE6"), new Component("AGENT16"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(5);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE5"), new Component("AGENT14"));
+		currentProviders.put(new Service("SERVICE6"), new Component("AGENT17"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(6);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE5"), new Component("AGENT15"));
+		currentProviders.put(new Service("SERVICE6"), new Component("AGENT18"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(7);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE7"), new Component("AGENT19"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(8);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE7"), new Component("AGENT20"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(9);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE7"), new Component("AGENT21"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(10);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE8"), new Component("AGENT22"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(11);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE8"), new Component("AGENT23"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(12);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE8"), new Component("AGENT24"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(13);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE9"), new Component("AGENT25"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(14);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE9"), new Component("AGENT26"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(15);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE9"), new Component("AGENT27"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(16);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE10"), new Component("AGENT28"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(17);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE10"), new Component("AGENT29"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(18);
+		capability = (DummyCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE10"), new Component("AGENT30"));
+		capability.setCurrentProviders(currentProviders);
+	}
+
+	private void setupDB(DummyServiceProvider agent) {
+		TraceDAO dao = new TraceDAO(agent.getAID().getLocalName());
+		dao.dropCollection();
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/ExperimentRunner1.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/ExperimentRunner1.java
new file mode 100644
index 0000000..ec525d7
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/ExperimentRunner1.java
@@ -0,0 +1,445 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.experiment;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.log4j.PropertyConfigurator;
+
+import bdi4jade.core.SingleCapabilityAgent;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.event.GoalListener;
+import bdi4jade.examples.interactionprotocol.CauseAnalysisCapability;
+import bdi4jade.examples.interactionprotocol.MonitorMetricsCapability;
+import bdi4jade.examples.interactionprotocol.ServiceProviderAgent;
+import bdi4jade.examples.interactionprotocol.dao.TraceDAO;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Link;
+import bdi4jade.examples.interactionprotocol.domain.LinkMonitor;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.goal.MonitorMetricsGoal;
+import bdi4jade.examples.interactionprotocol.goal.RequestServiceGoal;
+import jade.BootProfileImpl;
+import jade.core.ProfileImpl;
+import jade.wrapper.AgentContainer;
+import jade.wrapper.AgentController;
+import jade.wrapper.PlatformController;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class ExperimentRunner1 implements GoalListener {
+
+	public static final int ITERATIONS = 100;
+
+	private ProfileImpl bootProfile;
+	private jade.core.Runtime runtime;
+	private PlatformController controller;
+
+	private ArrayList<ServiceProviderAgent> providerAgents;
+	private ArrayList<ServiceProviderAgent> supportingAgents;
+	private SingleCapabilityAgent client;
+
+	private int failurePoint;
+	private int iteration;
+
+	public ExperimentRunner1() {
+		this.failurePoint = 50;
+		this.iteration = 0;
+		List<String> params = new ArrayList<String>();
+		params.add("-gui");
+		params.add("-detect-main:false");
+
+		this.bootProfile = new BootProfileImpl(params.toArray(new String[0]));
+		this.runtime = jade.core.Runtime.instance();
+		this.controller = runtime.createMainContainer(bootProfile);
+
+		this.providerAgents = initializeProviderAgents();
+		this.supportingAgents = initializeSupportingAgents();
+		initializeClientAgent();
+
+		HashMap<Service, ArrayList<Service>> serviceDependences = initializeServiceDependenceList();
+
+		setAgentCapabilitiesAndServices(this.providerAgents, this.supportingAgents, serviceDependences);
+
+		for (ServiceProviderAgent providers : this.providerAgents) {
+			providers.register();
+		}
+
+		setInitialCurrentProviders(this.providerAgents);
+	}
+
+	public static void main(String[] args) {
+		PropertyConfigurator.configure(ExperimentRunner1.class.getResource("log4j.properties"));
+		ExperimentRunner1 runner = new ExperimentRunner1();
+		runner.run();
+	}
+
+	public void run() {
+		try {
+			Thread.sleep(2000);
+			for (ServiceProviderAgent supporter : this.supportingAgents) {
+				supporter.addGoal(new RequestServiceGoal(new Service("SERVICE2"), null), this);
+				Thread.sleep(1000);
+			}
+			client.addGoal(new MonitorMetricsGoal(), this);
+
+			this.iteration++;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void goalPerformed(GoalEvent event) {
+		if (event.getStatus().isFinished() && event.getGoal() instanceof MonitorMetricsGoal) {
+			if (iteration < ITERATIONS) {
+				if (iteration == failurePoint) {
+
+					/*
+					 * ServiceProviderAgent agent = providerAgents.get(4); Belief<String, Boolean>
+					 * failure = (Belief<String, Boolean>) agent.getCapability().getBeliefBase()
+					 * .getBelief("failure"); failure.setValue(true);
+					 * System.out.println("Setting failure to " + agent.getLocalName());
+					 */
+
+					Link link = new Link(new Component("AGENT0"), new Component("AGENT4"), new Service("SERVICE2"));
+					LinkMonitor.getInstance().getAnomalousLinks().add(link);
+					System.out.println("Setting failure to link: " + link);
+
+				}
+
+				run();
+			} else {
+				System.out.println("Iterations finished!!");
+			}
+		}
+	}
+
+	private ArrayList<ServiceProviderAgent> initializeProviderAgents() {
+		System.out.println("Initializing 31 service providers...");
+		ArrayList<ServiceProviderAgent> agents = new ArrayList<>();
+
+		try {
+			for (int i = 0; i < 31; i++) {
+				ServiceProviderAgent agent = new ServiceProviderAgent("AGENT" + i);
+				agents.add(agent);
+				AgentController ac = ((AgentContainer) controller).acceptNewAgent(agent.getCustomName(), agent);
+				ac.start();
+				setupDB(agent);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		System.out.println("Provider agents initialized!");
+		return agents;
+	}
+
+	private void initializeClientAgent() {
+		System.out.println("Initializing client agent...");
+		this.client = new SingleCapabilityAgent();
+		try {
+			AgentController ac = ((AgentContainer) controller).acceptNewAgent("CLIENT", this.client);
+			ac.start();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		System.out.println("Client agent initalized!");
+	}
+
+	private ArrayList<ServiceProviderAgent> initializeSupportingAgents() {
+		System.out.println("Initializing 5 supporting agents...");
+		ArrayList<ServiceProviderAgent> agents = new ArrayList<>();
+		try {
+			for (int i = 1; i <= 5; i++) {
+				ServiceProviderAgent agent = new ServiceProviderAgent("SUPPORT" + i);
+				agents.add(agent);
+				AgentController ac = ((AgentContainer) controller).acceptNewAgent(agent.getCustomName(), agent);
+				ac.start();
+				setupDB(agent);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		System.out.println("Supporting agents initialized!");
+		return agents;
+	}
+
+	private HashMap<String, HashMap<String, Integer>> initializeAdjacencyList(List<ServiceProviderAgent> providers,
+			List<ServiceProviderAgent> supporters) {
+		System.out.println("Initializing adjacency list for " + (providers.size() + supporters.size()) + " agents...");
+		Random random = new Random(10);
+		List<ServiceProviderAgent> agents = new ArrayList<ServiceProviderAgent>();
+		agents.addAll(providers);
+		agents.addAll(supporters);
+
+		HashMap<String, HashMap<String, Integer>> adjacencyList = new HashMap<>();
+
+		for (SingleCapabilityAgent agent : agents) {
+
+			HashMap<String, Integer> neighbours = new HashMap<>();
+			String agentLocalName = agent.getLocalName();
+
+			for (SingleCapabilityAgent neighbour : agents) {
+				String neighbourLocalName = neighbour.getLocalName();
+				if (!neighbourLocalName.equals(agentLocalName)) {
+					if (adjacencyList.containsKey(neighbourLocalName)) {
+						neighbours.put(neighbourLocalName, adjacencyList.get(neighbourLocalName).get(agentLocalName));
+					} else {
+						neighbours.put(neighbourLocalName, random.nextInt(10));
+					}
+				}
+			}
+			adjacencyList.put(agentLocalName, neighbours);
+		}
+		System.out.println("Adjacency list initialization DONE!");
+		return adjacencyList;
+	}
+
+	private HashMap<Service, ArrayList<Service>> initializeServiceDependenceList() {
+		System.out.println("Creating service dependence list for 10 services...");
+		HashMap<Service, ArrayList<Service>> dependenceList = new HashMap<>();
+		for (int i = 0; i < 3; i++) {
+			Service service = new Service("SERVICE" + i);
+			ArrayList<Service> serviceDependences = new ArrayList<Service>();
+			serviceDependences.add(new Service("SERVICE" + (2 * i + 1)));
+			serviceDependences.add(new Service("SERVICE" + (2 * i + 2)));
+			dependenceList.put(service, serviceDependences);
+		}
+
+		for (int i = 3, j = 1; i < 7; i++, j--) {
+			Service service = new Service("SERVICE" + i);
+			ArrayList<Service> serviceDependences = new ArrayList<Service>();
+			serviceDependences.add(new Service("SERVICE" + (2 * i + j)));
+			dependenceList.put(service, serviceDependences);
+		}
+		/*
+		 * for (Service service : dependenceList.keySet()) {
+		 * System.out.println(service.getId()); System.out.println("\t" +
+		 * dependenceList.get(service)); }
+		 */
+
+		return dependenceList;
+	}
+
+	private void setAgentCapabilitiesAndServices(ArrayList<ServiceProviderAgent> providers,
+			ArrayList<ServiceProviderAgent> supporters, HashMap<Service, ArrayList<Service>> serviceDependences) {
+
+		setClientAgentCapability();
+
+		HashMap<String, HashMap<String, Integer>> adjacencyList = initializeAdjacencyList(providers, supporters);
+
+		System.out.println("Setting provider agent capabilities...");
+
+		ServiceProviderAgent a0 = providers.get(0);
+		HashMap<Service, ArrayList<Service>> myServices = new HashMap<Service, ArrayList<Service>>();
+		Service s0 = new Service("SERVICE0");
+		myServices.put(s0, serviceDependences.get(s0));
+		CauseAnalysisCapability capability = new CauseAnalysisCapability(a0, myServices,
+				adjacencyList.get(a0.getLocalName()));
+		capability.setServiceCost(s0, 0);
+		a0.setCapability(capability);
+
+		int agentCounter = 1;
+
+		for (int i = 1; i < 11; i++) {
+			for (int j = 0; j < 3; j++) {
+				ServiceProviderAgent provider = providers.get(agentCounter);
+				Service service = new Service("SERVICE" + i);
+
+				myServices = new HashMap<Service, ArrayList<Service>>();
+				ArrayList<Service> dependences = new ArrayList<Service>();
+				if (serviceDependences.get(service) != null) {
+					dependences = serviceDependences.get(service);
+				}
+				myServices.put(service, dependences);
+				capability = new CauseAnalysisCapability(provider, myServices,
+						adjacencyList.get(provider.getLocalName()));
+				capability.setServiceCost(service, agentCounter);
+
+				provider.setCapability(capability);
+				agentCounter++;
+			}
+		}
+		System.out.println("Provider agent capabilities initialized!");
+		System.out.println("Setting supporting agent capabilities...");
+
+		myServices = new HashMap<Service, ArrayList<Service>>();
+
+		myServices.put(s0, serviceDependences.get(s0));
+
+		HashMap<Service, Component> currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE1"), new Component("AGENT1"));
+		currentProviders.put(new Service("SERVICE2"), new Component("AGENT4"));
+
+		for (ServiceProviderAgent supporter : supporters) {
+			CauseAnalysisCapability cap = new CauseAnalysisCapability(supporter, myServices,
+					adjacencyList.get(supporter.getLocalName()));
+			cap.setCurrentProviders(currentProviders);
+			supporter.setCapability(cap);
+		}
+
+		System.out.println("Supporting agent capabilities initialized!");
+
+	}
+
+	private void setClientAgentCapability() {
+		System.out.println("Setting client agent capability...");
+		this.client.setCapability(new MonitorMetricsCapability());
+		System.out.println("Client agent capability initialized!");
+	}
+
+	private void setInitialCurrentProviders(ArrayList<ServiceProviderAgent> providers) {
+		ServiceProviderAgent agent = providers.get(0);
+		CauseAnalysisCapability capability = (CauseAnalysisCapability) agent.getCapability();
+		HashMap<Service, Component> currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE1"), new Component("AGENT1"));
+		currentProviders.put(new Service("SERVICE2"), new Component("AGENT4"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(1);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE3"), new Component("AGENT7"));
+		currentProviders.put(new Service("SERVICE4"), new Component("AGENT10"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(2);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE3"), new Component("AGENT8"));
+		currentProviders.put(new Service("SERVICE4"), new Component("AGENT11"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(3);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE3"), new Component("AGENT9"));
+		currentProviders.put(new Service("SERVICE4"), new Component("AGENT12"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(4);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE5"), new Component("AGENT13"));
+		currentProviders.put(new Service("SERVICE6"), new Component("AGENT16"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(5);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE5"), new Component("AGENT14"));
+		currentProviders.put(new Service("SERVICE6"), new Component("AGENT17"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(6);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE5"), new Component("AGENT15"));
+		currentProviders.put(new Service("SERVICE6"), new Component("AGENT18"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(7);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE7"), new Component("AGENT19"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(8);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE7"), new Component("AGENT20"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(9);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE7"), new Component("AGENT21"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(10);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE8"), new Component("AGENT22"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(11);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE8"), new Component("AGENT23"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(12);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE8"), new Component("AGENT24"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(13);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE9"), new Component("AGENT25"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(14);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE9"), new Component("AGENT26"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(15);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE9"), new Component("AGENT27"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(16);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE10"), new Component("AGENT28"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(17);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE10"), new Component("AGENT29"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(18);
+		capability = (CauseAnalysisCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE10"), new Component("AGENT30"));
+		capability.setCurrentProviders(currentProviders);
+	}
+
+	private void setupDB(ServiceProviderAgent agent) {
+		TraceDAO dao = new TraceDAO(agent.getAID().getLocalName());
+		dao.dropCollection();
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/InteractiveRunner.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/InteractiveRunner.java
new file mode 100644
index 0000000..9f51ed1
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/InteractiveRunner.java
@@ -0,0 +1,646 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.experiment;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.log4j.PropertyConfigurator;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.core.SingleCapabilityAgent;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.event.GoalListener;
+import bdi4jade.examples.interactionprotocol.CauseAnalysisCapability;
+import bdi4jade.examples.interactionprotocol.MonitorMetricsCapability;
+import bdi4jade.examples.interactionprotocol.ServiceProviderAgent;
+import bdi4jade.examples.interactionprotocol.dao.TraceDAO;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Link;
+import bdi4jade.examples.interactionprotocol.domain.LinkMonitor;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.goal.MonitorMetricsGoal;
+import bdi4jade.examples.interactionprotocol.goal.RequestServiceGoal;
+import jade.BootProfileImpl;
+import jade.core.ProfileImpl;
+import jade.wrapper.AgentContainer;
+import jade.wrapper.AgentController;
+import jade.wrapper.PlatformController;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class InteractiveRunner implements GoalListener {
+
+	public static final int ITERATIONS = 120;
+
+	private ProfileImpl bootProfile;
+	private jade.core.Runtime runtime;
+	private PlatformController controller;
+
+	private ArrayList<ServiceProviderAgent> providerAgents;
+	private ArrayList<ServiceProviderAgent> supportingAgents;
+	private SingleCapabilityAgent client;
+
+	private int providerFailure;
+	private int linkFailure;
+	private int providerAndLinkFailure;
+	private int iteration;
+	private Instant startedAt;
+
+	public InteractiveRunner() {
+		this.startedAt = Instant.now();
+		this.providerFailure = 30;
+		this.linkFailure = 60;
+		this.providerAndLinkFailure = 90;
+		this.iteration = 0;
+		List<String> params = new ArrayList<String>();
+		params.add("-gui");
+		params.add("-detect-main:false");
+
+		this.bootProfile = new BootProfileImpl(params.toArray(new String[0]));
+		this.runtime = jade.core.Runtime.instance();
+		this.controller = runtime.createMainContainer(bootProfile);
+
+		this.providerAgents = createProviderAgents();
+		this.supportingAgents = createSupportingAgents();
+		this.client = new SingleCapabilityAgent(new MonitorMetricsCapability());
+
+		try {
+			AgentController ac = ((AgentContainer) controller).acceptNewAgent("CLIENT", this.client);
+			ac.start();
+
+			ArrayList<ServiceProviderAgent> agents = new ArrayList<>();
+			agents.addAll(providerAgents);
+			agents.addAll(supportingAgents);
+			for (ServiceProviderAgent agent : agents) {
+				ac = ((AgentContainer) controller).acceptNewAgent(agent.getCustomName(), agent);
+				ac.start();
+				setupDB(agent);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		for (ServiceProviderAgent providers : this.providerAgents) {
+			providers.register();
+		}
+	}
+
+	public static void main(String[] args) {
+		PropertyConfigurator.configure(InteractiveRunner.class.getResource("log4j.properties"));
+		InteractiveRunner runner = new InteractiveRunner();
+		runner.run();
+	}
+
+	public void run() {
+		try {
+			Thread.sleep(2000);
+			System.out.println("#ITERATION: " + this.iteration);
+			for (int i = 0; i < 3; i++) {
+				ServiceProviderAgent supporter = this.supportingAgents.get(i);
+				supporter.addGoal(new RequestServiceGoal(new Service("B"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("D"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("E"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("J"), null), this);
+				Thread.sleep(500);
+			}
+
+			for (int i = 3; i < 6; i++) {
+				ServiceProviderAgent supporter = this.supportingAgents.get(i);
+				supporter.addGoal(new RequestServiceGoal(new Service("C"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("G"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("N"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("X"), null), this);
+				Thread.sleep(500);
+			}
+			client.addGoal(new MonitorMetricsGoal(), this);
+
+			this.iteration++;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void goalPerformed(GoalEvent event) {
+		if (event.getStatus().isFinished() && event.getGoal() instanceof MonitorMetricsGoal) {
+			if (iteration < ITERATIONS) {
+				if (iteration == providerFailure) {
+					ServiceProviderAgent agent = this.providerAgents.get(15);
+					@SuppressWarnings("unchecked")
+					Belief<String, Boolean> failure = (Belief<String, Boolean>) agent.getCapability().getBeliefBase()
+							.getBelief("failure");
+					failure.setValue(true);
+					System.out.println("Setting failure to " + agent.getLocalName());
+				} else if (iteration == linkFailure) {
+					Link link = new Link(new Component("AGENT21"), new Component("AGENT30"), new Service("X"));
+					LinkMonitor.getInstance().getAnomalousLinks().add(link);
+					System.out.println("Setting failure to link: " + link);
+				} else if (iteration == providerAndLinkFailure) {
+					ServiceProviderAgent agent = this.providerAgents.get(6);
+					@SuppressWarnings("unchecked")
+					Belief<String, Boolean> failure = (Belief<String, Boolean>) agent.getCapability().getBeliefBase()
+							.getBelief("failure");
+					failure.setValue(true);
+					Link link = new Link(new Component("AGENT02"), new Component("AGENT07"), new Service("D"));
+					LinkMonitor.getInstance().getAnomalousLinks().add(link);
+					System.out.println("Setting failure to " + agent.getLocalName() + " and link " + link);
+				}
+				run();
+			} else {
+				Instant finishedAt = Instant.now();
+				System.out.println("Iterations finished in " + Duration.between(startedAt, finishedAt).getSeconds());
+			}
+		}
+	}
+
+	public HashMap<String, Integer> getAdjacencyList() {
+		HashMap<String, Integer> adjacencyList = new HashMap<>();
+		Random random = new Random(System.currentTimeMillis());
+
+		for (int i = 1; i <= 6; i++) {
+			adjacencyList.put("SUPPORT" + i, random.nextInt(10));
+		}
+		return adjacencyList;
+	}
+
+	public ArrayList<ServiceProviderAgent> createProviderAgents() {
+		ArrayList<ServiceProviderAgent> agents = new ArrayList<>();
+
+		ServiceProviderAgent agent = new ServiceProviderAgent("AGENT01");
+		HashMap<Service, ArrayList<Service>> agentServices = new HashMap<>();
+		ArrayList<Service> serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("B"));
+		serviceDependences.add(new Service("C"));
+		agentServices.put(new Service("A"), serviceDependences);
+		HashMap<Service, Component> currentProviders = new HashMap<>();
+		currentProviders.put(new Service("B"), new Component("AGENT02"));
+		currentProviders.put(new Service("C"), new Component("AGENT04"));
+		HashMap<String, Integer> knownNeighbours = getAdjacencyList();
+		CauseAnalysisCapability capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("A"), 1);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT02");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("D"));
+		serviceDependences.add(new Service("E"));
+		agentServices.put(new Service("B"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("D"), new Component("AGENT07"));
+		currentProviders.put(new Service("E"), new Component("AGENT08"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("B"), 2);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT03");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("F"));
+		agentServices.put(new Service("B"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("F"), new Component("AGENT10"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("B"), 5);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT04");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("G"));
+		agentServices.put(new Service("C"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("G"), new Component("AGENT11"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("C"), 2);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT05");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("H"));
+		agentServices.put(new Service("C"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("H"), new Component("AGENT13"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("C"), 5);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT06");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("I"));
+		agentServices.put(new Service("D"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("I"), new Component("AGENT14"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("D"), 5);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT07");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("D"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("D"), 2);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT08");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("J"));
+		agentServices.put(new Service("E"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("J"), new Component("AGENT16"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("E"), 2);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT09");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("K"));
+		agentServices.put(new Service("E"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("K"), new Component("AGENT17"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("E"), 5);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT10");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("L"));
+		serviceDependences.add(new Service("M"));
+		agentServices.put(new Service("F"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("L"), new Component("AGENT18"));
+		currentProviders.put(new Service("M"), new Component("AGENT19"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("F"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT11");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("N"));
+		agentServices.put(new Service("G"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("N"), new Component("AGENT21"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("G"), 2);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT12");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("O"));
+		serviceDependences.add(new Service("P"));
+		agentServices.put(new Service("G"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("O"), new Component("AGENT22"));
+		currentProviders.put(new Service("P"), new Component("AGENT23"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("G"), 5);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT13");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("Q"));
+		agentServices.put(new Service("H"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("Q"), new Component("AGENT24"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("H"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT14");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("I"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("I"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT15");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("R"));
+		serviceDependences.add(new Service("S"));
+		agentServices.put(new Service("J"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("R"), new Component("AGENT25"));
+		currentProviders.put(new Service("S"), new Component("AGENT26"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("J"), 5);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT16");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("J"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("J"), 2);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT17");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("T"));
+		agentServices.put(new Service("K"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("T"), new Component("AGENT27"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("K"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT18");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("L"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("L"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT19");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("M"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("M"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT20");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("U"));
+		serviceDependences.add(new Service("V"));
+		agentServices.put(new Service("N"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("U"), new Component("AGENT28"));
+		currentProviders.put(new Service("V"), new Component("AGENT29"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("N"), 5);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT21");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("X"));
+		agentServices.put(new Service("N"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("X"), new Component("AGENT30"));
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("N"), 2);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT22");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("O"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("O"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT23");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("P"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("P"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT24");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("Q"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("Q"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT25");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("R"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("R"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT26");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("S"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("S"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT27");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("T"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("T"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT28");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("U"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("U"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT29");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("V"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("V"), 4);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("AGENT30");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("X"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("X"), 2);
+		agent.setCapability(capability);
+		agents.add(agent);
+		
+		agent = new ServiceProviderAgent("AGENT31");
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("X"), serviceDependences);
+		knownNeighbours = getAdjacencyList();
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setServiceCost(new Service("X"), 5);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		return agents;
+	}
+
+	public ArrayList<ServiceProviderAgent> createSupportingAgents() {
+		ArrayList<ServiceProviderAgent> agents = new ArrayList<>();
+
+		HashMap<Service, ArrayList<Service>> agentServices = new HashMap<>();
+		HashMap<String, Integer> knownNeighbours = new HashMap<>();
+		HashMap<Service, Component> currentProviders = new HashMap<>();
+		currentProviders.put(new Service("B"), new Component("AGENT02"));
+		currentProviders.put(new Service("D"), new Component("AGENT07"));
+		currentProviders.put(new Service("E"), new Component("AGENT08"));
+		currentProviders.put(new Service("J"), new Component("AGENT16"));
+
+		ServiceProviderAgent agent = new ServiceProviderAgent("SUPPORT1");
+		CauseAnalysisCapability capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("SUPPORT2");
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("SUPPORT3");
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("C"), new Component("AGENT04"));
+		currentProviders.put(new Service("G"), new Component("AGENT11"));
+		currentProviders.put(new Service("N"), new Component("AGENT21"));
+		currentProviders.put(new Service("X"), new Component("AGENT30"));
+
+		agent = new ServiceProviderAgent("SUPPORT4");
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("SUPPORT5");
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		agent = new ServiceProviderAgent("SUPPORT6");
+		capability = new CauseAnalysisCapability(agent, agentServices, knownNeighbours);
+		capability.setCurrentProviders(currentProviders);
+		agent.setCapability(capability);
+		agents.add(agent);
+
+		return agents;
+	}
+
+	private void setupDB(ServiceProviderAgent agent) {
+		TraceDAO dao = new TraceDAO(agent.getAID().getLocalName());
+		dao.dropCollection();
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/log4j.properties b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/log4j.properties
new file mode 100644
index 0000000..2c12d74
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/log4j.properties
@@ -0,0 +1,42 @@
+#
+# Log4J Settings for log4j 1.2.x (via jakarta-commons-logging)
+#
+# The five logging levels used by Log are (in order):
+#
+#   1. DEBUG (the least serious)
+#   2. INFO
+#   3. WARN
+#   4. ERROR
+#   5. FATAL (the most serious)
+
+
+# Set root logger level to WARN and append to stdout
+log4j.rootLogger=WARN
+
+#log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+#log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+
+# Pattern to output the caller's file name and line number.
+#log4j.appender.stdout.layout.ConversionPattern=%d{HH:mm:ss,SSS} %5p (%c{1}:%L) - %m%n
+
+# Print only messages of level ERROR or above in the package noModule.
+log4j.logger.noModule=FATAL
+
+# OpenSymphony Stuff
+log4j.logger.com.opensymphony=FATAL
+log4j.logger.org.apache.struts2=FATAL
+
+# Spring Stuff
+log4j.logger.org.springframework=FATAL
+
+#log4j.logger.bdi4jade=WARN
+#log4j.logger.bdi4jade.examples=DEBUG
+#log4j.logger.bdi4jade.extension=DEBUG, fileOut
+#log4j.logger.com.paradox.braess=INFO, fileOut
+log4j.logger.bdi4jade.examples.undo=DEBUG, fileOut
+log4j.logger.bdi4jade.examples.interactionprotocol=DEGUB, fileOut
+
+log4j.appender.fileOut =org.apache.log4j.RollingFileAppender
+log4j.appender.fileOut.File=causeAnalysis_out.log
+log4j.appender.fileOut.layout=org.apache.log4j.PatternLayout
+log4j.appender.fileOut.layout.ConversionPattern= %d{ABSOLUTE}\t%m%n
\ No newline at end of file
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/PassiveRunner.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/PassiveRunner.java
new file mode 100644
index 0000000..74c7ff3
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/PassiveRunner.java
@@ -0,0 +1,568 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.experiment;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.log4j.PropertyConfigurator;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.core.SingleCapabilityAgent;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.event.GoalListener;
+import bdi4jade.examples.interactionprotocol.MonitorMetricsCapability;
+import bdi4jade.examples.interactionprotocol.dao.TraceDAO;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Link;
+import bdi4jade.examples.interactionprotocol.domain.LinkMonitor;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.dummy.DummyCapability;
+import bdi4jade.examples.interactionprotocol.dummy.DummyServiceProvider;
+import bdi4jade.examples.interactionprotocol.goal.MonitorMetricsGoal;
+import bdi4jade.examples.interactionprotocol.goal.RequestServiceGoal;
+import jade.BootProfileImpl;
+import jade.core.ProfileImpl;
+import jade.wrapper.AgentContainer;
+import jade.wrapper.AgentController;
+import jade.wrapper.PlatformController;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class PassiveRunner implements GoalListener {
+
+	public static final int ITERATIONS = 120;
+
+	private ProfileImpl bootProfile;
+	private jade.core.Runtime runtime;
+	private PlatformController controller;
+
+	private ArrayList<DummyServiceProvider> providerAgents;
+	private ArrayList<DummyServiceProvider> supportingAgents;
+	private SingleCapabilityAgent client;
+
+	private int providerFailure;
+	private int linkFailure;
+	private int providerAndLinkFailure;
+	private int iteration;
+	private Instant startedAt;
+
+	public PassiveRunner() {
+		this.startedAt = Instant.now();
+		this.providerFailure = 30;
+		this.linkFailure = 60;
+		this.providerAndLinkFailure = 90;
+		this.iteration = 0;
+		List<String> params = new ArrayList<String>();
+		params.add("-gui");
+		params.add("-detect-main:false");
+
+		this.bootProfile = new BootProfileImpl(params.toArray(new String[0]));
+		this.runtime = jade.core.Runtime.instance();
+		this.controller = runtime.createMainContainer(bootProfile);
+
+		this.providerAgents = createProviderAgents();
+		this.supportingAgents = createSupportingAgents();
+		this.client = new SingleCapabilityAgent(new MonitorMetricsCapability());
+
+		try {
+			AgentController ac = ((AgentContainer) controller).acceptNewAgent("CLIENT", this.client);
+			ac.start();
+
+			ArrayList<DummyServiceProvider> agents = new ArrayList<>();
+			agents.addAll(providerAgents);
+			agents.addAll(supportingAgents);
+			for (DummyServiceProvider agent : agents) {
+				ac = ((AgentContainer) controller).acceptNewAgent(agent.getCustomName(), agent);
+				ac.start();
+				setupDB(agent);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		for (DummyServiceProvider providers : this.providerAgents) {
+			providers.register();
+		}
+
+	}
+
+	public static void main(String[] args) {
+		PropertyConfigurator.configure(PassiveRunner.class.getResource("log4j.properties"));
+		PassiveRunner runner = new PassiveRunner();
+		runner.run();
+	}
+
+	public void run() {
+		try {
+			Thread.sleep(2000);
+			System.out.println("#ITERATION: " + this.iteration);
+			for (int i = 0; i < 3; i++) {
+				DummyServiceProvider supporter = this.supportingAgents.get(i);
+				supporter.addGoal(new RequestServiceGoal(new Service("B"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("D"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("E"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("J"), null), this);
+				Thread.sleep(500);
+			}
+
+			for (int i = 3; i < 6; i++) {
+				DummyServiceProvider supporter = this.supportingAgents.get(i);
+				supporter.addGoal(new RequestServiceGoal(new Service("C"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("G"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("N"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("X"), null), this);
+				Thread.sleep(500);
+			}
+			client.addGoal(new MonitorMetricsGoal(), this);
+
+			this.iteration++;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void goalPerformed(GoalEvent event) {
+		if (event.getStatus().isFinished() && event.getGoal() instanceof MonitorMetricsGoal) {
+			if (iteration < ITERATIONS) {
+				if (iteration == providerFailure) {
+					DummyServiceProvider agent = this.providerAgents.get(15);
+					@SuppressWarnings("unchecked")
+					Belief<String, Boolean> failure = (Belief<String, Boolean>) agent.getCapability().getBeliefBase()
+							.getBelief("failure");
+					failure.setValue(true);
+					System.out.println("Setting failure to " + agent.getLocalName());
+				} else if (iteration == linkFailure) {
+					Link link = new Link(new Component("AGENT21"), new Component("AGENT30"), new Service("X"));
+					LinkMonitor.getInstance().getAnomalousLinks().add(link);
+					System.out.println("Setting failure to link: " + link);
+				} else if (iteration == providerAndLinkFailure) {
+					DummyServiceProvider agent = this.providerAgents.get(6);
+					@SuppressWarnings("unchecked")
+					Belief<String, Boolean> failure = (Belief<String, Boolean>) agent.getCapability().getBeliefBase()
+							.getBelief("failure");
+					failure.setValue(true);
+					Link link = new Link(new Component("AGENT02"), new Component("AGENT07"), new Service("D"));
+					LinkMonitor.getInstance().getAnomalousLinks().add(link);
+					System.out.println("Setting failure to " + agent.getLocalName() + " and link " + link);
+				}
+				run();
+			} else {
+				Instant finishedAt = Instant.now();
+				System.out.println("Iterations finished in " + Duration.between(startedAt, finishedAt).getSeconds());
+				
+			}
+		}
+	}
+
+	public ArrayList<DummyServiceProvider> createProviderAgents() {
+		ArrayList<DummyServiceProvider> agents = new ArrayList<>();
+
+		HashMap<Service, ArrayList<Service>> agentServices = new HashMap<>();
+		ArrayList<Service> serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("B"));
+		serviceDependences.add(new Service("C"));
+		agentServices.put(new Service("A"), serviceDependences);
+		HashMap<Service, Component> currentProviders = new HashMap<>();
+		currentProviders.put(new Service("B"), new Component("AGENT02"));
+		currentProviders.put(new Service("C"), new Component("AGENT04"));
+		DummyCapability capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("A"), 1);
+		DummyServiceProvider agent = new DummyServiceProvider("AGENT01", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("D"));
+		serviceDependences.add(new Service("E"));
+		agentServices.put(new Service("B"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("D"), new Component("AGENT07"));
+		currentProviders.put(new Service("E"), new Component("AGENT08"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("B"), 2);
+		agent = new DummyServiceProvider("AGENT02", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("F"));
+		agentServices.put(new Service("B"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("F"), new Component("AGENT10"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("B"), 5);
+		agent = new DummyServiceProvider("AGENT03", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("G"));
+		agentServices.put(new Service("C"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("G"), new Component("AGENT11"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("C"), 2);
+		agent = new DummyServiceProvider("AGENT04", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("H"));
+		agentServices.put(new Service("C"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("H"), new Component("AGENT13"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("C"), 5);
+		agent = new DummyServiceProvider("AGENT05", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("I"));
+		agentServices.put(new Service("D"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("I"), new Component("AGENT14"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("D"), 5);
+		agent = new DummyServiceProvider("AGENT06", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("D"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("D"), 2);
+		agent = new DummyServiceProvider("AGENT07", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("J"));
+		agentServices.put(new Service("E"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("J"), new Component("AGENT16"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("E"), 2);
+		agent = new DummyServiceProvider("AGENT08", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("K"));
+		agentServices.put(new Service("E"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("K"), new Component("AGENT17"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("E"), 5);
+		agent = new DummyServiceProvider("AGENT09", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("L"));
+		serviceDependences.add(new Service("M"));
+		agentServices.put(new Service("F"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("L"), new Component("AGENT18"));
+		currentProviders.put(new Service("M"), new Component("AGENT19"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("F"), 4);
+		agent = new DummyServiceProvider("AGENT10", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("N"));
+		agentServices.put(new Service("G"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("N"), new Component("AGENT21"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("G"), 2);
+		agent = new DummyServiceProvider("AGENT11", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("O"));
+		serviceDependences.add(new Service("P"));
+		agentServices.put(new Service("G"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("O"), new Component("AGENT22"));
+		currentProviders.put(new Service("P"), new Component("AGENT23"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("G"), 5);
+		agent = new DummyServiceProvider("AGENT12", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("Q"));
+		agentServices.put(new Service("H"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("Q"), new Component("AGENT24"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("H"), 4);
+		agent = new DummyServiceProvider("AGENT13", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("I"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("I"), 4);
+		agent = new DummyServiceProvider("AGENT14", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("R"));
+		serviceDependences.add(new Service("S"));
+		agentServices.put(new Service("J"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("R"), new Component("AGENT25"));
+		currentProviders.put(new Service("S"), new Component("AGENT26"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("J"), 5);
+		agent = new DummyServiceProvider("AGENT15", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("J"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("J"), 2);
+		agent = new DummyServiceProvider("AGENT16", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("T"));
+		agentServices.put(new Service("K"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("T"), new Component("AGENT27"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("K"), 4);
+		agent = new DummyServiceProvider("AGENT17", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("L"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("L"), 4);
+		agent = new DummyServiceProvider("AGENT18", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("M"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("M"), 4);
+		agent = new DummyServiceProvider("AGENT19", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("U"));
+		serviceDependences.add(new Service("V"));
+		agentServices.put(new Service("N"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("U"), new Component("AGENT28"));
+		currentProviders.put(new Service("V"), new Component("AGENT29"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("N"), 5);
+		agent = new DummyServiceProvider("AGENT20", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("X"));
+		agentServices.put(new Service("N"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("X"), new Component("AGENT30"));
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("N"), 2);
+		agent = new DummyServiceProvider("AGENT21", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("O"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("O"), 4);
+		agent = new DummyServiceProvider("AGENT22", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("P"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("P"), 4);
+		agent = new DummyServiceProvider("AGENT23", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("Q"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("Q"), 4);
+		agent = new DummyServiceProvider("AGENT24", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("R"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("R"), 4);
+		agent = new DummyServiceProvider("AGENT25", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("S"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("S"), 4);
+		agent = new DummyServiceProvider("AGENT26", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("T"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("T"), 4);
+		agent = new DummyServiceProvider("AGENT27", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("U"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("U"), 4);
+		agent = new DummyServiceProvider("AGENT28", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("V"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("V"), 4);
+		agent = new DummyServiceProvider("AGENT29", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("X"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("X"), 2);
+		agent = new DummyServiceProvider("AGENT30", capability);
+		agents.add(agent);
+		
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("X"), serviceDependences);
+		capability = new DummyCapability(agentServices);
+		capability.setServiceCost(new Service("X"), 5);
+		agent = new DummyServiceProvider("AGENT31", capability);
+		agents.add(agent);
+
+		return agents;
+	}
+
+	public ArrayList<DummyServiceProvider> createSupportingAgents() {
+		ArrayList<DummyServiceProvider> agents = new ArrayList<>();
+
+		HashMap<Service, ArrayList<Service>> agentServices = new HashMap<>();
+		HashMap<Service, Component> currentProviders = new HashMap<>();
+		currentProviders.put(new Service("B"), new Component("AGENT02"));
+		currentProviders.put(new Service("D"), new Component("AGENT07"));
+		currentProviders.put(new Service("E"), new Component("AGENT08"));
+		currentProviders.put(new Service("J"), new Component("AGENT16"));
+
+		DummyCapability capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		DummyServiceProvider agent = new DummyServiceProvider("SUPPORT1", capability);
+		agents.add(agent);
+
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		agent = new DummyServiceProvider("SUPPORT2", capability);
+		agents.add(agent);
+
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		agent = new DummyServiceProvider("SUPPORT3", capability);
+		agents.add(agent);
+
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("C"), new Component("AGENT04"));
+		currentProviders.put(new Service("G"), new Component("AGENT11"));
+		currentProviders.put(new Service("N"), new Component("AGENT21"));
+		currentProviders.put(new Service("X"), new Component("AGENT30"));
+
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		agent = new DummyServiceProvider("SUPPORT4", capability);
+		agents.add(agent);
+
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		agent = new DummyServiceProvider("SUPPORT5", capability);
+		agents.add(agent);
+
+		capability = new DummyCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		agent = new DummyServiceProvider("SUPPORT6", capability);
+		agents.add(agent);
+
+		return agents;
+	}
+
+	private void setupDB(DummyServiceProvider agent) {
+		TraceDAO dao = new TraceDAO(agent.getAID().getLocalName());
+		dao.dropCollection();
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/RemedialRunner.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/RemedialRunner.java
new file mode 100644
index 0000000..cebd100
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/RemedialRunner.java
@@ -0,0 +1,549 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.experiment;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.log4j.PropertyConfigurator;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.core.SingleCapabilityAgent;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.event.GoalListener;
+import bdi4jade.examples.interactionprotocol.MonitorMetricsCapability;
+import bdi4jade.examples.interactionprotocol.dao.TraceDAO;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Link;
+import bdi4jade.examples.interactionprotocol.domain.LinkMonitor;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.goal.MonitorMetricsGoal;
+import bdi4jade.examples.interactionprotocol.goal.RequestServiceGoal;
+import bdi4jade.examples.interactionprotocol.remedial.RemedialCapability;
+import bdi4jade.examples.interactionprotocol.remedial.RemedialServiceProvider;
+import jade.BootProfileImpl;
+import jade.core.ProfileImpl;
+import jade.wrapper.AgentContainer;
+import jade.wrapper.AgentController;
+import jade.wrapper.PlatformController;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class RemedialRunner implements GoalListener {
+
+	public static final int ITERATIONS = 120;
+
+	private ProfileImpl bootProfile;
+	private jade.core.Runtime runtime;
+	private PlatformController controller;
+
+	private ArrayList<RemedialServiceProvider> providerAgents;
+	private ArrayList<RemedialServiceProvider> supportingAgents;
+	private SingleCapabilityAgent client;
+
+	private int providerFailure;
+	private int linkFailure;
+	private int providerAndLinkFailure;
+	private int iteration;
+	private Instant startedAt;
+
+	public RemedialRunner() {
+		this.startedAt = Instant.now();
+		this.providerFailure = 30;
+		this.linkFailure = 60;
+		this.providerAndLinkFailure = 90;
+		this.iteration = 0;
+		List<String> params = new ArrayList<String>();
+		params.add("-gui");
+		params.add("-detect-main:false");
+
+		this.bootProfile = new BootProfileImpl(params.toArray(new String[0]));
+		this.runtime = jade.core.Runtime.instance();
+		this.controller = runtime.createMainContainer(bootProfile);
+
+		this.providerAgents = createProviderAgents();
+		this.supportingAgents = createSupportingAgents();
+		this.client = new SingleCapabilityAgent(new MonitorMetricsCapability());
+
+		try {
+			AgentController ac = ((AgentContainer) controller).acceptNewAgent("CLIENT", this.client);
+			ac.start();
+
+			ArrayList<RemedialServiceProvider> agents = new ArrayList<>();
+			agents.addAll(providerAgents);
+			agents.addAll(supportingAgents);
+			for (RemedialServiceProvider agent : agents) {
+				ac = ((AgentContainer) controller).acceptNewAgent(agent.getCustomName(), agent);
+				ac.start();
+				setupDB(agent);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		for (RemedialServiceProvider providers : this.providerAgents) {
+			providers.register();
+		}
+	}
+
+	public static void main(String[] args) {
+		PropertyConfigurator.configure(RemedialRunner.class.getResource("log4j.properties"));
+		RemedialRunner runner = new RemedialRunner();
+		runner.run();
+	}
+
+	public void run() {
+		try {
+			Thread.sleep(2000);
+			System.out.println("#ITERATION: " + this.iteration);
+			for (int i = 0; i < 3; i++) {
+				RemedialServiceProvider supporter = this.supportingAgents.get(i);
+				supporter.addGoal(new RequestServiceGoal(new Service("B"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("D"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("E"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("J"), null), this);
+				Thread.sleep(500);
+			}
+
+			for (int i = 3; i < 6; i++) {
+				RemedialServiceProvider supporter = this.supportingAgents.get(i);
+				supporter.addGoal(new RequestServiceGoal(new Service("C"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("G"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("N"), null), this);
+				supporter.addGoal(new RequestServiceGoal(new Service("X"), null), this);
+				Thread.sleep(500);
+			}
+			client.addGoal(new MonitorMetricsGoal(), this);
+
+			this.iteration++;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void goalPerformed(GoalEvent event) {
+		if (event.getStatus().isFinished() && event.getGoal() instanceof MonitorMetricsGoal) {
+			if (iteration < ITERATIONS) {
+				if (iteration == providerFailure) {
+					RemedialServiceProvider agent = this.providerAgents.get(15);
+					@SuppressWarnings("unchecked")
+					Belief<String, Boolean> failure = (Belief<String, Boolean>) agent.getCapability().getBeliefBase()
+							.getBelief("failure");
+					failure.setValue(true);
+					System.out.println("Setting failure to " + agent.getLocalName());
+				} else if (iteration == linkFailure) {
+					Link link = new Link(new Component("AGENT21"), new Component("AGENT30"), new Service("X"));
+					LinkMonitor.getInstance().getAnomalousLinks().add(link);
+					System.out.println("Setting failure to link: " + link);
+				} else if (iteration == providerAndLinkFailure) {
+					RemedialServiceProvider agent = this.providerAgents.get(6);
+					@SuppressWarnings("unchecked")
+					Belief<String, Boolean> failure = (Belief<String, Boolean>) agent.getCapability().getBeliefBase()
+							.getBelief("failure");
+					failure.setValue(true);
+					Link link = new Link(new Component("AGENT02"), new Component("AGENT07"), new Service("D"));
+					LinkMonitor.getInstance().getAnomalousLinks().add(link);
+					System.out.println("Setting failure to " + agent.getLocalName() + " and link " + link);
+				}
+				run();
+			} else {
+				Instant finishedAt = Instant.now();
+				System.out.println("Iterations finished in " + Duration.between(startedAt, finishedAt).getSeconds());
+			}
+		}
+	}
+
+	public ArrayList<RemedialServiceProvider> createProviderAgents() {
+		ArrayList<RemedialServiceProvider> agents = new ArrayList<>();
+
+		HashMap<Service, ArrayList<Service>> agentServices = new HashMap<>();
+		ArrayList<Service> serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("B"));
+		serviceDependences.add(new Service("C"));
+		agentServices.put(new Service("A"), serviceDependences);
+		HashMap<Service, Component> currentProviders = new HashMap<>();
+		currentProviders.put(new Service("B"), new Component("AGENT02"));
+		currentProviders.put(new Service("C"), new Component("AGENT04"));
+		RemedialCapability capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("A"), 1);
+		RemedialServiceProvider agent = new RemedialServiceProvider("AGENT01", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("D"));
+		serviceDependences.add(new Service("E"));
+		agentServices.put(new Service("B"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("D"), new Component("AGENT07"));
+		currentProviders.put(new Service("E"), new Component("AGENT08"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("B"), 2);
+		agent = new RemedialServiceProvider("AGENT02", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("F"));
+		agentServices.put(new Service("B"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("F"), new Component("AGENT10"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("B"), 5);
+		agent = new RemedialServiceProvider("AGENT03", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("G"));
+		agentServices.put(new Service("C"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("G"), new Component("AGENT11"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("C"), 2);
+		agent = new RemedialServiceProvider("AGENT04", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("H"));
+		agentServices.put(new Service("C"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("H"), new Component("AGENT13"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("C"), 5);
+		agent = new RemedialServiceProvider("AGENT05", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("I"));
+		agentServices.put(new Service("D"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("I"), new Component("AGENT14"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("D"), 5);
+		agent = new RemedialServiceProvider("AGENT06", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("D"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("D"), 2);
+		agent = new RemedialServiceProvider("AGENT07", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("J"));
+		agentServices.put(new Service("E"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("J"), new Component("AGENT16"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("E"), 2);
+		agent = new RemedialServiceProvider("AGENT08", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("K"));
+		agentServices.put(new Service("E"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("K"), new Component("AGENT17"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("E"), 5);
+		agent = new RemedialServiceProvider("AGENT09", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("L"));
+		serviceDependences.add(new Service("M"));
+		agentServices.put(new Service("F"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("L"), new Component("AGENT18"));
+		currentProviders.put(new Service("M"), new Component("AGENT19"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("F"), 4);
+		agent = new RemedialServiceProvider("AGENT10", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("N"));
+		agentServices.put(new Service("G"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("N"), new Component("AGENT21"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("G"), 2);
+		agent = new RemedialServiceProvider("AGENT11", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("O"));
+		serviceDependences.add(new Service("P"));
+		agentServices.put(new Service("G"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("O"), new Component("AGENT22"));
+		currentProviders.put(new Service("P"), new Component("AGENT23"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("G"), 5);
+		agent = new RemedialServiceProvider("AGENT12", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("Q"));
+		agentServices.put(new Service("H"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("Q"), new Component("AGENT24"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("H"), 4);
+		agent = new RemedialServiceProvider("AGENT13", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("I"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("I"), 4);
+		agent = new RemedialServiceProvider("AGENT14", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("R"));
+		serviceDependences.add(new Service("S"));
+		agentServices.put(new Service("J"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("R"), new Component("AGENT25"));
+		currentProviders.put(new Service("S"), new Component("AGENT26"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("J"), 5);
+		agent = new RemedialServiceProvider("AGENT15", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("J"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("J"), 2);
+		agent = new RemedialServiceProvider("AGENT16", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("T"));
+		agentServices.put(new Service("K"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("T"), new Component("AGENT27"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("K"), 4);
+		agent = new RemedialServiceProvider("AGENT17", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("L"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("L"), 4);
+		agent = new RemedialServiceProvider("AGENT18", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("M"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("M"), 4);
+		agent = new RemedialServiceProvider("AGENT19", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("U"));
+		serviceDependences.add(new Service("V"));
+		agentServices.put(new Service("N"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("U"), new Component("AGENT28"));
+		currentProviders.put(new Service("V"), new Component("AGENT29"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("N"), 5);
+		agent = new RemedialServiceProvider("AGENT20", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		serviceDependences.add(new Service("X"));
+		agentServices.put(new Service("N"), serviceDependences);
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("X"), new Component("AGENT30"));
+		capability = new RemedialCapability(agentServices);
+		capability.setCurrentProviders(currentProviders);
+		capability.setServiceCost(new Service("N"), 2);
+		agent = new RemedialServiceProvider("AGENT21", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("O"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("O"), 4);
+		agent = new RemedialServiceProvider("AGENT22", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("P"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("P"), 4);
+		agent = new RemedialServiceProvider("AGENT23", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("Q"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("Q"), 4);
+		agent = new RemedialServiceProvider("AGENT24", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("R"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("R"), 4);
+		agent = new RemedialServiceProvider("AGENT25", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("S"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("S"), 4);
+		agent = new RemedialServiceProvider("AGENT26", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("T"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("T"), 4);
+		agent = new RemedialServiceProvider("AGENT27", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("U"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("U"), 4);
+		agent = new RemedialServiceProvider("AGENT28", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("V"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("V"), 4);
+		agent = new RemedialServiceProvider("AGENT29", capability);
+		agents.add(agent);
+
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("X"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("X"), 2);
+		agent = new RemedialServiceProvider("AGENT30", capability);
+		agents.add(agent);
+		
+		agentServices = new HashMap<>();
+		serviceDependences = new ArrayList<>();
+		agentServices.put(new Service("X"), serviceDependences);
+		capability = new RemedialCapability(agentServices);
+		capability.setServiceCost(new Service("X"), 5);
+		agent = new RemedialServiceProvider("AGENT31", capability);
+		agents.add(agent);
+
+		return agents;
+	}
+
+	public ArrayList<RemedialServiceProvider> createSupportingAgents() {
+		ArrayList<RemedialServiceProvider> agents = new ArrayList<>();
+
+		HashMap<Service, ArrayList<Service>> agentServices = new HashMap<>();
+		HashMap<Service, Component> currentProviders = new HashMap<>();
+		currentProviders.put(new Service("B"), new Component("AGENT02"));
+		currentProviders.put(new Service("D"), new Component("AGENT07"));
+		currentProviders.put(new Service("E"), new Component("AGENT08"));
+		currentProviders.put(new Service("J"), new Component("AGENT16"));
+
+		for (int i = 1; i <= 3; i++) {
+			RemedialCapability capability = new RemedialCapability(agentServices);
+			capability.setCurrentProviders(currentProviders);
+			RemedialServiceProvider agent = new RemedialServiceProvider("SUPPORT" + i, capability);
+			agents.add(agent);
+		}
+
+		currentProviders = new HashMap<>();
+		currentProviders.put(new Service("C"), new Component("AGENT04"));
+		currentProviders.put(new Service("G"), new Component("AGENT11"));
+		currentProviders.put(new Service("N"), new Component("AGENT21"));
+		currentProviders.put(new Service("X"), new Component("AGENT30"));
+
+		for (int i = 4; i <= 6; i++) {
+			RemedialCapability capability = new RemedialCapability(agentServices);
+			capability.setCurrentProviders(currentProviders);
+			RemedialServiceProvider agent = new RemedialServiceProvider("SUPPORT" + i, capability);
+			agents.add(agent);
+		}
+
+		return agents;
+	}
+
+	private void setupDB(RemedialServiceProvider agent) {
+		TraceDAO dao = new TraceDAO(agent.getAID().getLocalName());
+		dao.dropCollection();
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/RemedialRunnerOld.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/RemedialRunnerOld.java
new file mode 100644
index 0000000..b510f0c
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/experiment/RemedialRunnerOld.java
@@ -0,0 +1,360 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.experiment;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.log4j.PropertyConfigurator;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.core.SingleCapabilityAgent;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.event.GoalListener;
+import bdi4jade.examples.interactionprotocol.MonitorMetricsCapability;
+import bdi4jade.examples.interactionprotocol.dao.TraceDAO;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.goal.MonitorMetricsGoal;
+import bdi4jade.examples.interactionprotocol.remedial.RemedialCapability;
+import bdi4jade.examples.interactionprotocol.remedial.RemedialServiceProvider;
+import jade.BootProfileImpl;
+import jade.core.ProfileImpl;
+import jade.wrapper.AgentContainer;
+import jade.wrapper.AgentController;
+import jade.wrapper.PlatformController;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class RemedialRunnerOld implements GoalListener {
+
+	public static final int ITERATIONS = 100;
+
+	private ProfileImpl bootProfile;
+	private jade.core.Runtime runtime;
+	private PlatformController controller;
+
+	private ArrayList<RemedialServiceProvider> providers;
+	private SingleCapabilityAgent client;
+
+	private int failurePoint;
+	private int iteration;
+
+	public RemedialRunnerOld() {
+		this.failurePoint = 50;
+		this.iteration = 0;
+		List<String> params = new ArrayList<String>();
+		params.add("-gui");
+		params.add("-detect-main:false");
+
+		this.bootProfile = new BootProfileImpl(params.toArray(new String[0]));
+		this.runtime = jade.core.Runtime.instance();
+		this.controller = runtime.createMainContainer(bootProfile);
+
+		this.providers = initializeProviderAgents();
+		initializeClientAgent();
+
+		HashMap<Service, ArrayList<Service>> serviceDependences = initializeServiceDependenceList();
+
+		setAgentCapabilitiesAndServices(this.providers, serviceDependences);
+
+		for (RemedialServiceProvider providers : this.providers) {
+			providers.register();
+		}
+
+		setInitialCurrentProviders(this.providers);
+	}
+
+	public static void main(String[] args) {
+		PropertyConfigurator.configure(RemedialRunnerOld.class.getResource("log4j.properties"));
+		RemedialRunnerOld runner = new RemedialRunnerOld();
+		runner.run();
+	}
+
+	public void run() {
+		try {
+			Thread.sleep(2000);
+			client.addGoal(new MonitorMetricsGoal(), this);
+
+			this.iteration++;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void goalPerformed(GoalEvent event) {
+		if (event.getStatus().isFinished() && event.getGoal() instanceof MonitorMetricsGoal) {
+			if (iteration < ITERATIONS) {
+				if (iteration == failurePoint) {
+
+					RemedialServiceProvider agent = providers.get(4);
+					Belief<String, Boolean> failure = (Belief<String, Boolean>) agent.getCapability().getBeliefBase()
+							.getBelief("failure");
+					failure.setValue(true);
+					System.out.println("Setting failure to " + agent.getLocalName());
+
+					/*
+					 * Link link = new Link(new Component("AGENT0"), new Component("AGENT4"), new
+					 * Service("SERVICE2"));
+					 * LinkMonitor.getInstance().getAnomalousLinks().add(link);
+					 * System.out.println("Setting failure to link: " + link);
+					 */
+
+				}
+
+				run();
+			} else {
+				System.out.println("Iterations finished!!");
+			}
+		}
+	}
+
+	private ArrayList<RemedialServiceProvider> initializeProviderAgents() {
+		System.out.println("Initializing 31 service providers...");
+		ArrayList<RemedialServiceProvider> agents = new ArrayList<>();
+
+		try {
+			for (int i = 0; i < 31; i++) {
+				RemedialServiceProvider agent = new RemedialServiceProvider("AGENT" + i);
+				agents.add(agent);
+				AgentController ac = ((AgentContainer) controller).acceptNewAgent(agent.getCustomName(), agent);
+				ac.start();
+				setupDB(agent);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		System.out.println("Provider agents initialized!");
+		return agents;
+	}
+
+	private void initializeClientAgent() {
+		System.out.println("Initializing client agent...");
+		this.client = new SingleCapabilityAgent();
+		try {
+			AgentController ac = ((AgentContainer) controller).acceptNewAgent("CLIENT", this.client);
+			ac.start();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		System.out.println("Client agent initalized!");
+	}
+
+	private HashMap<Service, ArrayList<Service>> initializeServiceDependenceList() {
+		System.out.println("Creating service dependence list for 10 services...");
+		HashMap<Service, ArrayList<Service>> dependenceList = new HashMap<>();
+		for (int i = 0; i < 3; i++) {
+			Service service = new Service("SERVICE" + i);
+			ArrayList<Service> serviceDependences = new ArrayList<Service>();
+			serviceDependences.add(new Service("SERVICE" + (2 * i + 1)));
+			serviceDependences.add(new Service("SERVICE" + (2 * i + 2)));
+			dependenceList.put(service, serviceDependences);
+		}
+
+		for (int i = 3, j = 1; i < 7; i++, j--) {
+			Service service = new Service("SERVICE" + i);
+			ArrayList<Service> serviceDependences = new ArrayList<Service>();
+			serviceDependences.add(new Service("SERVICE" + (2 * i + j)));
+			dependenceList.put(service, serviceDependences);
+		}
+
+		return dependenceList;
+	}
+
+	private void setAgentCapabilitiesAndServices(ArrayList<RemedialServiceProvider> providers,
+			HashMap<Service, ArrayList<Service>> serviceDependences) {
+
+		setClientAgentCapability();
+		System.out.println("Setting provider agent capabilities...");
+
+		RemedialServiceProvider a0 = providers.get(0);
+		HashMap<Service, ArrayList<Service>> myServices = new HashMap<Service, ArrayList<Service>>();
+		Service s0 = new Service("SERVICE0");
+		myServices.put(s0, serviceDependences.get(s0));
+		RemedialCapability capability = new RemedialCapability(myServices);
+		capability.setServiceCost(s0, 0);
+		a0.setCapability(capability);
+
+		int agentCounter = 1;
+
+		for (int i = 1; i < 11; i++) {
+			for (int j = 0; j < 3; j++) {
+				RemedialServiceProvider provider = providers.get(agentCounter);
+				Service service = new Service("SERVICE" + i);
+
+				myServices = new HashMap<Service, ArrayList<Service>>();
+				ArrayList<Service> dependences = new ArrayList<Service>();
+				if (serviceDependences.get(service) != null) {
+					dependences = serviceDependences.get(service);
+				}
+				myServices.put(service, dependences);
+				capability = new RemedialCapability(myServices);
+				capability.setServiceCost(service, agentCounter);
+
+				provider.setCapability(capability);
+				agentCounter++;
+			}
+		}
+		System.out.println("Provider agent capabilities initialized!");
+	}
+
+	private void setClientAgentCapability() {
+		System.out.println("Setting client agent capability...");
+		this.client.setCapability(new MonitorMetricsCapability());
+		System.out.println("Client agent capability initialized!");
+	}
+
+	private void setInitialCurrentProviders(ArrayList<RemedialServiceProvider> providers) {
+		RemedialServiceProvider agent = providers.get(0);
+		RemedialCapability capability = (RemedialCapability) agent.getCapability();
+		HashMap<Service, Component> currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE1"), new Component("AGENT1"));
+		currentProviders.put(new Service("SERVICE2"), new Component("AGENT4"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(1);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE3"), new Component("AGENT7"));
+		currentProviders.put(new Service("SERVICE4"), new Component("AGENT10"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(2);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE3"), new Component("AGENT8"));
+		currentProviders.put(new Service("SERVICE4"), new Component("AGENT11"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(3);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE3"), new Component("AGENT9"));
+		currentProviders.put(new Service("SERVICE4"), new Component("AGENT12"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(4);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE5"), new Component("AGENT13"));
+		currentProviders.put(new Service("SERVICE6"), new Component("AGENT16"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(5);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE5"), new Component("AGENT14"));
+		currentProviders.put(new Service("SERVICE6"), new Component("AGENT17"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(6);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE5"), new Component("AGENT15"));
+		currentProviders.put(new Service("SERVICE6"), new Component("AGENT18"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(7);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE7"), new Component("AGENT19"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(8);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE7"), new Component("AGENT20"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(9);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE7"), new Component("AGENT21"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(10);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE8"), new Component("AGENT22"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(11);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE8"), new Component("AGENT23"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(12);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE8"), new Component("AGENT24"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(13);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE9"), new Component("AGENT25"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(14);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE9"), new Component("AGENT26"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(15);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE9"), new Component("AGENT27"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(16);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE10"), new Component("AGENT28"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(17);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE10"), new Component("AGENT29"));
+		capability.setCurrentProviders(currentProviders);
+
+		agent = providers.get(18);
+		capability = (RemedialCapability) agent.getCapability();
+		currentProviders = new HashMap<Service, Component>();
+		currentProviders.put(new Service("SERVICE10"), new Component("AGENT30"));
+		capability.setCurrentProviders(currentProviders);
+	}
+
+	private void setupDB(RemedialServiceProvider agent) {
+		TraceDAO dao = new TraceDAO(agent.getAID().getLocalName());
+		dao.dropCollection();
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/ChangeServiceProviderGoal.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/ChangeServiceProviderGoal.java
new file mode 100644
index 0000000..610b142
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/ChangeServiceProviderGoal.java
@@ -0,0 +1,46 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.goal;
+
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.goal.Goal;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class ChangeServiceProviderGoal implements Goal {
+
+	private static final long serialVersionUID = -6628531131594379472L;
+
+	private Service service;
+
+	public ChangeServiceProviderGoal(Service service) {
+		this.service = service;
+	}
+
+	public Service getService() {
+		return this.service;
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/MonitorMetricsGoal.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/MonitorMetricsGoal.java
new file mode 100644
index 0000000..6f604e3
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/MonitorMetricsGoal.java
@@ -0,0 +1,35 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.goal;
+
+import bdi4jade.goal.Goal;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class MonitorMetricsGoal implements Goal {
+
+	private static final long serialVersionUID = -2202692821788300986L;
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/ProvideAnomalousProbabilityGoal.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/ProvideAnomalousProbabilityGoal.java
new file mode 100644
index 0000000..156aee4
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/ProvideAnomalousProbabilityGoal.java
@@ -0,0 +1,45 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.goal;
+
+import bdi4jade.goal.Goal;
+import jade.lang.acl.ACLMessage;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class ProvideAnomalousProbabilityGoal implements Goal {
+
+	private static final long serialVersionUID = -3152927909222599238L;
+
+	private ACLMessage msg;
+	
+	public ProvideAnomalousProbabilityGoal(ACLMessage msg) {
+		this.msg = msg;
+	}
+	
+	public ACLMessage getMessage() {
+		return this.msg;
+	}
+ }
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/ProvideServiceGoal.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/ProvideServiceGoal.java
new file mode 100644
index 0000000..ccbcb2a
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/ProvideServiceGoal.java
@@ -0,0 +1,49 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.goal;
+
+import bdi4jade.goal.Goal;
+import jade.lang.acl.ACLMessage;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class ProvideServiceGoal implements Goal {
+
+	private static final long serialVersionUID = -2889889682252478969L;
+
+	private ACLMessage msg;
+	
+	public ProvideServiceGoal(ACLMessage msg) {
+		this.msg = msg;
+	}
+	
+	public ProvideServiceGoal() {
+		this(null);
+	}
+	
+	public ACLMessage getMessage() {
+		return this.msg;
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/RequestServiceGoal.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/RequestServiceGoal.java
new file mode 100644
index 0000000..c876fa9
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/RequestServiceGoal.java
@@ -0,0 +1,61 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.goal;
+
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.goal.Goal;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class RequestServiceGoal implements Goal {
+
+	private static final long serialVersionUID = -8816235981052740771L;
+
+	private Service service;
+	private String parentCid;
+	private Integer cost;
+
+	public RequestServiceGoal(Service service, String parentCid) {
+		this.service = service;
+		this.parentCid = parentCid;
+		this.cost = 0;
+	}
+
+	public Service getService() {
+		return this.service;
+	}
+
+	public String getParentCid() {
+		return this.parentCid;
+	}
+
+	public Integer getCost() {
+		return this.cost;
+	}
+
+	public void setCost(Integer cost) {
+		this.cost = cost;
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/VerifyAbnormalBehaviourGoal.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/VerifyAbnormalBehaviourGoal.java
new file mode 100644
index 0000000..3fc1e87
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/VerifyAbnormalBehaviourGoal.java
@@ -0,0 +1,46 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.goal;
+
+import bdi4jade.goal.Goal;
+import jade.lang.acl.ACLMessage;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class VerifyAbnormalBehaviourGoal implements Goal {
+
+	private static final long serialVersionUID = 6321003065997875304L;
+
+	private ACLMessage msg;
+
+	public VerifyAbnormalBehaviourGoal(ACLMessage msg) {
+		this.msg = msg;
+	}
+
+	public ACLMessage getMsg() {
+		return this.msg;
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/VerifySuspiciousComponentGoal.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/VerifySuspiciousComponentGoal.java
new file mode 100644
index 0000000..1b1c682
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/goal/VerifySuspiciousComponentGoal.java
@@ -0,0 +1,60 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.goal;
+
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Conversation;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.goal.Goal;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class VerifySuspiciousComponentGoal implements Goal {
+
+	private static final long serialVersionUID = -7350855136367882896L;
+
+	private Component component;
+	private Service service;
+	private Conversation conversation;
+
+	public VerifySuspiciousComponentGoal(Component component, Service service, Conversation conversation) {
+		this.component = component;
+		this.service = service;
+		this.conversation = conversation;
+	}
+
+	public Component getComponent() {
+		return this.component;
+	}
+
+	public Service getService() {
+		return this.service;
+	}
+
+	public Conversation getConversation() {
+		return this.conversation;
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/MonitorMetricsCapability.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/MonitorMetricsCapability.java
new file mode 100644
index 0000000..1a22d48
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/MonitorMetricsCapability.java
@@ -0,0 +1,67 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import bdi4jade.annotation.Belief;
+import bdi4jade.core.Capability;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousComponent;
+import bdi4jade.examples.interactionprotocol.goal.MonitorMetricsGoal;
+import bdi4jade.examples.interactionprotocol.plan.MonitorMetricsPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.NotifyAnomalousComponentPlanBody;
+import bdi4jade.goal.GoalTemplateFactory;
+import bdi4jade.plan.DefaultPlan;
+import bdi4jade.plan.Plan;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class MonitorMetricsCapability extends Capability {
+
+	private static final long serialVersionUID = -5800167858824897939L;
+	public static final String SERVICE = "A";
+	public static final String PROVIDER = "AGENT01";
+
+	@Belief
+	private Map<Service, Component> currentProviders;
+
+	@bdi4jade.annotation.Plan
+	private Plan monitorMetricsPlan;
+	@bdi4jade.annotation.Plan
+	private Plan notifyAnomalyPlan;
+
+	public MonitorMetricsCapability() {
+		super();
+		this.currentProviders = new HashMap<Service, Component>();
+		this.currentProviders.put(new Service(SERVICE), new Component(PROVIDER));
+		this.monitorMetricsPlan = new DefaultPlan(MonitorMetricsGoal.class, MonitorMetricsPlanBody.class);
+		this.notifyAnomalyPlan = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfTypeWithValue(AnomalousComponent.class, false),
+				NotifyAnomalousComponentPlanBody.class);
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/CauseEffectKnowledgeModelUpdater.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/CauseEffectKnowledgeModelUpdater.java
new file mode 100644
index 0000000..cebbd04
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/CauseEffectKnowledgeModelUpdater.java
@@ -0,0 +1,45 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import bdi4jade.extension.remediation.RemediationCapability;
+import bdi4jade.extension.remediation.graph.CauseEffectKnowledgeModel;
+import bdi4jade.extension.remediation.graph.TransientCauseEffectRelationship;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public abstract class CauseEffectKnowledgeModelUpdater extends AbstractPlanBody {
+
+	private static final long serialVersionUID = -6556597528124201185L;
+
+	public void updateKnowledgeModel(TransientCauseEffectRelationship tcer) {
+		if (this.getCapability() instanceof RemediationCapability) {
+			RemediationCapability capability = (RemediationCapability) this.getCapability();
+			CauseEffectKnowledgeModel cem = (CauseEffectKnowledgeModel) capability.getBeliefBase().getBelief(CauseEffectKnowledgeModel.NAME);
+			cem.addCauseEffectRelationship(tcer);
+		}
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/ChangeServiceProviderPlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/ChangeServiceProviderPlanBody.java
new file mode 100644
index 0000000..579f991
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/ChangeServiceProviderPlanBody.java
@@ -0,0 +1,105 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.goal.ChangeServiceProviderGoal;
+import bdi4jade.plan.Plan.EndState;
+import jade.domain.FIPAAgentManagement.DFAgentDescription;
+import jade.domain.FIPAAgentManagement.Property;
+import jade.domain.FIPAAgentManagement.ServiceDescription;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class ChangeServiceProviderPlanBody extends YellowPagesPlanBody {
+
+	private static final long serialVersionUID = 7732565620673695278L;
+
+	@bdi4jade.annotation.Belief
+	private Belief<String, Map<Service, Component>> currentProviders;
+	@bdi4jade.annotation.Belief
+	private Belief<String, ArrayList<Component>> unavailableProviders;
+
+	@Override
+	public void action() {
+		ChangeServiceProviderGoal goal = (ChangeServiceProviderGoal) this.getGoal();
+		Service service = goal.getService();
+		System.out.println("[" + this.getAgent().getLocalName() + "] Changing provider of " + service.getId());
+
+		ArrayList<DFAgentDescription> descriptions = getServiceProviders(service);
+
+		Map<Integer, String> map = new HashMap<>();
+		for (DFAgentDescription dfAgentDescription : descriptions) {
+			Integer serviceCost = getServiceCostByAgent(dfAgentDescription, service);
+			map.put(serviceCost, dfAgentDescription.getName().getLocalName());
+		}
+
+		TreeMap<Integer, String> orderedProviders = new TreeMap<Integer, String>(map);
+		boolean flag = true;
+
+		while (flag) {
+			Integer key = orderedProviders.firstKey();
+			Component candidateProvider = new Component(orderedProviders.get(key).toString());
+			if (currentProviders.getValue().containsKey(service)) {
+				Component currentProvider = currentProviders.getValue().get(service);
+				if (currentProvider == null || (!currentProvider.equals(candidateProvider)
+						&& !unavailableProviders.getValue().contains(candidateProvider))) {
+					currentProviders.getValue().put(service, candidateProvider);
+					flag = false;
+				} else {
+					orderedProviders.remove(orderedProviders.firstKey());
+				}
+			}
+		}
+		System.out.println("[" + this.getAgent().getLocalName() + "] " + service.getId() + "'s provider changed.");
+		setEndState(EndState.SUCCESSFUL);
+	}
+
+	private Integer getServiceCostByAgent(DFAgentDescription ad, Service service) {
+		Integer value = Integer.MAX_VALUE;
+		Iterator<?> serviceIterator = ad.getAllServices();
+		while (serviceIterator.hasNext()) {
+			ServiceDescription sd = (ServiceDescription) serviceIterator.next();
+			if (sd.getType().equals(service.getId())) {
+				Iterator<?> propertyIterator = sd.getAllProperties();
+				while (propertyIterator.hasNext()) {
+					Property property = (Property) propertyIterator.next();
+					if (property.getName().equals(Service.COST)) {
+						value = Integer.valueOf((String) property.getValue());
+					}
+				}
+			}
+		}
+		return value;
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/DoNothingPlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/DoNothingPlanBody.java
new file mode 100644
index 0000000..38c98fe
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/DoNothingPlanBody.java
@@ -0,0 +1,47 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import bdi4jade.examples.interactionprotocol.goal.VerifyAbnormalBehaviourGoal;
+import bdi4jade.plan.Plan.EndState;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+import jade.lang.acl.ACLMessage;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class DoNothingPlanBody extends AbstractPlanBody {
+
+	private static final long serialVersionUID = 2126243814362640010L;
+
+	@Override
+	public void action() {
+		VerifyAbnormalBehaviourGoal goal = (VerifyAbnormalBehaviourGoal) this.getGoal();
+		ACLMessage replyMsg = goal.getMsg().createReply();
+		replyMsg.setPerformative(ACLMessage.DISCONFIRM);
+		myAgent.send(replyMsg);
+		setEndState(EndState.SUCCESSFUL);
+	}
+	
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/MonitorMetricsPlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/MonitorMetricsPlanBody.java
new file mode 100644
index 0000000..1c3b8cc
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/MonitorMetricsPlanBody.java
@@ -0,0 +1,113 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import java.time.Duration;
+import java.time.Instant;
+
+import bdi4jade.belief.TransientPredicate;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.examples.interactionprotocol.MonitorMetricsCapability;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Conversation;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousComponent;
+import bdi4jade.goal.PredicateGoal;
+import bdi4jade.plan.Plan.EndState;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+import jade.core.AID;
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class MonitorMetricsPlanBody extends AbstractPlanBody {
+
+	private static final long serialVersionUID = 1240182579625681535L;
+	private static int anomalyCounter = 0;
+
+	private static final int METRIC_VALUE = 250;
+	private boolean sent = false;
+	private boolean dispatched = false;
+	private Instant sentAt;
+	private MessageTemplate mt;
+	private String conversationId;
+
+	@Override
+	public void action() {
+		if (!sent) {
+			ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
+			msg.setContent(MonitorMetricsCapability.SERVICE);
+			msg.addReceiver(new AID(MonitorMetricsCapability.PROVIDER, false));
+
+			this.conversationId = this.myAgent.getLocalName() + System.currentTimeMillis();
+			msg.setConversationId(this.conversationId);
+			myAgent.send(msg);
+			this.sentAt = Instant.now();
+
+			//System.out.println("[" + myAgent.getLocalName() + "] Requesting " + MonitorMetricsCapability.SERVICE + " from " + MonitorMetricsCapability.PROVIDER);
+
+			this.mt = MessageTemplate.MatchConversationId(msg.getConversationId());
+			this.sent = true;
+		} else {
+			if (!dispatched) {
+				ACLMessage reply = myAgent.receive(mt);
+				if (reply != null) {
+					Instant receivedAt = Instant.now();
+					long delta = Duration.between(sentAt, receivedAt).toMillis();
+					System.out.println("Message received after " + delta + "ms.");
+					if (delta > METRIC_VALUE) {
+						MonitorMetricsPlanBody.anomalyCounter++;
+					}
+					
+					if (MonitorMetricsPlanBody.anomalyCounter == 1) {
+						//System.out.println("ANOMALIA DETECTADA!");
+						AnomalousComponent anomalousCompPredicate = new AnomalousComponent(
+								new Component(MonitorMetricsCapability.PROVIDER),
+								new Service(MonitorMetricsCapability.SERVICE), new Conversation(conversationId));
+						TransientPredicate<AnomalousComponent> anomalousCompBelief = new TransientPredicate<AnomalousComponent>(
+								anomalousCompPredicate, true);
+						this.getBeliefBase().addBelief(anomalousCompBelief);
+						dispatchSubgoalAndListen(new PredicateGoal<AnomalousComponent>(anomalousCompPredicate, false));
+						this.dispatched = true;
+					} else {
+						this.sent = false;
+						setEndState(EndState.SUCCESSFUL);
+					}
+				} else {
+					block();
+				}
+			} else {
+				GoalEvent goalEvent = getGoalEvent();
+				if (goalEvent != null) {
+					this.sent = false;
+					MonitorMetricsPlanBody.anomalyCounter = 0;
+					this.dispatched = false;
+					setEndState(EndState.SUCCESSFUL);
+				}
+			}
+		}
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/NormalizeCommunicationPlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/NormalizeCommunicationPlanBody.java
new file mode 100644
index 0000000..e0ca478
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/NormalizeCommunicationPlanBody.java
@@ -0,0 +1,72 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import java.util.ArrayList;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.belief.TransientPredicate;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousCommunication;
+import bdi4jade.examples.interactionprotocol.goal.ChangeServiceProviderGoal;
+import bdi4jade.goal.PredicateGoal;
+import bdi4jade.plan.Plan.EndState;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class NormalizeCommunicationPlanBody extends AbstractPlanBody {
+
+	private static final long serialVersionUID = -7695129957189675038L;
+	private boolean sent = false;
+	
+	@bdi4jade.annotation.Belief
+	private Belief<String, ArrayList<Component>> unavailableProviders;
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void action() {
+		PredicateGoal<AnomalousCommunication> goal = (PredicateGoal<AnomalousCommunication>) this.getGoal();
+		if (!sent) {
+			Service service = goal.getBeliefName().getVariable().getService();
+			Component component = goal.getBeliefName().getVariable().getComponent();
+			unavailableProviders.getValue().add(component);
+			System.out.println("[" + this.getAgent().getLocalName() + "] Normalizing communication for " + service.getId());
+			dispatchSubgoalAndListen(new ChangeServiceProviderGoal(service));
+			this.sent = true;
+		} else {
+			GoalEvent goalEvent = getGoalEvent();
+			if (goalEvent != null) {
+				TransientPredicate<AnomalousCommunication> anomalousCommBelief = (TransientPredicate<AnomalousCommunication>) this
+						.getCapability().getBeliefBase().getBelief(goal.getBeliefName());
+				anomalousCommBelief.setValue(false);
+				this.sent = false;
+				setEndState(EndState.SUCCESSFUL);
+			}
+		}
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/NotifyAnomalousComponentPlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/NotifyAnomalousComponentPlanBody.java
new file mode 100644
index 0000000..0a287a1
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/NotifyAnomalousComponentPlanBody.java
@@ -0,0 +1,105 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.belief.TransientPredicate;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Conversation;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousComponent;
+import bdi4jade.goal.PredicateGoal;
+import bdi4jade.plan.Plan.EndState;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+import jade.core.AID;
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class NotifyAnomalousComponentPlanBody extends AbstractPlanBody {
+
+	private static final long serialVersionUID = 1923017302339086902L;
+	private final Log log = LogFactory.getLog(this.getClass());
+
+	@bdi4jade.annotation.Belief
+	private Belief<String, Map<Service, Component>> currentProviders;
+	@bdi4jade.annotation.Belief
+	private Belief<String, ArrayList<Component>> unavailableProviders;
+
+	private MessageTemplate mt;
+	private boolean sent = false;
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void action() {
+		PredicateGoal<AnomalousComponent> anomalousCompGoal = (PredicateGoal<AnomalousComponent>) this.getGoal();
+		AnomalousComponent anomalousCompPredicate = anomalousCompGoal.getBeliefName();
+		if (!sent) {
+			Component anomalousComponent = anomalousCompPredicate.getVariable1();
+			Conversation anomalousConversation = anomalousCompPredicate.getVariable3();
+
+			ACLMessage msg = new ACLMessage(ACLMessage.INFORM_REF);
+			AID receiver = new AID(anomalousComponent.getId(), false);
+			msg.setContent(anomalousConversation.getId());
+			msg.addReceiver(receiver);
+			msg.setConversationId(this.myAgent.getLocalName() + System.currentTimeMillis());
+			myAgent.send(msg);
+			System.out.println("[" + this.myAgent.getLocalName() + "] Notifying abnormal " + anomalousComponent.getId()
+					+ "[" + msg.getContent() + "]");
+			//log.info(msg.getConversationId() + "\t" + this.myAgent.getLocalName() + "\t" + msg.getPerformative() + "\t" + anomalousComponent.getId() + "\t" + msg.getContent());
+			this.mt = MessageTemplate.and(MessageTemplate.MatchSender(receiver), MessageTemplate.MatchConversationId(msg.getConversationId()));
+			this.sent = true;
+		} else {
+			ACLMessage reply = myAgent.receive(mt);
+			if (reply != null) {
+				TransientPredicate<AnomalousComponent> anomalousCompBelief = (TransientPredicate<AnomalousComponent>) this
+						.getBeliefBase().getBelief(anomalousCompPredicate);
+				anomalousCompBelief.setValue(false);
+				// UNDO
+				this.currentProviders.getValue().replace(anomalousCompPredicate.getVariable2(),
+						anomalousCompPredicate.getVariable1());
+				System.out.println("[" + this.myAgent.getLocalName() + "]" + reply.getSender().getLocalName() + " is not anomalous anymore!");
+				this.sent = false;
+				
+				if (unavailableProviders != null) {
+					if (unavailableProviders.getValue().contains(anomalousCompPredicate.getVariable1())) {
+						unavailableProviders.getValue().remove(anomalousCompPredicate.getVariable1());
+					}
+				}
+				setEndState(EndState.SUCCESSFUL);
+			} else {
+				block();
+			}
+		}
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/ProvideAnomalousProbabilityPlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/ProvideAnomalousProbabilityPlanBody.java
new file mode 100644
index 0000000..b3ce433
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/ProvideAnomalousProbabilityPlanBody.java
@@ -0,0 +1,180 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import bdi4jade.examples.interactionprotocol.Trace;
+import bdi4jade.examples.interactionprotocol.dao.TraceDAO;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.goal.ProvideAnomalousProbabilityGoal;
+import bdi4jade.plan.Plan.EndState;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+import jade.lang.acl.ACLMessage;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class ProvideAnomalousProbabilityPlanBody extends AbstractPlanBody {
+
+	private static final long serialVersionUID = 6587858865136342797L;
+	private final Log log = LogFactory.getLog(this.getClass());
+
+	private String homePath = "src/bdi4jade/examples/interactionprotocol/";
+
+	@Override
+	public void action() {
+		try {
+			ProvideAnomalousProbabilityGoal goal = (ProvideAnomalousProbabilityGoal) this.getGoal();
+			Component provider = new Component(goal.getMessage().getUserDefinedParameter(Component.NAME));
+			Service service = new Service(goal.getMessage().getUserDefinedParameter(Service.NAME));
+
+			ArrayList<Trace> traces = getTracesByProviderAndService(provider, service);
+
+			if (!traces.isEmpty()) {
+				Double probability = computeAnomalousProbability(traces);
+				System.out.println("[" + this.getAgent().getLocalName() + "] Providing anomaly probability " + probability + " for "
+						+ provider.getId() + "[" + service.getId() + "]");
+				sendReply(goal.getMessage(), probability);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		setEndState(EndState.SUCCESSFUL);
+
+	}
+
+	private void sendReply(ACLMessage msg, Double probability) {
+		ACLMessage reply = msg.createReply();
+		reply.setContent(String.valueOf(probability));
+		reply.setPerformative(ACLMessage.CONFIRM);
+		//log.info(reply.getConversationId() + "\t" + myAgent.getLocalName() + "\t" + reply.getPerformative() + "\t - \t" + reply.getContent());
+		this.getAgent().send(reply);
+	}
+
+	private Double computeAnomalousProbability(ArrayList<Trace> traces) {
+		long currentTime = System.currentTimeMillis();
+		ArrayList<Double> values = new ArrayList<>();
+		ArrayList<Double> rawWeights = new ArrayList<>();
+
+		for (Trace trace : traces) {
+			values.add((double)trace.getReceivedAt() - trace.getSentAt());
+			rawWeights.add((double)currentTime - trace.getReceivedAt());
+		}
+		ArrayList<Double> weights = computeWeights(rawWeights);
+
+		File inputFile = new File(homePath + this.myAgent.getLocalName() + "_in.txt");
+		File outputFile = new File(homePath + this.myAgent.getLocalName() + "_out.txt");
+		try {
+			inputFile.createNewFile();
+			outputFile.createNewFile();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+
+		populateInputFile(inputFile, values, weights);
+		callRScript(inputFile, outputFile);
+		String output = readOutputFile(outputFile);
+		inputFile.delete();
+		outputFile.delete();
+		Double val = Double.valueOf(output);
+		Double probability = 1 - (val > 1 ? 1 : val); 
+
+		return probability;
+	}
+
+	private void populateInputFile(File inputFile, ArrayList<Double> values, ArrayList<Double> weights) {
+		Charset utf8 = StandardCharsets.UTF_8;
+		List<String> lines = new ArrayList<>();
+		lines.add("time\tweights");
+		for (int i = 0; i < values.size(); i++) {
+			lines.add(values.get(i).toString() + "\t" + weights.get(i).toString());
+		}
+		try {
+			Files.write(Paths.get(inputFile.getAbsolutePath()), lines, utf8);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	private String readOutputFile(File outputFile) {
+		List<String> lines = new ArrayList<String>();
+		try {
+			lines = Files.readAllLines(Paths.get(outputFile.getAbsolutePath()));
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		if (!lines.isEmpty()) {
+			return lines.get(0);
+		}
+		return "1";
+	}
+
+	private void callRScript(File inputFile, File outputFile) {
+		File scriptFile = new File(homePath + "script.r");
+		String command = "Rscript " + scriptFile.getAbsolutePath() + " " + inputFile.getAbsolutePath() + " "
+				+ outputFile.getAbsolutePath();
+		try {
+			Runtime.getRuntime().exec(command);
+			Thread.sleep(1000);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	private ArrayList<Double> computeWeights(ArrayList<Double> rawWeights) {
+		Double minWeight = rawWeights.get(rawWeights.size() - 1);
+		ArrayList<Double> normalizedWeights = new ArrayList<Double>();
+		Double sum = 0.0;
+		for (Double weight : rawWeights) {
+			Double normalizedWeight = minWeight / weight;
+			sum += normalizedWeight;
+			normalizedWeights.add(normalizedWeight);
+		}
+		Double multiplier = 1.0 / sum;
+		ArrayList<Double> weights = new ArrayList<Double>();
+		for (Double normalizedWeight : normalizedWeights) {
+			weights.add(normalizedWeight * multiplier);
+		}
+		return weights;
+	}
+
+	private ArrayList<Trace> getTracesByProviderAndService(Component component, Service service) {
+		TraceDAO dao = new TraceDAO(getAgent().getLocalName());
+		ArrayList<Trace> traces = dao.getTracesByServiceAndProvider(service.getId(), component.getId());
+		return traces;
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/ProvideServicePlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/ProvideServicePlanBody.java
new file mode 100644
index 0000000..6d708c0
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/ProvideServicePlanBody.java
@@ -0,0 +1,142 @@
+//----------------------------------------------------------------------------
+
+// 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.examples.interactionprotocol.plan;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Link;
+import bdi4jade.examples.interactionprotocol.domain.LinkMonitor;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.goal.ProvideServiceGoal;
+import bdi4jade.examples.interactionprotocol.goal.RequestServiceGoal;
+import bdi4jade.plan.Plan.EndState;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+import jade.lang.acl.ACLMessage;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class ProvideServicePlanBody extends AbstractPlanBody {
+
+	private static final long serialVersionUID = -7820028025514943596L;
+	public static final String SUCCEEDED = "SUCCEEDED";
+	private final Log log = LogFactory.getLog(this.getClass());
+
+	@bdi4jade.annotation.Belief
+	private Belief<String, Map<Service, ArrayList<Service>>> myServices;
+	@bdi4jade.annotation.Belief
+	private Belief<String, Boolean> failure;
+	@bdi4jade.annotation.Belief
+	private Belief<String, Map<Service, Integer>> serviceCost;
+
+	private boolean sent = false;
+	private int counter;
+	private Instant startedAt;
+	private int cummulatedCost;
+
+	public ProvideServicePlanBody() {
+		this.counter = 0;
+		this.startedAt = Instant.now();
+		this.cummulatedCost = 0;
+	}
+	
+	@Override
+	public void action() {
+		ProvideServiceGoal goal = (ProvideServiceGoal) this.getGoal();
+		ACLMessage requestMsg = goal.getMessage();
+		Service service = new Service(requestMsg.getContent());
+		ArrayList<Service> subServices = myServices.getValue().get(service);
+		String parentCid = requestMsg.getConversationId();
+
+		if (!subServices.isEmpty()) {
+			if (!sent) {
+
+				for (Service subService : subServices) {
+					RequestServiceGoal subgoal = new RequestServiceGoal(subService, parentCid);
+					dispatchSubgoalAndListen(subgoal);
+				}
+				this.sent = true;
+			} else {
+				GoalEvent goalEvent = getGoalEvent();
+				if (goalEvent != null) {
+					if (goalEvent.getGoal() instanceof RequestServiceGoal) {
+						RequestServiceGoal subgoal = (RequestServiceGoal) goalEvent.getGoal();
+						this.cummulatedCost += subgoal.getCost();
+					}
+					
+					counter++;
+					if (counter == subServices.size()) {
+						this.sent = false;
+						simulateProcessingTime(requestMsg);
+						replyRequest(requestMsg, service);
+					}
+				}
+			}
+		} else {
+			simulateProcessingTime(requestMsg);
+			replyRequest(requestMsg, service);
+		}
+	}
+
+	private void replyRequest(ACLMessage requestMsg, Service service) {
+		ACLMessage replyRequest = requestMsg.createReply();
+		Integer cost = serviceCost.getValue().get(service);
+		replyRequest.setContent(cost.toString());
+		replyRequest.setPerformative(ACLMessage.CONFIRM);
+
+		Instant finishedAt = Instant.now();
+		long delta = Duration.between(startedAt, finishedAt).toMillis();
+		log.info(requestMsg.getConversationId() + "\t" + myAgent.getLocalName() + "\t"
+				+ requestMsg.getSender().getLocalName() + "\t" + requestMsg.getContent() + "\t" + this.cummulatedCost + "\t" + delta);
+		
+		myAgent.send(replyRequest);
+		setEndState(EndState.SUCCESSFUL);
+	}
+
+	private void simulateProcessingTime(ACLMessage msg) {
+		try {
+			Thread.sleep(10);
+			Link link = new Link(new Component(this.getAgent().getLocalName()),
+					new Component(msg.getSender().getLocalName()), new Service(msg.getContent()));
+			if (failure.getValue()) {
+				Thread.sleep(250);
+			}
+			if (LinkMonitor.getInstance().getAnomalousLinks().contains(link)) {
+				Thread.sleep(250);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/RepairLinkPlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/RepairLinkPlanBody.java
new file mode 100644
index 0000000..937f0a6
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/RepairLinkPlanBody.java
@@ -0,0 +1,74 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.belief.TransientPredicate;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.LinkMonitor;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousLink;
+import bdi4jade.goal.PredicateGoal;
+import bdi4jade.plan.Plan.EndState;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class RepairLinkPlanBody extends AbstractPlanBody {
+
+	private static final long serialVersionUID = 7705669736518583815L;
+	
+	@bdi4jade.annotation.Belief
+	private Belief<String, Map<Service, Component>> currentProviders;
+	@bdi4jade.annotation.Belief
+	private Belief<String, ArrayList<Component>> unavailableProviders;
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void action() {
+		if (this.getGoal() instanceof PredicateGoal<?>) {
+			PredicateGoal<AnomalousLink> goal = (PredicateGoal<AnomalousLink>) this.getGoal();
+			TransientPredicate<AnomalousLink> belief = (TransientPredicate<AnomalousLink>) this.getCapability()
+					.getBeliefBase().getBelief(goal.getBeliefName());
+			if (belief != null) {
+				System.out.println("[" + this.getAgent().getLocalName() + "] Repairing link " + belief.getName().getVariable());
+				belief.setValue(false);
+				// Remove from link monitor
+				LinkMonitor.getInstance().getAnomalousLinks().remove(belief.getName().getVariable());
+				// UNDO
+				this.currentProviders.getValue().replace(belief.getName().getVariable().getService(),
+						belief.getName().getVariable().getTo());
+				if (unavailableProviders.getValue().contains(goal.getBeliefName().getVariable().getTo())) {
+					unavailableProviders.getValue().remove(goal.getBeliefName().getVariable().getTo());
+				}
+				setEndState(EndState.SUCCESSFUL);
+			}
+		}
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/RequestServicePlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/RequestServicePlanBody.java
new file mode 100644
index 0000000..0e36290
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/RequestServicePlanBody.java
@@ -0,0 +1,118 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import java.time.Instant;
+import java.util.Map;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.examples.interactionprotocol.Trace;
+import bdi4jade.examples.interactionprotocol.dao.TraceDAO;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.goal.RequestServiceGoal;
+import bdi4jade.plan.Plan.EndState;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+import jade.core.AID;
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class RequestServicePlanBody extends AbstractPlanBody {
+
+	private static final long serialVersionUID = 59990651870691366L;
+	//private final Log log = LogFactory.getLog(this.getClass());
+
+	@bdi4jade.annotation.Belief
+	private Belief<String, Map<Service, Component>> currentProviders;
+
+	private boolean sent;
+	private MessageTemplate mt;
+	private Instant sentAt;
+
+	@Override
+	public void action() {
+		RequestServiceGoal goal = (RequestServiceGoal) this.getGoal();
+		Service service = goal.getService();
+		if (!sent) {
+			String parentCid = goal.getParentCid();
+
+			ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
+			msg.setContent(service.getId());
+
+			Component provider = currentProviders.getValue().get(service);
+			msg.addReceiver(new AID(provider.getId(), false));
+			msg.setConversationId(this.myAgent.getLocalName() + System.currentTimeMillis());
+
+			myAgent.send(msg);
+
+			setTrace(msg, provider.getId(), parentCid);
+			this.mt = MessageTemplate.and(MessageTemplate.MatchConversationId(msg.getConversationId()), MessageTemplate.MatchPerformative(ACLMessage.CONFIRM));
+			this.sent = true;
+		} else {
+			ACLMessage reply = myAgent.receive(mt);
+			if (reply != null) {
+				goal.setCost(Integer.valueOf(reply.getContent()));
+				updateTrace(reply);
+				this.sent = false;
+				setEndState(EndState.SUCCESSFUL);
+			} else {
+				block();
+			}
+		}
+	}
+
+	public void setTrace(ACLMessage msg, String receiver, String parentCid) {
+		Trace trace = new Trace(msg.getSender().getLocalName(), receiver, msg.getContent(), msg.getConversationId(),
+				parentCid);
+		this.sentAt = Instant.now();
+		trace.setSentAt(this.sentAt.toEpochMilli());
+
+		TraceDAO dao = new TraceDAO(this.getAgent().getAID().getLocalName());
+		dao.addTrace(trace);
+	}
+
+	public void updateTrace(ACLMessage msg) {
+		Instant receivedAt = Instant.now();
+		//long delta = Duration.between(this.sentAt, receivedAt).toMillis();
+		//log.info("REQUEST\t" + msg.getConversationId() + "\t" + myAgent.getLocalName() + "\t" + msg.getSender().getLocalName() + "\t" + msg.getContent() + "\t" + delta);
+
+		Trace trace = new Trace(this.getAgent().getLocalName(), msg.getSender().getLocalName(), null,
+				msg.getConversationId());
+		trace.setReceivedAt(receivedAt.toEpochMilli());
+		trace.setValue(msg.getContent());
+
+		TraceDAO dao = new TraceDAO(this.getAgent().getAID().getLocalName());
+		dao.updateTrace(trace);
+	}
+
+	@Override
+	public void onStart() {
+		super.onStart();
+		this.sent = false;
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/SelfHealingPlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/SelfHealingPlanBody.java
new file mode 100644
index 0000000..54d09e4
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/SelfHealingPlanBody.java
@@ -0,0 +1,61 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.belief.TransientBelief;
+import bdi4jade.examples.interactionprotocol.domain.predicate.Abnormal;
+import bdi4jade.goal.PredicateGoal;
+import bdi4jade.plan.Plan.EndState;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class SelfHealingPlanBody extends AbstractPlanBody {
+
+	private static final long serialVersionUID = 4186257510692528626L;
+	
+	@bdi4jade.annotation.Belief
+	private Belief<String, Boolean> failure;
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void action() {
+		System.out.println("[" + this.getAgent().getLocalName() + "] Starting SELF-HEALING action...");
+		PredicateGoal<Abnormal> goal = (PredicateGoal<Abnormal>) this.getGoal();
+		TransientBelief<Abnormal, Boolean> abnormalBehaviourBelief = (TransientBelief<Abnormal, Boolean>) this.getBeliefBase()
+				.getBelief(goal.getBeliefName());
+		if (abnormalBehaviourBelief == null) {
+			abnormalBehaviourBelief = new TransientBelief<Abnormal, Boolean>(goal.getBeliefName(), false);
+			this.getBeliefBase().addBelief(abnormalBehaviourBelief);
+		} else {
+			abnormalBehaviourBelief.setValue(false);
+		}
+		failure.setValue(false);
+		System.out.println("[" + this.getAgent().getLocalName() + "] SELF-HEALING DONE!");
+		setEndState(EndState.SUCCESSFUL);
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/VerifyInternalOrExternalCausePlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/VerifyInternalOrExternalCausePlanBody.java
new file mode 100644
index 0000000..49efe76
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/VerifyInternalOrExternalCausePlanBody.java
@@ -0,0 +1,258 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+
+import bdi4jade.belief.TransientPredicate;
+import bdi4jade.event.GoalEvent;
+import bdi4jade.examples.interactionprotocol.Trace;
+import bdi4jade.examples.interactionprotocol.dao.TraceDAO;
+import bdi4jade.examples.interactionprotocol.domain.Communication;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Conversation;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.domain.predicate.Abnormal;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousCommunication;
+import bdi4jade.examples.interactionprotocol.goal.VerifyAbnormalBehaviourGoal;
+import bdi4jade.examples.interactionprotocol.goal.VerifySuspiciousComponentGoal;
+import bdi4jade.extension.remediation.graph.TransientCauseEffectRelationship;
+import bdi4jade.extension.remediation.logics.Fact;
+import bdi4jade.goal.PredicateGoal;
+import bdi4jade.plan.Plan.EndState;
+import jade.lang.acl.ACLMessage;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class VerifyInternalOrExternalCausePlanBody extends CauseEffectKnowledgeModelUpdater {
+
+	private static final long serialVersionUID = 8287156375478059409L;
+
+	private boolean sent = false;
+	private int counter = 0;
+	HashMap<String, HashSet<String>> suspiciousComponents;
+
+	public VerifyInternalOrExternalCausePlanBody() {
+		super();
+		this.suspiciousComponents = new HashMap<String, HashSet<String>>();
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public void action() {
+		VerifyAbnormalBehaviourGoal goal = (VerifyAbnormalBehaviourGoal) this.getGoal();
+		if (!sent) {
+			Conversation abnormalConversation = new Conversation(goal.getMsg().getContent());
+			Abnormal abnormalBehaviour = new Abnormal(abnormalConversation);
+
+			HashSet<String> serviceProviders = getServiceProviders(abnormalConversation.getId());
+
+			System.out.println("[" + this.myAgent.getLocalName() + "] Verifying internal or external cause...");
+			for (String provider : serviceProviders) {
+				HashSet<String> anomalousServices = new HashSet<String>();
+				HashSet<String> providedServices = getProvidedServices(abnormalConversation.getId(), provider);
+				for (String service : providedServices) {
+					System.out.println("\t[" + this.myAgent.getLocalName() + "] Buscando dados sobre " + service + " e " + provider);
+					ArrayList<Long> data = getFilteredData(service, provider, abnormalConversation.getId());
+					Long lastMeasurement = data.remove(data.size() - 1);
+					Collections.sort(data);
+					if (isAnomalous(data, lastMeasurement)) {
+						anomalousServices.add(service);
+					}
+				}
+				if (!anomalousServices.isEmpty()) {
+					suspiciousComponents.put(provider, anomalousServices);
+				}
+			}
+
+			if (suspiciousComponents.isEmpty()) {
+				System.out.println(
+						"[" + this.getAgent().getLocalName() + "] Dispatching <PredicateGoal[Abnormal], false>");
+				dispatchSubgoalAndListen(new PredicateGoal<Abnormal>(abnormalBehaviour, false));
+			} else {
+				for (String provider : suspiciousComponents.keySet()) {
+					HashSet<String> anomalousServices = suspiciousComponents.get(provider);
+					for (String service : anomalousServices) {
+						String childCid = getChildCid(abnormalConversation.getId(), provider, service);
+
+						AnomalousCommunication anomalousCommPredicate = new AnomalousCommunication(
+								new Communication(new Component(provider), new Service(service)));
+
+						TransientPredicate<AnomalousCommunication> anomalousCommBelief = (TransientPredicate<AnomalousCommunication>) this
+								.getBeliefBase().getBelief(anomalousCommPredicate);
+						if (anomalousCommBelief != null) {
+							anomalousCommBelief.setValue(true);
+						} else {
+							anomalousCommBelief = new TransientPredicate<AnomalousCommunication>(anomalousCommPredicate,
+									true);
+							this.getBeliefBase().addBelief(anomalousCommBelief);
+						}
+
+						// Create Cause Effect Relationship
+						TransientCauseEffectRelationship tcer = new TransientCauseEffectRelationship(
+								new Fact(anomalousCommPredicate, true));
+						updateKnowledgeModel(tcer);
+
+						// Create goals
+						// !¬Anomalous(Communication)
+						System.out.println("[" + this.getAgent().getLocalName()
+								+ "] Dispatching <PredicateGoal[AnomalousCommunication], false>");
+						dispatchSubgoalAndListen(
+								new PredicateGoal<AnomalousCommunication>(anomalousCommPredicate, false));
+						// **?Anomalous(Component)** virou VerifySuspiciousComponentGoal
+						System.out.println(
+								"[" + this.getAgent().getLocalName() + "] Dispatching <VerifySuspiciousComponent>");
+						dispatchGoal(new VerifySuspiciousComponentGoal(new Component(provider), new Service(service),
+								new Conversation(childCid)));
+
+						this.counter++;
+					}
+				}
+			}
+			this.sent = true;
+		} else {
+			GoalEvent goalEvent = getGoalEvent();
+			if (goalEvent != null) {
+				this.counter--;
+				if (this.counter <= 0) {
+					this.sent = false;
+					replyNotifier(goal.getMsg());
+				}
+			}
+		}
+	}
+
+	private void replyNotifier(ACLMessage msg) {
+		ACLMessage replyMsg = msg.createReply();
+		replyMsg.setPerformative(ACLMessage.DISCONFIRM);
+		myAgent.send(replyMsg);
+		setEndState(EndState.SUCCESSFUL);
+	}
+
+	private boolean isAnomalous(ArrayList<Long> data, Long value) {
+		if (data.isEmpty()) {
+			return false;
+		}
+		
+		int medianIndex = 0;
+
+		// reset basic stats
+		Double lowerQuartile = 0.0;
+		Double upperQuartile = 0.0;
+		Long median = 0L;
+		Double lowerBound = 0.0;
+		Double upperBound = 0.0;
+
+		// the boolean determining whether there are an even number of elements
+		Boolean evenm = false;
+
+		// set the quartile positions
+		if ((data.size() % 2) == 0) {
+			medianIndex = (int) Math.floor(data.size() / 2);
+			evenm = true;
+		} else {
+			medianIndex = (data.size() + 1) / 2;
+			medianIndex = medianIndex - 1;
+		}
+
+		// get the median position
+		if (medianIndex > 0) {
+			// lower quartile
+			lowerQuartile += (data.get((int) Math.floor(medianIndex / 2)) + data.get((int) Math
+					.ceil(medianIndex / 2))) / 2;
+
+			if (evenm == false) {
+				// median of an odd set
+				median = data.get(medianIndex);
+			} else if (evenm == true) {
+				// median of an even set
+				median += (data.get(medianIndex) + data.get(medianIndex + 1)) / 2;
+			}
+
+			// upper quartile
+			upperQuartile += (data.get(((int) (medianIndex + Math.ceil(medianIndex / 2)))) + data
+					.get(((int) (medianIndex + Math.floor(medianIndex / 2))))) / 2;
+
+			upperBound = median + ((upperQuartile - lowerQuartile) * 1.5);
+			lowerBound = median - ((upperQuartile - lowerQuartile) * 1.5);
+		}
+		System.out.println("\t\tUpperBound: " + upperBound + " LowerBound: " + lowerBound + "Value: " + value);
+		
+		//return value < lowerBound || value > upperBound;
+		return value > upperBound;
+	}
+
+	private HashSet<String> getProvidedServices(String parentCid, String provider) {
+		TraceDAO dao = new TraceDAO(this.getAgent().getLocalName());
+		ArrayList<Trace> traces = dao.getTracesByParentCIDAndProvider(parentCid, provider);
+
+		HashSet<String> services = new HashSet<String>();
+
+		for (Trace trace : traces) {
+			services.add(trace.getService());
+		}
+		return services;
+	}
+
+	private HashSet<String> getServiceProviders(String parentCid) {
+		TraceDAO dao = new TraceDAO(this.getAgent().getLocalName());
+		ArrayList<Trace> traces = dao.getTracesByParentCID(parentCid);
+
+		HashSet<String> providers = new HashSet<String>();
+
+		for (Trace trace : traces) {
+			providers.add(trace.getReceiver());
+		}
+		return providers;
+	}
+
+	private String getChildCid(String parentCid, String provider, String service) {
+		TraceDAO dao = new TraceDAO(this.getAgent().getLocalName());
+		String childCid = dao.getCIDByParentCIDAndProviderAndService(parentCid, provider, service);
+		return childCid;
+	}
+
+	// Later I need to add the quality feature as a parameter.
+	private ArrayList<Long> getFilteredData(String service, String provider, String parentCid) {
+		TraceDAO dao = new TraceDAO(this.getAgent().getLocalName());
+		ArrayList<Trace> traces = dao.getTracesOfProvidedByBefore(service, provider, parentCid);
+
+		ArrayList<Long> data = new ArrayList<Long>();
+
+		for (Trace trace : traces) {
+			Long receivedAt = trace.getReceivedAt();
+			Long sentAt = trace.getSentAt();
+			if (receivedAt != null) {
+				Long measurement = receivedAt - sentAt;
+				data.add(measurement);
+			}
+		}
+		return data;
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/VerifySuspiciousComponentPlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/VerifySuspiciousComponentPlanBody.java
new file mode 100644
index 0000000..40e32ee
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/VerifySuspiciousComponentPlanBody.java
@@ -0,0 +1,176 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import bdi4jade.belief.Belief;
+import bdi4jade.belief.TransientPredicate;
+import bdi4jade.examples.interactionprotocol.domain.Communication;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Link;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousCommunication;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousComponent;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousLink;
+import bdi4jade.examples.interactionprotocol.goal.VerifySuspiciousComponentGoal;
+import bdi4jade.extension.remediation.goal.CauseEffectProblem;
+import bdi4jade.extension.remediation.goal.CauseFactorStatus;
+import bdi4jade.extension.remediation.logics.Fact;
+import bdi4jade.extension.remediation.reasoning.RemediationOptionGenerationFunction;
+import bdi4jade.goal.Goal;
+import bdi4jade.goal.PredicateGoal;
+import bdi4jade.plan.Plan.EndState;
+import jade.core.AID;
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class VerifySuspiciousComponentPlanBody extends CauseEffectKnowledgeModelUpdater {
+
+	private static final long serialVersionUID = -1636092292876808685L;
+	private final Log log = LogFactory.getLog(this.getClass());
+
+	private final int MAX_TIME = 5000;
+	private final double ANOMALY_THRESHOLD = 0.5;
+
+	@bdi4jade.annotation.Belief
+	private Belief<String, Map<String, Integer>> knownAgents;
+
+	private MessageTemplate mt;
+	private HashMap<String, Double> probabilities;
+	private boolean sent = false;
+	private long startedAt;
+
+	@Override
+	public void action() {
+		VerifySuspiciousComponentGoal goal = (VerifySuspiciousComponentGoal) this.getGoal();
+		if (!sent) {
+			System.out.println("[" + this.getAgent().getLocalName() + "] Verifying suspicious "
+					+ goal.getService().getId() + " from " + goal.getComponent().getId());
+			this.probabilities = new HashMap<String, Double>();
+
+			ACLMessage msg = new ACLMessage(ACLMessage.QUERY_IF);
+			msg.addUserDefinedParameter(Service.NAME, goal.getService().getId());
+			msg.addUserDefinedParameter(Component.NAME, goal.getComponent().getId());
+
+			for (String neighbourLocalName : knownAgents.getValue().keySet()) {
+				msg.addReceiver(new AID(neighbourLocalName, false));
+			}
+			msg.setConversationId(this.myAgent.getLocalName() + System.currentTimeMillis());
+			//log.info(msg.getConversationId() + "\t" + myAgent.getLocalName() + "\t" + msg.getPerformative() + "\tKNOWNAGENTS\t" + msg.getContent());
+			myAgent.send(msg);
+
+			this.startedAt = System.currentTimeMillis();
+			this.mt = MessageTemplate.and(MessageTemplate.MatchPerformative(ACLMessage.CONFIRM), MessageTemplate.MatchConversationId(msg.getConversationId()));
+			this.sent = true;
+		} else {
+			if (System.currentTimeMillis() - this.startedAt < this.MAX_TIME) {
+				ACLMessage reply = myAgent.receive(mt);
+				if (reply != null) {
+					String sender = reply.getSender().getLocalName();
+					Double probability = Double.valueOf(reply.getContent());
+					if (!this.probabilities.containsKey(sender)) {
+						this.probabilities.put(sender, probability);
+					}
+				} else {
+					block();
+				}
+			} else {
+				Double anomalyReputation = getAnomalyReputation(this.probabilities);
+				System.out.println(
+						"\t[" + this.getAgent().getLocalName() + "] ANOMALY REPUTATION OBTAINED: " + anomalyReputation);
+
+				AnomalousCommunication anomalousCommPredicate = new AnomalousCommunication(
+						new Communication(goal.getComponent(), goal.getService()));
+				PredicateGoal<AnomalousCommunication> effect = new PredicateGoal<AnomalousCommunication>(
+						anomalousCommPredicate, false);
+
+				if (anomalyReputation > ANOMALY_THRESHOLD) { // Update CEP with AnomalousComponent
+					AnomalousComponent anomalousCompPredicate = new AnomalousComponent(goal.getComponent(),
+							goal.getService(), goal.getConversation());
+					updateCauseEffectProblem(effect, new Fact(anomalousCompPredicate, true));
+
+					TransientPredicate<AnomalousComponent> anomalousCompBelief = new TransientPredicate<AnomalousComponent>(
+							anomalousCompPredicate, true);
+					this.getBeliefBase().addBelief(anomalousCompBelief);
+				} else { // Update CEP with AnomalousLink
+					AnomalousLink anomalousLinkPredicate = new AnomalousLink(new Link(
+							new Component(this.getAgent().getLocalName()), goal.getComponent(), goal.getService()));
+					updateCauseEffectProblem(effect, new Fact(anomalousLinkPredicate, true));
+
+					TransientPredicate<AnomalousLink> anomalousLinkBelief = (TransientPredicate<AnomalousLink>) this
+							.getBeliefBase().getBelief(anomalousLinkPredicate);
+					if (anomalousLinkBelief != null) {
+						anomalousLinkBelief.setValue(true);
+					} else {
+						anomalousLinkBelief = new TransientPredicate<AnomalousLink>(anomalousLinkPredicate, true);
+						this.getBeliefBase().addBelief(anomalousLinkBelief);
+					}
+				}
+
+				setEndState(EndState.SUCCESSFUL);
+				this.sent = false;
+			}
+		}
+	}
+
+	private Double getAnomalyReputation(HashMap<String, Double> probabilities) {
+		Integer similarities = 0;
+		Double weightedProbabilities = 0.0;
+
+		for (String agentName : probabilities.keySet()) {
+			Integer similarity = knownAgents.getValue().get(agentName);
+			similarities += similarity;
+
+			Double weightedProbability = probabilities.get(agentName) * similarity;
+			weightedProbabilities += weightedProbability;
+		}
+		Double anomalyReputation = weightedProbabilities / similarities;
+		return anomalyReputation;
+	}
+
+	private void updateCauseEffectProblem(Goal effect, Fact optionalCause) {
+		if (this.getCapability().getOptionGenerationFunction() instanceof RemediationOptionGenerationFunction) {
+			Map<Goal, CauseEffectProblem> ceps = ((RemediationOptionGenerationFunction) this.getCapability()
+					.getOptionGenerationFunction()).getCauseEffectProblems();
+
+			CauseEffectProblem cep = ceps.get(effect);
+			if (cep != null) {
+				cep.getCauseEffectRelationship().addOptionalCause(optionalCause);
+				Set<CauseFactorStatus> set = new HashSet<CauseFactorStatus>();
+				set.add(new CauseFactorStatus(optionalCause));
+				cep.setCauseFactorStatus(set);
+			}
+		}
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/YellowPagesPlanBody.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/YellowPagesPlanBody.java
new file mode 100644
index 0000000..09670c9
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/plan/YellowPagesPlanBody.java
@@ -0,0 +1,64 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.plan;
+
+import java.util.ArrayList;
+
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.plan.planbody.AbstractPlanBody;
+import jade.domain.DFService;
+import jade.domain.FIPAException;
+import jade.domain.FIPAAgentManagement.DFAgentDescription;
+import jade.domain.FIPAAgentManagement.ServiceDescription;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public abstract class YellowPagesPlanBody extends AbstractPlanBody {
+
+	private static final long serialVersionUID = 6856724391696865379L;
+
+	protected ArrayList<DFAgentDescription> getServiceProviders(Service service) {
+
+		ArrayList<DFAgentDescription> descriptions = new ArrayList<DFAgentDescription>();
+		DFAgentDescription[] dfAgentDescriptions = new DFAgentDescription[0];
+
+		try {
+			DFAgentDescription agentDescription = new DFAgentDescription();
+			ServiceDescription serviceDescription = new ServiceDescription();
+			serviceDescription.setType(service.getId());
+			serviceDescription.setName(service.getId());
+			agentDescription.addServices(serviceDescription);
+
+			dfAgentDescriptions = DFService.search(this.myAgent, agentDescription);
+
+			for (DFAgentDescription dfAgentDescription : dfAgentDescriptions) {
+				descriptions.add(dfAgentDescription);
+			}
+		} catch (FIPAException fe) {
+			System.err.println("DFService: Error while requesting the DFService!");
+		}
+		return descriptions;
+	}	
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/remedial/RemedialCapability.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/remedial/RemedialCapability.java
new file mode 100644
index 0000000..c661205
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/remedial/RemedialCapability.java
@@ -0,0 +1,157 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.remedial;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import bdi4jade.annotation.Belief;
+import bdi4jade.core.Capability;
+import bdi4jade.examples.interactionprotocol.domain.Component;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import bdi4jade.examples.interactionprotocol.domain.predicate.Abnormal;
+import bdi4jade.examples.interactionprotocol.domain.predicate.AnomalousCommunication;
+import bdi4jade.examples.interactionprotocol.goal.ChangeServiceProviderGoal;
+import bdi4jade.examples.interactionprotocol.goal.ProvideServiceGoal;
+import bdi4jade.examples.interactionprotocol.goal.RequestServiceGoal;
+import bdi4jade.examples.interactionprotocol.goal.VerifyAbnormalBehaviourGoal;
+import bdi4jade.examples.interactionprotocol.plan.ChangeServiceProviderPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.NormalizeCommunicationPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.ProvideServicePlanBody;
+import bdi4jade.examples.interactionprotocol.plan.RequestServicePlanBody;
+import bdi4jade.examples.interactionprotocol.plan.SelfHealingPlanBody;
+import bdi4jade.examples.interactionprotocol.plan.VerifyInternalOrExternalCausePlanBody;
+import bdi4jade.goal.GoalTemplateFactory;
+import bdi4jade.plan.DefaultPlan;
+import bdi4jade.plan.Plan;
+import bdi4jade.reasoning.DefaultBeliefRevisionStrategy;
+import jade.lang.acl.ACLMessage;
+import jade.lang.acl.MessageTemplate;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class RemedialCapability extends Capability {
+
+	private static final long serialVersionUID = -2145767656215646224L;
+
+	// Beliefs
+	@Belief
+	private Map<Service, ArrayList<Service>> myServices;
+	@Belief
+	private Map<Service, Integer> serviceCost;
+	@Belief
+	private Map<Service, Component> currentProviders;
+	@Belief
+	private ArrayList<Component> unavailableProviders;
+	@Belief
+	private Boolean failure;
+
+	@bdi4jade.annotation.Plan
+	private Plan verifyInternalOrExternalCausePlan;
+	@bdi4jade.annotation.Plan
+	private Plan selfHealingPlan;
+	@bdi4jade.annotation.Plan
+	private Plan normalizeCommunicationPlan;
+	@bdi4jade.annotation.Plan
+	private Plan changeServiceProviderPlan;
+	@bdi4jade.annotation.Plan
+	private Plan provideServicePlan;
+	@bdi4jade.annotation.Plan
+	private Plan requestServicePlan;
+
+	public RemedialCapability(Map<Service, ArrayList<Service>> myServices) {
+		this.myServices = myServices;
+		this.serviceCost = new HashMap<Service, Integer>();
+		this.unavailableProviders = new ArrayList<>();
+		this.failure = false;
+		this.currentProviders = new HashMap<Service, Component>();
+
+		this.verifyInternalOrExternalCausePlan = new DefaultPlan(VerifyAbnormalBehaviourGoal.class,
+				VerifyInternalOrExternalCausePlanBody.class);
+		this.selfHealingPlan = new DefaultPlan(GoalTemplateFactory.hasBeliefOfTypeWithValue(Abnormal.class, false),
+				SelfHealingPlanBody.class);
+		this.normalizeCommunicationPlan = new DefaultPlan(
+				GoalTemplateFactory.hasBeliefOfTypeWithValue(AnomalousCommunication.class, false),
+				NormalizeCommunicationPlanBody.class);
+		this.changeServiceProviderPlan = new DefaultPlan(ChangeServiceProviderGoal.class,
+				ChangeServiceProviderPlanBody.class);
+		this.provideServicePlan = new DefaultPlan(ProvideServiceGoal.class, ProvideServicePlanBody.class);
+		this.requestServicePlan = new DefaultPlan(GoalTemplateFactory.goalOfType(RequestServiceGoal.class),
+				RequestServicePlanBody.class);
+
+		setBeliefRevisionStrategy(new RemedialBeliefRevisionStrategy());
+	}
+	
+	public ArrayList<Service> getMyServices() {
+		ArrayList<Service> services = new ArrayList<Service>(this.myServices.keySet());
+		return services;
+	}
+
+	public ArrayList<Service> getMyServiceDependences(Service service) {
+		if (this.myServices.containsKey(service)) {
+			return this.myServices.get(service);
+		}
+		return new ArrayList<Service>();
+	}
+
+	public void setCurrentProviders(Map<Service, Component> currentProviders) {
+		this.currentProviders = currentProviders;
+	}
+
+	public void setServiceCost(Service service, Integer cost) {
+		this.serviceCost.put(service, cost);
+	}
+
+	public Map<Service, Integer> getServiceCost() {
+		return this.serviceCost;
+	}
+
+	class RemedialBeliefRevisionStrategy extends DefaultBeliefRevisionStrategy {
+		
+		private MessageTemplate mtNotification;
+		private MessageTemplate mtServiceRequest;
+
+		@Override
+		public void reviewBeliefs() {
+			super.reviewBeliefs();
+			
+			this.mtNotification = MessageTemplate.MatchPerformative(ACLMessage.INFORM_REF);
+			ACLMessage notificationMsg = getMyAgent().receive(mtNotification);
+			if (notificationMsg != null) {
+				getMyAgent().addGoal(new VerifyAbnormalBehaviourGoal(notificationMsg));
+			}
+
+			this.mtServiceRequest = MessageTemplate.MatchPerformative(ACLMessage.REQUEST);
+			ACLMessage serviceRequestMsg = getMyAgent().receive(mtServiceRequest);
+			if (serviceRequestMsg != null) {
+				Service service = new Service(serviceRequestMsg.getContent());
+				if (myServices.containsKey(service)) {
+					getMyAgent().addGoal(new ProvideServiceGoal(serviceRequestMsg));
+				}
+			}
+		}
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/remedial/RemedialServiceProvider.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/remedial/RemedialServiceProvider.java
new file mode 100644
index 0000000..54c15aa
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/remedial/RemedialServiceProvider.java
@@ -0,0 +1,98 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol.remedial;
+
+import java.util.ArrayList;
+
+import bdi4jade.core.Capability;
+import bdi4jade.core.SingleCapabilityAgent;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import jade.domain.DFService;
+import jade.domain.FIPAException;
+import jade.domain.FIPAAgentManagement.DFAgentDescription;
+import jade.domain.FIPAAgentManagement.Property;
+import jade.domain.FIPAAgentManagement.ServiceDescription;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class RemedialServiceProvider extends SingleCapabilityAgent {
+
+	private static final long serialVersionUID = 7910239686830855344L;
+	
+	private String customName;
+
+	public RemedialServiceProvider(String customName) {
+		super();
+		this.customName = customName;
+	}
+
+	public RemedialServiceProvider(String customName, Capability capability) {
+		super(capability);
+		this.customName = customName;
+	}
+
+	public String getCustomName() {
+		return customName;
+	}
+
+	public void register() {
+		RemedialCapability capability = (RemedialCapability) this.getCapability();
+		ArrayList<Service> services = capability.getMyServices();
+
+		DFAgentDescription dfd = new DFAgentDescription();
+		dfd.setName(this.getAID());
+		for (Service service : services) {
+			ServiceDescription sd = new ServiceDescription();
+			sd.setType(service.getId());
+			sd.setName(service.getId());
+
+			Property property = new Property();
+			property.setName(Service.COST);
+			
+			int cost = capability.getServiceCost().get(service);
+			property.setValue(String.valueOf(cost));
+
+			sd.addProperties(property);
+			dfd.addServices(sd);
+		}
+		try {
+			DFService.register(this, dfd);
+		} catch (FIPAException fe) {
+			fe.printStackTrace();
+		}
+	}
+
+	@Override
+	protected void takeDown() {
+		try {
+			DFService.deregister(this);
+		} catch (FIPAException fe) {
+			fe.printStackTrace();
+		}
+		System.out.println("Deregistering from Yellow Page Services.");
+		super.takeDown();
+	}
+	
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/script.r b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/script.r
new file mode 100644
index 0000000..c429843
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/script.r
@@ -0,0 +1,18 @@
+args = commandArgs(trailingOnly=TRUE)
+
+if (length(args)==0) {
+  stop("At least one argument must be supplied (input file).n", call.=FALSE)
+}
+
+df = read.table(args[1], header=TRUE)
+time = c(df$time)
+weights = c(df$weights)
+densidade <- density(time, weights = weights)
+
+lowerfence <- quantile(time)[["25%"]] - 1.5 * IQR(time)
+upperfence <- quantile(time)[["75%"]] + 1.5 * IQR(time)
+
+f <- approxfun(densidade$x, densidade$y, yleft = 0, yright = 0)
+result <- integrate(f, lowerfence, upperfence)$value
+
+write.table(result, file=args[2], row.names = FALSE, col.names = FALSE)
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/ServiceProviderAgent.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/ServiceProviderAgent.java
new file mode 100644
index 0000000..b9c7b00
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/ServiceProviderAgent.java
@@ -0,0 +1,101 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol;
+
+import java.util.ArrayList;
+
+import bdi4jade.core.Capability;
+import bdi4jade.core.SingleCapabilityAgent;
+import bdi4jade.examples.interactionprotocol.domain.Service;
+import jade.domain.DFService;
+import jade.domain.FIPAException;
+import jade.domain.FIPAAgentManagement.DFAgentDescription;
+import jade.domain.FIPAAgentManagement.Property;
+import jade.domain.FIPAAgentManagement.ServiceDescription;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class ServiceProviderAgent extends SingleCapabilityAgent {
+
+	private static final long serialVersionUID = 3958283995451069802L;
+
+	private String customName;
+
+	public ServiceProviderAgent(String customName) {
+		super();
+		this.customName = customName;
+	}
+
+	public ServiceProviderAgent(String customName, Capability capability) {
+		super(capability);
+		this.customName = customName;
+	}
+
+	public String getCustomName() {
+		return customName;
+	}
+
+	public void register() {
+		CauseAnalysisCapability capability = (CauseAnalysisCapability) this.getCapability();
+		ArrayList<Service> services = capability.getMyServices();
+
+		DFAgentDescription dfd = new DFAgentDescription();
+		dfd.setName(this.getAID());
+		//System.out.println(this.customName);
+		for (Service service : services) {
+			ServiceDescription sd = new ServiceDescription();
+			sd.setType(service.getId());
+			sd.setName(service.getId());
+
+			Property property = new Property();
+			property.setName(Service.COST);
+			
+			int cost = capability.getServiceCost().get(service);
+			property.setValue(String.valueOf(cost));
+
+			sd.addProperties(property);
+			dfd.addServices(sd);
+			
+			//System.out.println("\t" + service.getId() + ": " + cost);
+		}
+		try {
+			DFService.register(this, dfd);
+		} catch (FIPAException fe) {
+			fe.printStackTrace();
+		}
+	}
+
+	@Override
+	protected void takeDown() {
+		try {
+			DFService.deregister(this);
+		} catch (FIPAException fe) {
+			fe.printStackTrace();
+		}
+		System.out.println("Deregistering from Yellow Page Services.");
+		super.takeDown();
+	}
+
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/Trace.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/Trace.java
new file mode 100644
index 0000000..00fddc2
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/Trace.java
@@ -0,0 +1,117 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class Trace {
+
+	private String sender;
+	private String receiver;
+	private String service;
+	private String cid;
+	private String parentCid;
+	private long sentAt;
+	private long receivedAt;
+	private String value;
+
+	public Trace(String sender, String receiver, String service, String cid) {
+		this.sender = sender;
+		this.receiver = receiver;
+		this.service = service;
+		this.cid = cid;
+		this.parentCid = null;
+		this.sentAt = System.currentTimeMillis();
+	}
+
+	public Trace(String sender, String receiver, String service, String cid, String parentCid) {
+		this(sender, receiver, service, cid);
+		this.parentCid = parentCid;
+	}
+
+	public String getSender() {
+		return sender;
+	}
+
+	public void setSender(String sender) {
+		this.sender = sender;
+	}
+
+	public String getReceiver() {
+		return receiver;
+	}
+
+	public void setReceiver(String receiver) {
+		this.receiver = receiver;
+	}
+
+	public String getService() {
+		return service;
+	}
+
+	public void setService(String service) {
+		this.service = service;
+	}
+
+	public String getCid() {
+		return cid;
+	}
+
+	public void setCid(String cid) {
+		this.cid = cid;
+	}
+
+	public String getParentCid() {
+		return this.parentCid;
+	}
+
+	public void setParentCid(String parentCid) {
+		this.parentCid = parentCid;
+	}
+
+	public long getSentAt() {
+		return sentAt;
+	}
+
+	public void setSentAt(long sentAt) {
+		this.sentAt = sentAt;
+	}
+
+	public long getReceivedAt() {
+		return receivedAt;
+	}
+
+	public void setReceivedAt(long receivedAt) {
+		this.receivedAt = receivedAt;
+	}
+
+	public String getValue() {
+		return value;
+	}
+
+	public void setValue(String value) {
+		this.value = value;
+	}
+}
diff --git a/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/TraceDatabase.java b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/TraceDatabase.java
new file mode 100644
index 0000000..205116d
--- /dev/null
+++ b/bdi-jade-test/src/bdi4jade/examples/interactionprotocol/TraceDatabase.java
@@ -0,0 +1,55 @@
+//----------------------------------------------------------------------------
+// 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.examples.interactionprotocol;
+
+import com.mongodb.MongoClient;
+
+/**
+ * @author jgfaccin
+ *
+ */
+public class TraceDatabase implements AutoCloseable {
+
+	private static MongoClient instance = null;
+
+	private TraceDatabase() {}
+
+	public static MongoClient getInstance() {
+		if (instance == null)
+			synchronized(TraceDatabase.class) {
+				if (instance == null) {
+					instance = new MongoClient("localhost");
+				}
+			}
+
+		return instance;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.AutoCloseable#close()
+	 */
+	@Override
+	public void close() throws Exception {
+		instance.close();		
+	}
+}