package org.societies.personalisation.CAUIPrediction.impl;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.societies.api.comm.xmpp.interfaces.ICommManager;
import org.societies.api.context.event.CtxChangeEvent;
import org.societies.api.context.event.CtxChangeEventListener;
import org.societies.api.context.model.CtxAssociation;
import org.societies.api.context.model.CtxAssociationIdentifier;
import org.societies.api.context.model.CtxAttribute;
import org.societies.api.context.model.CtxAttributeIdentifier;
import org.societies.api.context.model.CtxEntityIdentifier;
import org.societies.api.context.model.CtxIdentifier;
import org.societies.api.context.model.CtxModelType;
import org.societies.api.context.model.util.SerialisationHelper;
import org.societies.api.identity.IIdentity;
import org.societies.api.identity.INetworkNode;
import org.societies.api.identity.InvalidFormatException;
import org.societies.api.internal.context.broker.ICtxBroker;
import org.societies.api.internal.context.model.CtxAssociationTypes;
import org.societies.api.internal.context.model.CtxAttributeTypes;
import org.societies.personalisation.CAUI.api.model.UserIntentModelData;
public class CommunityJoinMonitor implements CtxChangeEventListener{
private static final Logger LOG = LoggerFactory.getLogger(CommunityJoinMonitor.class);
private ExecutorService executorService = Executors.newSingleThreadExecutor();
private ICtxBroker ctxBroker;
private final IIdentity ownerId;
private ICommManager commMgr;
/// check community estimation communities state
//private final Set<String> communities = new CopyOnWriteArraySet<String>();
private final Set<CtxEntityIdentifier> communities = new CopyOnWriteArraySet<CtxEntityIdentifier>();
public CommunityJoinMonitor(ICtxBroker ctxBrok, ICommManager commMngr) throws Exception{
this.commMgr = commMngr;
this.ctxBroker = ctxBrok;
//fetch my CSS ID
final String ownerIdStr = commMgr.getIdManager().getThisNetworkNode().getBareJid();
this.ownerId = commMngr.getIdManager().fromJid(ownerIdStr);
//fetch my CSS Entity
//IndividualCtxEntity ownerEnt = this.ctxBroker.retrieveIndividualEntity(this.ownerId).get();
CtxEntityIdentifier indiEntID = this.ctxBroker.retrieveIndividualEntityId(null, this.ownerId).get();
List<CtxIdentifier> isMemberOfCtxIDList = this.ctxBroker.lookup(indiEntID, CtxModelType.ASSOCIATION, CtxAssociationTypes.IS_MEMBER_OF).get();
if(!isMemberOfCtxIDList.isEmpty() ){
CtxAssociation isMemberOfAssoc = (CtxAssociation) this.ctxBroker.retrieve(isMemberOfCtxIDList.get(0)).get();
if (LOG.isInfoEnabled())
LOG.debug("Registering for context changes related to CSS is_member_of association '"
+ ownerId + "'");
ctxBroker.registerForChanges(this, isMemberOfAssoc.getId());
} else {
LOG.error("Could not initialise: is_member_of_CISs association is null");
throw new IllegalStateException("Could not initialise: is_member_of_CISs association is null");
}
}
@Override
public void onCreation(CtxChangeEvent event) {
// TODO Auto-generated method stub
}
@Override
public void onUpdate(CtxChangeEvent event) {
// TODO Auto-generated method stub
}
@Override
public void onModification(CtxChangeEvent event) {
if (CtxAssociationTypes.IS_MEMBER_OF.equals(event.getId().getType())){
LOG.debug("joined cis event received : event.getId(): "+ event.getId() + " --- event.getSource():"+ event.getSource());
CtxAssociationIdentifier assocID = (CtxAssociationIdentifier) event.getId();
this.executorService.execute(new CssJoinedCommunityHandler(assocID));
}
}
@Override
public void onRemoval(CtxChangeEvent event) {
// TODO Auto-generated method stub
}
private class CssJoinedCommunityHandler implements Runnable {
private final CtxAssociationIdentifier ctxAssocId;
private CssJoinedCommunityHandler(CtxAssociationIdentifier ctxAssocId) {
this.ctxAssocId = ctxAssocId;
LOG.debug("CssJoinedCommunityHandler 1 "+ this.ctxAssocId );
//CssJoinedCommunityHandler 1 context://university.ict-societies.eu/ASSOCIATION/isMemberOf/2
}
@Override
public void run() {
//LOG.info("CssJoinedCommunityHandler 2 "+ this.ctxId );
CtxEntityIdentifier cssEntId = null;
try {
final CtxAssociation isMemberOfAssoc = (CtxAssociation) ctxBroker.retrieve(this.ctxAssocId).get();
if (isMemberOfAssoc == null) {
LOG.error("Could not handle CIS membership change: "
+ "Could not retrieve '" + this.ctxAssocId + "'");
return;
}
LOG.debug("CssJoinedCommunityHandler 3 "+ isMemberOfAssoc.getId() );
final Set<CtxEntityIdentifier> currentCommunities = new HashSet<CtxEntityIdentifier>();
for (final CtxEntityIdentifier cisCtxId : isMemberOfAssoc.getChildEntities()) {
//final String communityId = cisCtxId.getOwnerId();
currentCommunities.add(cisCtxId);
}
// find communities the user is no long member of
final Set<CtxEntityIdentifier> oldCommunities = new HashSet<CtxEntityIdentifier>(communities);
oldCommunities.removeAll(currentCommunities);
LOG.debug("CSS ctx Id " + isMemberOfAssoc.getParentEntity() + ", oldCommunities=" + oldCommunities);
// find new communities the user is member of
final Set<CtxEntityIdentifier> newCommunities = new HashSet<CtxEntityIdentifier>(currentCommunities);
newCommunities.removeAll(communities);
LOG.debug("CSS ctx Id " + isMemberOfAssoc.getParentEntity() + ", newCommunities=" + newCommunities);
// update communities the user is member of
communities.clear();
communities.addAll(currentCommunities);
for (final CtxEntityIdentifier oldCommunity : oldCommunities){
ctxBroker.unregisterFromChanges(new CACIModelEventHandler(), oldCommunity, CtxAttributeTypes.CACI_MODEL);
LOG.info("UnRegistering for context changes related to CIS CACI_Model ctx attribute for "+oldCommunity );
}
for (final CtxEntityIdentifier newCommunity : newCommunities) {
ctxBroker.registerForChanges(new CACIModelEventHandler(), newCommunity , CtxAttributeTypes.CACI_MODEL);
LOG.info("Registering for context changes related to CIS CACI_Model ctx attribute for "+newCommunity );
}
} catch (Exception e) {
LOG.error(" Exception while trying to register for context changes related to CIS CACI_Model ctx attribute of cis: '" +cssEntId +"' "+e.getLocalizedMessage() );
e.printStackTrace();
}
}
}
private class CACIModelEventHandler implements CtxChangeEventListener{
CACIModelEventHandler(){
LOG.debug("inside CACIModelEventHandler ------------------");
}
@Override
public void onCreation(CtxChangeEvent event) {
LOG.info("inside CACIModelEventHandler ------------------ onCreation "+event.getId());
}
@Override
public void onUpdate(CtxChangeEvent event) {
LOG.info("inside CACIModelEventHandler ------------------ onUpdate "+event.getId());
//
}
@Override
public void onModification(CtxChangeEvent event) {
LOG.info("inside CACIModelEventHandler ------------------ onModification ");
if (CtxAttributeTypes.CACI_MODEL.equals(event.getId().getType()))
LOG.debug("update of caci model received : event.getId(): "+ event.getId() + " --- event.getSource():"+ event.getSource());
CtxIdentifier attributeCaciID = event.getId();
if( attributeCaciID != null ){
try {
// retrieve caciModelAttr from CIS ctx DB
CtxAttribute caciModelAttrRemote = (CtxAttribute) ctxBroker.retrieve(attributeCaciID).get();
LOG.debug("*** remote caci attribute retrieved " + caciModelAttrRemote);
LOG.debug("***onModification 1 caciModelAttrRemote= " + caciModelAttrRemote.getId());
//store caciModel to local CSS ctx DB
CtxAttribute caciModelAttrLocal = null;
///List<CtxIdentifier> caciModelAttrLocalList = ctxBroker.lookup(CtxModelType.ATTRIBUTE, CtxAttributeTypes.CACI_MODEL).get();
List<CtxIdentifier> caciModelAttrLocalList = ctxBroker.lookup(caciModelAttrRemote.getScope(), CtxModelType.ATTRIBUTE, CtxAttributeTypes.CACI_MODEL).get();
LOG.debug("***onModification 2 caciModelAttrLocalList= " + caciModelAttrLocalList.size());
// IIdentity localcssID = getOwnerId();
// CtxEntityIdentifier entityID = ctxBroker.retrieveIndividualEntityId(null, localcssID).get();
// LOG.info("***onModification 3 entityID= " + entityID.toString());
if( caciModelAttrLocalList.isEmpty()){
// caciModelAttrLocal = ctxBroker.createAttribute(entityID, CtxAttributeTypes.CACI_MODEL).get();
LOG.debug("***onModification 4 ctxBroker.createAttribute= null ");
} else {
CtxAttributeIdentifier attrID = (CtxAttributeIdentifier) caciModelAttrLocalList.get(0);
caciModelAttrLocal = (CtxAttribute) ctxBroker.retrieveAttribute(attrID, false).get();
LOG.debug("***onModification 5 ctxBroker.retrieveAttribute= " + caciModelAttrLocal.getId());
}
if(caciModelAttrRemote.getBinaryValue() != null){
UserIntentModelData newUIModelData = (UserIntentModelData) SerialisationHelper.deserialise(caciModelAttrRemote.getBinaryValue(), this.getClass().getClassLoader());
byte[] binaryModel = SerialisationHelper.serialise(newUIModelData);
caciModelAttrLocal.setBinaryValue(binaryModel);
ctxBroker.update(caciModelAttrLocal);
LOG.debug("*** model stored in = " + caciModelAttrLocal.getId());
}
} catch (Exception e) {
LOG.error("Exception when handling modification event for new remote CACI model "+e.getLocalizedMessage());
e.printStackTrace();
}
}
}
@Override
public void onRemoval(CtxChangeEvent event) {
// TODO Auto-generated method stub
}
public IIdentity getOwnerId(){
IIdentity cssOwnerId = null;
try {
final INetworkNode cssNodeId = commMgr.getIdManager().getThisNetworkNode();
//LOG.info("*** cssNodeId = " + cssNodeId);
final String cssOwnerStr = cssNodeId.getBareJid();
cssOwnerId = commMgr.getIdManager().fromJid(cssOwnerStr);
} catch (InvalidFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return cssOwnerId;
}
}
}