VerifySuspiciousComponentPlanBody.java

177 lines | 7.285 kB Blame History Raw Download
//----------------------------------------------------------------------------
// 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);
			}
		}
	}
}