/** * Copyright (c) 2011, SOCIETIES Consortium * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.societies.personalisation.CAUIPrediction.impl; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.societies.api.comm.xmpp.interfaces.ICommManager; import org.societies.api.context.CtxException; import org.societies.api.context.model.CtxAssociation; import org.societies.api.context.model.CtxAssociationTypes; 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.IndividualCtxEntity; 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.CtxAttributeTypes; import org.societies.api.personalisation.model.IAction; import org.societies.personalisation.CAUI.api.CAUITaskManager.ICAUITaskManager; import org.societies.personalisation.CAUI.api.model.IUserIntentAction; import org.societies.personalisation.CAUI.api.model.UserIntentModelData; /** * CAUIPrediction * * @author nikosk * @created 12-May-2013 7:15:15 PM */ public class CACIPrediction { private static final Logger LOG = LoggerFactory.getLogger(CACIPrediction.class); private ICtxBroker ctxBroker; private ICAUITaskManager caciTaskManager; private ICommManager commsMgr ; static boolean caciPredictionEnabled = true; static boolean caciFreshness = false; static boolean cacimodelExist = false; public UserIntentModelData currentCACIModelData; public CACIPrediction(ICtxBroker ctxBroker, ICommManager commsMgr){ this.ctxBroker = ctxBroker; this.commsMgr = commsMgr; } public CACIPrediction(ICtxBroker ctxBroker, ICAUITaskManager caciTaskManager, ICommManager commsMgr){ this.ctxBroker = ctxBroker; this.caciTaskManager = caciTaskManager; this.commsMgr = commsMgr; LOG.debug("inside CACIPrediction "); //when css joins a new cis, will automatically register for caci model events. try { LOG.debug("register for cis join and new community model creation"); new CommunityJoinMonitor(this.ctxBroker ,this.commsMgr); } catch (Exception e) { LOG.error("Exception while trying to register for new community join events " +e.getLocalizedMessage()); } } /* private void setupLocalCaciAttr(){ CtxAttribute caciModelAttrLocal = null; List<CtxIdentifier> caciModelAttrLocalList; try { // TODO update this with proper lookup method lookup(entID, CtxModelType.ATTRIBUTE, CtxAttributeTypes.CACI_MODEL) caciModelAttrLocalList = ctxBroker.lookup(CtxModelType.ATTRIBUTE, CtxAttributeTypes.CACI_MODEL).get(); if( !caciModelAttrLocalList.isEmpty() ){ // get locally stored model CtxAttribute caciModelAttr = this.ctxBroker.retrieveAttribute((CtxAttributeIdentifier) caciModelAttrLocalList.get(0), false).get(); if(caciModelAttr.getBinaryValue() != null){ UserIntentModelData newCACIModelData = (UserIntentModelData) SerialisationHelper.deserialise(caciModelAttr.getBinaryValue(), this.getClass().getClassLoader()); setCACIActiveModel(newCACIModelData); } } else { LOG.debug("caci model doesn't exist -- creating empty local Caci Attribute"); IIdentity localcssID = getOperatorID(); CtxEntityIdentifier entityID = ctxBroker.retrieveIndividualEntityId(null, localcssID).get(); caciModelAttrLocal = ctxBroker.createAttribute(entityID, CtxAttributeTypes.CACI_MODEL).get(); LOG.debug("***CACI constructor ctxBroker.createAttribute= " + caciModelAttrLocal.getId()); } } catch (Exception e) { LOG.error("Exception while trying to create CACI CtxAttribute upon component start up" +e.getLocalizedMessage()); e.printStackTrace(); } } */ public List<IUserIntentAction> getPrediction(IIdentity requestor, IAction action){ //List<IUserIntentAction> predictedActionsList = new ArrayList<IUserIntentAction>(); // identify performed action in model List<IUserIntentAction> results = new ArrayList<IUserIntentAction>(); String par = action.getparameterName(); String val = action.getvalue(); if(currentCACIModelData != null ) { LOG.debug("set latest CACI model " + currentCACIModelData); this.caciTaskManager.updateModel(currentCACIModelData); } LOG.debug("cacimodel to be used for prediction: "+ this.caciTaskManager.getCAUIActiveModel() ); List<IUserIntentAction> actionsList = this.caciTaskManager.retrieveActionsByTypeValue(par, val); LOG.debug("1. CACIMODEL TaskManager.retrieveActionsByTypeValue(par, val) " +actionsList); if(actionsList.size()>0){ // improve this to also use context for action identification //IUserIntentAction currentAction = actionsList.get(0); IUserIntentAction currentAction = findBestMatchingAction(actionsList); LOG.debug("2. CACIMODEL currentAction " +currentAction); Map<IUserIntentAction,Double> nextActionsMap = this.caciTaskManager.retrieveNextActions(currentAction); //LOG.info("5. nextActionsMap " +nextActionsMap); // no context if(nextActionsMap.size()>0){ for(IUserIntentAction nextAction : nextActionsMap.keySet()){ Double doubleConf = nextActionsMap.get(nextAction); doubleConf = doubleConf*100; //doubleConf = 70.0; nextAction.setConfidenceLevel(doubleConf.intValue()); //LOG.info("6. nextActionsMap " +nextAction); results.add(nextAction); LOG.debug(" ****** caci prediction map created "+ results); } } } return results; } private IUserIntentAction findBestMatchingAction(List<IUserIntentAction> actionList){ IUserIntentAction bestAction = null; HashMap<IUserIntentAction, Integer> actionsScoreMap = new HashMap<IUserIntentAction, Integer>(); CtxAttribute currentLocation = retrieveOperatorsCtx(CtxAttributeTypes.LOCATION_SYMBOLIC); CtxAttribute currentStatus = retrieveOperatorsCtx(CtxAttributeTypes.STATUS); //CtxAttribute currentTemp = retrieveOperatorsCtx(CtxAttributeTypes.TEMPERATURE); for(IUserIntentAction action : actionList ){ HashMap<String,Serializable> actionCtx = action.getActionContext(); int actionMatchScore = 0; if( actionCtx != null ){ actionMatchScore = 0; for(String ctxType : actionCtx.keySet()){ Serializable ctxValue = actionCtx.get(ctxType); if( ctxValue != null){ if(ctxType.equals(CtxAttributeTypes.LOCATION_SYMBOLIC)&& ctxValue instanceof String){ String actionLocation = (String) ctxValue; // LOG.info("String context location value :"+ actionLocation); if(currentLocation != null){ if(currentLocation.getStringValue() != null){ if(currentLocation.getStringValue().equals(actionLocation)) actionMatchScore = actionMatchScore +1; } } } /*else if(ctxType.equals(CtxAttributeTypes.TEMPERATURE) && ctxValue instanceof Integer ){ Integer actionTemperature= (Integer) ctxValue; LOG.info("Integer context temperature value :"+ actionTemperature); if(currentTemp.getIntegerValue().equals(actionTemperature)) actionMatchScore = actionMatchScore +1; }*/ else if(ctxType.equals(CtxAttributeTypes.STATUS) && ctxValue instanceof String ){ String actionStatus = (String) ctxValue; //LOG.info("String context status value :"+ actionStatus); if(currentStatus != null ){ if(currentStatus.getStringValue() != null){ if( currentStatus.getStringValue().equals(actionStatus)) actionMatchScore = actionMatchScore +1; } } } else { LOG.debug("findBestMatchingAction: context type:"+ctxType +" does not match"); } } } actionsScoreMap.put(action, actionMatchScore); //System.out.println("actionsScoreMap " +actionsScoreMap); } } int maxValueInMap=(Collections.max(actionsScoreMap.values())); // This will return max value in the Hashmap for(IUserIntentAction action : actionsScoreMap.keySet()){ if(actionsScoreMap.get(action).equals(maxValueInMap)) bestAction = action; } //LOG.info("best action "+bestAction); return bestAction; } /* * retreive caci model code from CIS context db public void retrieveCACIModel(){ List<CtxEntityIdentifier> commEntIDList = retrieveBelongingCIS(); LOG.debug("retrieveCACIModel commEntIDList 1 "+commEntIDList); //TODO keep local caci model //TODO remove remote com to community if(!commEntIDList.isEmpty()){ for(CtxEntityIdentifier cisEntID : commEntIDList){ LOG.debug("retrieveCACIModel commEntIDList 2 "+commEntIDList); try { CommunityCtxEntity commEntity = (CommunityCtxEntity) this.ctxBroker.retrieve(cisEntID).get(); Set<CtxAttribute> caciSet = commEntity.getAttributes(CtxAttributeTypes.CACI_MODEL); LOG.debug("retrieveCACIModel commEntIDList 3 commEntity "+commEntity.getId()); for(CtxAttribute caciAttrCommunity: caciSet){ LOG.debug("retrieveCACIModel commEntIDList 3 caciAttr "+caciAttrCommunity.getId()); if(caciAttrCommunity.getBinaryValue() != null){ //currentCaciModelAttr = caciAttr; UserIntentModelData newCACIModelData = (UserIntentModelData) SerialisationHelper.deserialise(caciAttrCommunity.getBinaryValue(), this.getClass().getClassLoader()); LOG.debug("retrieveCACIModel commEntIDList 4 caciAttr "+newCACIModelData ); storeCaciModelBD(newCACIModelData); setCACIActiveModel(newCACIModelData); } } } catch (Exception e) { LOG.error("Exception while trying to retrieve a CACI model from an existing CIS " +e.getLocalizedMessage()); e.printStackTrace(); } } } } */ /* private Boolean getCaciFreshness(CtxAttribute currentCaciModelAttr){ Boolean isFresh = false; if(currentCaciModelAttr.getQuality().getFreshness() < 10000 ){ isFresh = true; } return isFresh; } */ public void storeCaciModelDB(UserIntentModelData modelData){ final INetworkNode cssNodeId = this.commsMgr.getIdManager().getThisNetworkNode(); final String cssOwnerStr = cssNodeId.getBareJid(); CtxAttribute attr = null; try { IIdentity cssOwnerId = this.commsMgr.getIdManager().fromJid(cssOwnerStr); CtxEntityIdentifier indiEntId = this.ctxBroker.retrieveIndividualEntityId(null, cssOwnerId).get(); List<CtxIdentifier> lsCaci = this.ctxBroker.lookup(indiEntId, CtxModelType.ATTRIBUTE, CtxAttributeTypes.CACI_MODEL).get(); CtxAttributeIdentifier caciModelAttributeId = null; if (lsCaci.size()>0) { caciModelAttributeId = (CtxAttributeIdentifier) lsCaci.get(0); attr = (CtxAttribute) this.ctxBroker.retrieve(caciModelAttributeId).get(); byte[] binaryModel = SerialisationHelper.serialise(modelData); LOG.debug("updating caci model " +attr.getId() +" model: "+modelData ); this.ctxBroker.updateAttribute(attr.getId(), binaryModel).get(); } } catch (Exception e) { LOG.error("CtxAttribute of type "+CtxAttributeTypes.CACI_MODEL+ "was not updated with caci model "+e.getLocalizedMessage()); e.printStackTrace(); } } public List<CtxEntityIdentifier> retrieveBelongingCIS(){ List<CtxEntityIdentifier> commEntIDList = new ArrayList<CtxEntityIdentifier>(); List<CtxIdentifier> listISMemberOf = new ArrayList<CtxIdentifier>(); try { listISMemberOf = this.ctxBroker.lookup(CtxModelType.ASSOCIATION, CtxAssociationTypes.IS_MEMBER_OF).get(); LOG.debug(".............listISMemberOf................." +listISMemberOf); if(!listISMemberOf.isEmpty() ){ CtxAssociation assoc = (CtxAssociation) this.ctxBroker.retrieve(listISMemberOf.get(0)).get(); Set<CtxEntityIdentifier> entIDSet = assoc.getChildEntities(); for(CtxEntityIdentifier entId : entIDSet){ IIdentity cisId = this.commsMgr.getIdManager().fromJid(entId.getOwnerId()); LOG.debug("cis id : "+cisId ); CtxEntityIdentifier commId = this.ctxBroker.retrieveCommunityEntityId(cisId).get(); commEntIDList.add(commId); } } } catch (Exception e) { LOG.error("Unable to retrieve CISids that css belongs to " +e.getLocalizedMessage()); } return commEntIDList; } private CtxAttribute retrieveOperatorsCtx(String type){ CtxAttribute ctxAttr = null; try { IndividualCtxEntity operator = this.ctxBroker.retrieveIndividualEntity(getOperatorID()).get(); Set<CtxAttribute> ctxAttrSet = operator.getAttributes(type); if(ctxAttrSet.size()>0){ List<CtxAttribute> ctxAttrList = new ArrayList<CtxAttribute> (ctxAttrSet); ctxAttr = ctxAttrList.get(0); } } catch (InterruptedException e) { // e.printStackTrace(); } catch (ExecutionException e) { // e.printStackTrace(); } catch (CtxException e) { // e.printStackTrace(); } return ctxAttr; } public void setCACIActiveModel (UserIntentModelData newCACIModelData){ if (newCACIModelData != null){ this.caciTaskManager.updateModel(null); this.caciTaskManager.updateModel(newCACIModelData); currentCACIModelData = newCACIModelData; cacimodelExist = true; LOG.info("caci model set - actions map: "+newCACIModelData.getActionModel()); } } protected IIdentity getOperatorID (){ final INetworkNode cssNodeId = this.commsMgr.getIdManager().getThisNetworkNode(); final String cssOwnerStr = cssNodeId.getBareJid(); IIdentity cssOwnerId = null; try { cssOwnerId = this.commsMgr.getIdManager().fromJid(cssOwnerStr); } catch (InvalidFormatException e) { LOG.error("Exception while trying to retrieve operator IIdentity "+ e.getLocalizedMessage()); e.printStackTrace(); } return cssOwnerId; } }