package it.unito.di.artifact;
import it.unito.di.logic.commit.Commitment;
import jade.core.AID;
import jade.core.behaviours.Behaviour;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import cartago.CartagoException;
import cartago.OPERATION;
import cartago.Op;
import cartago.OpFeedbackParam;
import cartago.tools.AbstractTupleSpace;
import cartago.util.agent.ActionFailedException;
public abstract class CommunicationArtifact extends AbstractTupleSpace {
protected Logger logger = LogManager.getLogger(CommunicationArtifact.class);
public static final String ENACT = "enact";
public static final String DEACT = "deact";
public static String ARTIFACT_TYPE = "CommunicationArtifact";
public static String CA_ROLE = "CARole";
/**
* List of enabled Roles for this artifact.
*/
protected static HashMap<String, Class<? extends Role>> enabledRoles = new HashMap<String, Class<? extends Role>>();
static {
addEnabledRole(CA_ROLE, CARole.class);
}
/**
* List of currently enacted Roles for this artifact.
*/
protected ArrayList<Role> enactedRoles = new ArrayList<Role>();
public CommunicationArtifact() {
super();
}
public ArrayList<RoleId> getEnactedRolesIds() {
ArrayList<RoleId> arr = new ArrayList<RoleId>();
for (Role r : enactedRoles) {
arr.add(r.getRoleId());
}
return arr;
}
public abstract String getArtifactType();
/**
* Method mandatory to add enabled Roles to this communication artifact.
* @param roleName
*/
protected static void addEnabledRole(String roleName, Class<? extends Role> roleType) {
enabledRoles.put(roleName, roleType);
}
@OPERATION
protected void enact(String roleName, Behaviour offeredPlayerBehaviour, AID agent, OpFeedbackParam<Role> role) {
logger.debug("Enactment of "+roleName+" for agent "+agent.getName());
if (roleName.equals(CA_ROLE)) {
role.set(this.new CARole(CA_ROLE, offeredPlayerBehaviour, agent));
enactedRoles.add(role.get());
logger.debug("Enactment done.");
return;
}
if (checkRoleRequirements(roleName, new Behaviour[]{offeredPlayerBehaviour})) {
// set the requested role; need to load class and instantiate a role
Class<? extends Role> a = enabledRoles.get(roleName);
try {
Constructor<? extends Role> cons = a.getDeclaredConstructor(new Class[] {this.getClass(), Behaviour.class, AID.class});
Role newRole = cons.newInstance(this, offeredPlayerBehaviour, agent);
role.set(newRole);
enactedRoles.add(role.get());
logger.debug("Enactment done.");
return;
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
logger.error("Enactment failed: Wrong Role Type.");
failed("Wrong role type.");
}
}
@OPERATION
protected void deact(String roleName, Role role) {
}
@OPERATION
protected void send(CAMessage message) {
// must register the sender of the message
logger.debug("Sending "+message);
if (message.getRoleReceiver().getType() == RoleId.GENERIC_ROLE) {
for (Role r : enactedRoles)
// conditions: do not send the message to yourself, and send message to roles with the right generic type
if (!(r.getRoleId().equals(message.getSender())) && r.getRoleId().equals(message.getRoleReceiver()))
outImpl(r.getRoleId()+"."+message.getPerformative(), message);
}
else
outImpl(message.getRoleReceiver().toString()+"."+message.getPerformative(), message);
}
// @OPERATION
// protected void receive(RoleId receiverRoleId, OpFeedbackParam<RoleMessage> message) {
// inImpl(receiverRoleId.toString(), message);
// logger.debug("Received from "+receiverRoleId +" message "+message.get());
//
// }
@OPERATION
protected void receive(RoleId receiverRoleId, int performative, OpFeedbackParam<CAMessage> message) {
inImpl(receiverRoleId+"."+performative, message);
logger.debug("Received from "+receiverRoleId +" message "+message.get());
}
@OPERATION
protected void receiveNoBlock(RoleId receiverRoleId, OpFeedbackParam<CAMessage> message) {
inpImpl(receiverRoleId.toString()+".11", message);
logger.debug("Received non-blocking from "+receiverRoleId);
}
@OPERATION
protected void receiveNoBlockPerf(RoleId receiverRoleId, int performative, OpFeedbackParam<CAMessage> message) {
inpImpl(receiverRoleId+"."+performative, message);
logger.debug("Received non-blocking from "+receiverRoleId);
}
/*
* Test whether proposed Role match requirements for this artifact.
*/
protected boolean checkRoleRequirements(String roleName, Behaviour[] offeredPlayerBehaviours) {
logger.debug("Checking role requirements for "+roleName);
// check the requested Role Name
if (!enabledRoles.containsKey(roleName)) {
logger.debug("Role "+roleName+" not found among enabled roles.");
return false;
}
// control is excluded for role "CA_Role"
if (roleName.equals(CA_ROLE))
return true;
logger.debug("Retrieving annotations for behaviour classes...");
Class<? extends Behaviour> behClass;
ArrayList<Annotation> behaviourTypeAnnotations = new ArrayList<Annotation>();
Annotation behaviourTypeAnnotation;
for (Behaviour beh : offeredPlayerBehaviours) {
behClass = beh.getClass();
behaviourTypeAnnotation = behClass.getAnnotation(BehaviourType.class);
if (behaviourTypeAnnotation == null) {
logger.debug("Annotation 'BehaviourType' is missing for behaviour");
return false;
}
behaviourTypeAnnotations.add(behaviourTypeAnnotation);
}
logger.debug("Found "+behaviourTypeAnnotations.size()+" annotations.");
logger.debug("Done. Retrieving annotations for role class...");
Class<?> roleClass;
try {
String roleClassName = (this.getClass().getName())+"$"+roleName;
logger.debug("Retrieving class for requested "+roleClassName);
roleClass = Class.forName(roleClassName);
} catch (ClassNotFoundException e) {
logger.debug("Bad role name.");
return false;
}
Annotation roleAnnotation = roleClass.getAnnotation(RoleType.class);
if (roleAnnotation == null) {
logger.debug("Annotation 'RoleType' is missing for role");
return false;
}
// Both annotations retrieved
logger.debug("Both annotations retrieved. Checking requirements compliance...");
// Getting instances for retrieved types
ArrayList<Type> typesToMerge = new ArrayList<Type>();
Type behaviourType;
Type roleType;
Type mergedType;
try {
for (Annotation ann : behaviourTypeAnnotations) {
behaviourType = ((BehaviourType)ann).capabilities().getDeclaredConstructor().newInstance();
typesToMerge.add(behaviourType);
}
roleType = ((RoleType)roleAnnotation).requirements().getDeclaredConstructor().newInstance();
logger.debug("Behaviour Types size: "+typesToMerge.size());
logger.debug("Role Type: "+roleType);
logger.debug("Merging retrieved types...");
mergedType = Type.merge(typesToMerge);
return roleType.isIncluded(mergedType);
} catch (InstantiationException e) {
logger.error("Instatiation error when instancing requirements.");
e.printStackTrace();
} catch (IllegalAccessException e) {
logger.error("Illegal Access Exception.");
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
/**
* Role "User", for basic send/receive communication artifact primitives
* @author fefo
*
*/
public class CARole extends Role {
public CARole(String roleName, Behaviour player, AID agent) {
super(roleName, player, agent, getId());
}
public void send(CAMessage message) {
try {
logger.debug("Sending message: "+message);
doAction(this.getArtifactId(), new Op("send", message));
} catch (ActionFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CartagoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// receive the first message sent to this role
public CAMessage receive(int performative) {
OpFeedbackParam<CAMessage> message = new OpFeedbackParam<CAMessage>();
try {
doAction(this.getArtifactId(), new Op("receive", this.getRoleId(), performative, message));
} catch (ActionFailedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CartagoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return message.get();
}
// receive the first message sent to this role
public CAMessage receiveNoBlock(int performative) {
OpFeedbackParam<CAMessage> message = new OpFeedbackParam<CAMessage>();
try {
doAction(this.getArtifactId(), new Op("receiveNoBlockPerf", this.getRoleId(), performative, message));
} catch (ActionFailedException e) {
// TODO Auto-generated catch block
logger.error("Errore: "+e.getMessage());
e.printStackTrace();
} catch (CartagoException e) {
logger.error("Errore: "+e.getMessage());
// TODO Auto-generated catch block
e.printStackTrace();
}
return message.get();
}
// receive all messages sent to this role
public ArrayList<CAMessage> receiveAll() {
OpFeedbackParam<CAMessage> message = new OpFeedbackParam<CAMessage>();
ArrayList<CAMessage> arr = new ArrayList<CAMessage>();
boolean noMoreMessages = false;
while (!noMoreMessages) {
try {
doAction(this.getArtifactId(), new Op("receiveNoBlock", this.getRoleId(), message));
if (message.get() != null)
arr.add(message.get());
else
noMoreMessages = true;
} catch (ActionFailedException e) {
logger.error("No more matches in receiving");
noMoreMessages = true;
} catch (CartagoException e) {
logger.error("Error in receiving, "+e.getMessage());
e.printStackTrace();
}
}
return arr;
}
// receive first messages sent to this role
public CAMessage receive() {
OpFeedbackParam<CAMessage> message = new OpFeedbackParam<CAMessage>();
try {
doAction(this.getArtifactId(), new Op("receiveNoBlock", this.getRoleId(), message));
if (message.get() != null)
return message.get();
else
return null;
} catch (ActionFailedException e) {
e.printStackTrace();
logger.error("No more matches in receiving");
return null;
} catch (CartagoException e) {
logger.error("Error in receiving, "+e.getMessage());
e.printStackTrace();
return null;
}
}
public ArrayList<CAMessage> receiveAll(int performative) {
OpFeedbackParam<CAMessage> message = new OpFeedbackParam<CAMessage>();
ArrayList<CAMessage> arr = new ArrayList<CAMessage>();
boolean noMoreMessages = false;
while (!noMoreMessages) {
try {
doAction(this.getArtifactId(), new Op("receiveNoBlockPerf", this.getRoleId(), performative, message));
logger.info("Richiesta la receiveNoBlock");
if (message.get() != null)
arr.add(message.get());
else
noMoreMessages = true;
} catch (ActionFailedException e) {
logger.error("No more matches in receiving");
noMoreMessages = true;
} catch (CartagoException e) {
logger.error("Error in receiveing, "+e.getMessage());
e.printStackTrace();
}
}
return arr;
}
}
}