/** * 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.CRISTUserIntentTaskManager.impl; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.societies.api.context.CtxException; import org.societies.api.context.model.CtxAttribute; import org.societies.api.context.model.CtxAttributeIdentifier; import org.societies.api.context.model.CtxAttributeValueType; import org.societies.api.context.model.CtxEntity; import org.societies.api.context.model.CtxEntityIdentifier; import org.societies.api.context.model.CtxEntityTypes; import org.societies.api.context.model.CtxHistoryAttribute; import org.societies.api.context.model.CtxIdentifier; import org.societies.api.context.model.CtxModelObject; 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.internal.context.broker.ICtxBroker; import org.societies.api.internal.context.model.CtxAttributeTypes; import org.societies.api.internal.logging.IPerformanceMessage; import org.societies.api.internal.logging.PerformanceMessage; import org.societies.api.personalisation.model.IAction; import org.societies.api.schema.servicelifecycle.model.ServiceResourceIdentifier; import org.societies.personalisation.CRIST.api.CRISTUserIntentDiscovery.ICRISTUserIntentDiscovery; import org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager.ICRISTUserIntentTaskManager; import org.societies.personalisation.CRIST.api.model.CRISTUserAction; import org.societies.personalisation.CRIST.api.model.CRISTUserSituation; import org.societies.personalisation.CRIST.api.model.CRISTUserTask; import org.societies.personalisation.CRIST.api.model.CRISTUserTaskModelData; import org.societies.personalisation.CRISTUserIntentDiscovery.impl.CRISTHistoryData; import org.societies.personalisation.CRISTUserIntentDiscovery.impl.CRISTUserIntentDiscovery; import org.societies.personalisation.common.api.management.IInternalPersonalisationManager; import org.societies.personalisation.common.api.model.PersonalisationTypes; public class CRISTUserIntentTaskManager implements ICRISTUserIntentTaskManager { private static Logger PERF_LOG = LoggerFactory.getLogger("PerformanceMessage"); // to define a dedicated Logger IPerformanceMessage m; private static final Logger LOG = LoggerFactory.getLogger(CRISTUserIntentTaskManager.class); public static final int UPDATE_TRIGGER_THRESHOLD = 5; public static final int MAX_HISTORY_LENGTH = 1000; public static final double COMMUNITY_MODEL_WEIGHT = 0.5; // how much the community influence the individual, from 0 to 1 public static HashMap<String, CtxAttributeIdentifier> REGISTERED_CONTEXTS = null; private ArrayList<CRISTHistoryData> historyList = new ArrayList<CRISTHistoryData>(); private LinkedHashMap<String, Integer> intentModel = null;// initialized in discovery private HashMap<IIdentity, CRISTUserAction> currentUserActionMap = new HashMap<IIdentity, CRISTUserAction>(); private HashMap<IIdentity, CRISTUserSituation> currentUserSituationMap = new HashMap<IIdentity, CRISTUserSituation>(); private ICRISTUserIntentDiscovery cristDiscovery; private ICtxBroker ctxBroker; private IInternalPersonalisationManager persoMgr; public CRISTUserIntentTaskManager() { LOG.info("Hello! I'm the CRIST User Intent Manager!"); } public IInternalPersonalisationManager getPersoMgr() { return persoMgr; } public void setPersoMgr(IInternalPersonalisationManager persoMgr) { this.persoMgr = persoMgr; } public ICRISTUserIntentDiscovery getCristDiscovery() { return cristDiscovery; } public void setCristDiscovery(ICRISTUserIntentDiscovery cristDiscovery) { this.cristDiscovery = cristDiscovery; } public ICtxBroker getCtxBroker() { return ctxBroker; } public void setCtxBroker(ICtxBroker ctxBroker) { this.ctxBroker = ctxBroker; } public void initialiseCRISTUserIntentManager() { if (ctxBroker == null) { LOG.error(this.getClass().getName() + "CtxBroker is null"); } if (this.persoMgr == null) { LOG.error(this.getClass().getName() + "PersoMgr is null"); } LOG.info("Yo!! I'm a brand new service and my interface is: " + this.getClass().getName()); /* * debug CRISTCtxBrokerContact.initializeHistory(registeredContext, * ctxBrokerContact); * * historyList = * CRISTCtxBrokerContact.retrieveHistoryData(ctxBrokerContact); * * for (CRISTHistoryData historyData : historyList) { * LOG.info("retrieveHistoryData ----- " + historyData.toString()); } */ } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #addSituationsAndActionsToTask(org.societies.personalisation * .CRIST.api.model.CRISTUserTask, java.util.HashMap, java.util.HashMap) */ @Override public CRISTUserTask addSituationsAndActionsToTask(CRISTUserTask arg0, HashMap<CRISTUserAction, Double> arg1, HashMap<CRISTUserSituation, Double> arg2) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#getAction(java.lang.String) */ @Override public CRISTUserAction getAction(String arg0) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#getActionsByType(java.lang.String, * java.lang.String) */ @Override public ArrayList<CRISTUserAction> getActionsByType(String arg0, String arg1) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #getCurrentIntentAction(org.societies.api.comm.xmpp.datatypes.IIdentity, * org.societies.api.comm.xmpp.datatypes.IIdentity, * org.societies.api.servicelifecycle.model.ServiceResourceIdentifier) */ @Override public CRISTUserAction getCurrentIntentAction(IIdentity arg0, IIdentity arg1, ServiceResourceIdentifier arg2) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#getCurrentUserAction() */ @Override public CRISTUserAction getCurrentUserAction(IIdentity entityID) { // TODO Auto-generated method stub return this.currentUserActionMap.get(entityID); } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#getCurrentUserSituation() */ @Override public CRISTUserSituation getCurrentUserSituation(IIdentity entityID) { // TODO Auto-generated method stub return this.currentUserSituationMap.get(entityID); } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #getCurrentUserContext(org.societies.api.identity.IIdentity) */ @Override public ArrayList<String> getCurrentUserContext(IIdentity entityID) { // TODO Auto-generated method stub return null; // return this.currentUserContextMap.get(entityID); } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #updateUserSituation(org.societies.api.identity.IIdentity, * org.societies.api.context.model.CtxAttribute) */ @Override public void updateUserSituation(IIdentity entityID, CtxAttribute ctxAttribute) { CRISTUserSituation currentUserSituation = inferUserSituation(entityID); if (currentUserSituation != null) { this.currentUserSituationMap.put(entityID, currentUserSituation); } } //will be used in inferUserSituation method, ensure not return null private String retrieveCurrentUserContext(CtxAttributeIdentifier ctxAttrId) { try { Future<CtxModelObject> ctxAttributeRetrievedStringFuture = this.ctxBroker .retrieve(ctxAttrId); CtxAttribute retrievedCtxAttribute = (CtxAttribute) ctxAttributeRetrievedStringFuture .get(); return getValue(retrievedCtxAttribute); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (CtxException e) { e.printStackTrace(); } return ""; } private String getValue(CtxAttribute attribute){ String result = ""; if (attribute.getStringValue()!=null) { result = attribute.getStringValue(); return result; } else if(attribute.getIntegerValue()!=null) { Integer valueInt = attribute.getIntegerValue(); result = valueInt.toString(); return result; } else if (attribute.getDoubleValue()!=null) { Double valueDouble = attribute.getDoubleValue(); result = valueDouble.toString(); return result; } return result; } //ensure no return null //may have bug about convert Set to List private CRISTUserAction retrieveCurrentUserAction() { try { List<CtxAttributeIdentifier> listOfEscortingAttributeIds = new ArrayList<CtxAttributeIdentifier>(); if (ctxBroker .retrieveHistoryTuples(CtxAttributeTypes.LAST_ACTION, listOfEscortingAttributeIds, null, null) == null) { return null; } Map<CtxHistoryAttribute, List<CtxHistoryAttribute>> ctxHocTuples = ctxBroker .retrieveHistoryTuples(CtxAttributeTypes.LAST_ACTION, listOfEscortingAttributeIds, null, null).get(); if (ctxHocTuples == null || ctxHocTuples.size() == 0) { return null; } List<CtxHistoryAttribute> primaryHocAttrs = new ArrayList<CtxHistoryAttribute>(ctxHocTuples.keySet()); CtxHistoryAttribute primaryHocAttr = primaryHocAttrs.get(primaryHocAttrs.size()-1);//the last one is the current action IAction retrievedAction = (IAction) SerialisationHelper .deserialise(primaryHocAttr.getBinaryValue(), this .getClass().getClassLoader()); return new CRISTUserAction(retrievedAction); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } return null; } private CtxAttributeIdentifier registerContextUpdate(IIdentity entityID, String ctxAttributeTypeString) { CtxEntity operator; try { operator = this.ctxBroker.retrieveIndividualEntity(entityID).get(); //operator = this.ctxBroker.retrieveCssOperator().get(); Set<CtxAttribute> attrSet = operator .getAttributes(ctxAttributeTypeString); List<CtxAttribute> attrList = new ArrayList<CtxAttribute>(attrSet); if (attrList.size() > 0) { CtxAttribute attr = attrList.get(0);// the first one //System.out.println("persoMgr="+persoMgr); this.persoMgr.registerForContextUpdate(entityID, PersonalisationTypes.CRISTIntent, attr.getId()); return attr.getId(); } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (CtxException e) { e.printStackTrace(); } LOG.info("registerContextUpdate failed: " + ctxAttributeTypeString); return null; } /* ensure no return null. How? Add a "OTHER" situation, if any context is null, it is in "OTHER" * @param entityID * @return */ private CRISTUserSituation inferUserSituation(IIdentity entityID) { if (REGISTERED_CONTEXTS == null) { REGISTERED_CONTEXTS = new HashMap<String, CtxAttributeIdentifier>(); CtxAttributeIdentifier ctxAttrId = registerContextUpdate(entityID, CtxAttributeTypes.STATUS); if (ctxAttrId != null) { //System.out.println("test registered 1"); REGISTERED_CONTEXTS.put(CtxAttributeTypes.STATUS, ctxAttrId); } ctxAttrId = registerContextUpdate(entityID, CtxAttributeTypes.LOCATION_SYMBOLIC); if (ctxAttrId != null) { REGISTERED_CONTEXTS.put(CtxAttributeTypes.LOCATION_SYMBOLIC, ctxAttrId); } } CRISTUserSituation situation = new CRISTUserSituation(); //System.out.println("test0"); if (REGISTERED_CONTEXTS.get(CtxAttributeTypes.STATUS) != null) { String currentStatusString = retrieveCurrentUserContext(REGISTERED_CONTEXTS.get(CtxAttributeTypes.STATUS)); //System.out.println("test1"); if (!currentStatusString.equals("")) { //System.out.println("test2"); if (REGISTERED_CONTEXTS.get(CtxAttributeTypes.LOCATION_SYMBOLIC) != null) { String currentLocationString = retrieveCurrentUserContext(REGISTERED_CONTEXTS.get(CtxAttributeTypes.LOCATION_SYMBOLIC)); //System.out.println("test3"); if (!currentLocationString.equals("")) { situation.setSituationID(currentStatusString+"_"+currentLocationString); //System.out.println("test4"); } else { situation.setSituationID(currentStatusString); } } else { situation.setSituationID(currentStatusString); } } else { if (REGISTERED_CONTEXTS.get(CtxAttributeTypes.LOCATION_SYMBOLIC) != null) { String currentLocationString = retrieveCurrentUserContext(REGISTERED_CONTEXTS.get(CtxAttributeTypes.LOCATION_SYMBOLIC)); if (!currentLocationString.equals("")) { situation.setSituationID(currentLocationString); } } } } else { if (REGISTERED_CONTEXTS.get(CtxAttributeTypes.LOCATION_SYMBOLIC) != null) { String currentLocationString = retrieveCurrentUserContext(REGISTERED_CONTEXTS.get(CtxAttributeTypes.LOCATION_SYMBOLIC)); if (!currentLocationString.equals("")) { situation.setSituationID(currentLocationString); } } } if (situation.getSituationID() == null){ situation.setSituationID("OTHER"); } return situation; } public int getMaxIndex(double[] array) { int maxIndex = 0; double a = array[0]; for(int i=1; i<array.length; i++) { if(a < array[i]) { a = array[i]; maxIndex = i; } } return maxIndex; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #predictUserIntent(org.societies.api.identity.IIdentity, * org.societies.api.context.model.CtxAttribute) */ @SuppressWarnings("unchecked") @Override public ArrayList<CRISTUserAction> predictUserIntent(IIdentity entityID, CtxAttribute ctxAttribute) { // null paras are already handled in Prediction class // update the current situation for current context list in DB. here do not store to DB, ua do. CRISTUserSituation currentUserSituation = inferUserSituation(entityID); if (currentUserSituation != null) { this.currentUserSituationMap.put(entityID, currentUserSituation); CRISTUserAction userAction = getCurrentUserAction(entityID); if (userAction == null) { userAction = retrieveCurrentUserAction(); } if (userAction == null) { return new ArrayList<CRISTUserAction>(); } else { this.currentUserActionMap.put(entityID, userAction); } if (this.intentModel == null) { // create intent model if (cristDiscovery == null) { LOG.info("The CRIST Discovery is NULL. "); return new ArrayList<CRISTUserAction>(); } // this.cristDiscovery.enableCRISTUIDiscovery(true); //@@@ // Logging for test m = new PerformanceMessage(); m.setTestContext("Personalisation.CRISTUserIntent.HistoryList.Size"); m.setSourceComponent(this.getClass()+""); m.setOperationType("IntentModelLearningFromActionHistory");//? m.setD82TestTableName("S18"); m.setPerformanceType(IPerformanceMessage.Quanitative); m.setPerformanceNameValue("Size=" + historyList.size()); //LOG.info("#2#This is a test log for PerformanceMessage S18!"); PERF_LOG.trace(m.toString()); m = new PerformanceMessage(); m.setTestContext("Personalisation.CRISTUserIntent.ModelLearning.Delay"); m.setSourceComponent(this.getClass()+""); m.setOperationType("IntentModelLearningFromActionHistory");//? m.setD82TestTableName("S18"); m.setPerformanceType(IPerformanceMessage.Delay); long startTime = System.currentTimeMillis(); //@@@ tested method this.intentModel = this.cristDiscovery .generateNewCRISTUIModel(this.historyList); m.setPerformanceNameValue("Delay=" + (System.currentTimeMillis()-startTime)); PERF_LOG.trace(m.toString()); //Logging end //@@@ } return getNextActions(entityID, userAction, currentUserSituation); } else { LOG.info("currentUserSituation is null."); } // When currentUserSituation == null return new ArrayList<CRISTUserAction>(); } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #predictUserIntent(org.societies.api.identity.IIdentity, * org.societies.personalisation.CRIST.api.model.CRISTUserAction) */ @SuppressWarnings("unchecked") @Override public ArrayList<CRISTUserAction> predictUserIntent(IIdentity entityID, CRISTUserAction userAction) { // null paras are already handled in Prediction class /* * if (entityID == null) { * LOG.error("The entityID is null, getCRISTPrediction can not run."); * return new ArrayList<CRISTUserAction>(); } if (userAction == null) { * LOG.error("The action is null, getCRISTPrediction can not run."); * return new ArrayList<CRISTUserAction>(); } */ // Update the given user's current action, // put method is already has the function of replace /* * if (this.currentUserActionMap.containsKey(entityID)) { * this.currentUserActionMap.remove(entityID); } */ this.currentUserActionMap.put(entityID, userAction); // update the current situation for current context list in DB CRISTUserSituation currentUserSituation = inferUserSituation(entityID); if (currentUserSituation != null) { this.currentUserSituationMap.put(entityID, currentUserSituation); // update local historyList. how about ctxDB? here do not store to DB, ua do. this.historyList.add(new CRISTHistoryData(userAction, currentUserSituation)); if (this.intentModel == null || historyList.size() % UPDATE_TRIGGER_THRESHOLD == 0) { // update intent model if (cristDiscovery == null) { LOG.info("The CRIST Discovery is NULL. "); return new ArrayList<CRISTUserAction>(); } // this.cristDiscovery.enableCRISTUIDiscovery(true); // control the max length of history list: if (historyList.size() > MAX_HISTORY_LENGTH + UPDATE_TRIGGER_THRESHOLD){ historyList.subList(0, UPDATE_TRIGGER_THRESHOLD).clear(); } //@@@ // Logging for test m = new PerformanceMessage(); m.setTestContext("Personalisation.CRISTUserIntent.HistoryList.Size"); m.setSourceComponent(this.getClass()+""); m.setOperationType("IntentModelLearningFromActionHistory");//? m.setD82TestTableName("S18"); m.setPerformanceType(IPerformanceMessage.Quanitative); m.setPerformanceNameValue("Size=" + historyList.size()); //LOG.info("#1#This is a test log for PerformanceMessage S18!"); PERF_LOG.trace(m.toString()); m = new PerformanceMessage(); m.setTestContext("Personalisation.CRISTUserIntent.ModelLearning.Delay"); m.setSourceComponent(this.getClass()+""); m.setOperationType("IntentModelLearningFromActionHistory");//? m.setD82TestTableName("S18"); m.setPerformanceType(IPerformanceMessage.Delay); long startTime = System.currentTimeMillis(); //@@@ tested method this.intentModel = this.cristDiscovery .generateNewCRISTUIModel(this.historyList);// ensure not // return // null m.setPerformanceNameValue("Delay=" + (System.currentTimeMillis()-startTime)); PERF_LOG.trace(m.toString()); //Logging end //@@@ } return getNextActions(entityID, userAction, currentUserSituation); } else { LOG.info("currentUserSituation is null."); } // When currentUserSituation == null return new ArrayList<CRISTUserAction>(); } /* * (non-Javadoc) * able to return null * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #getCurrentUserIntent(org.societies.api.identity.IIdentity, * org.societies. * api.schema.servicelifecycle.model.ServiceResourceIdentifier, * java.lang.String) */ @SuppressWarnings("unchecked") @Override public CRISTUserAction getCurrentUserIntent(IIdentity entityID, ServiceResourceIdentifier serviceID, String parameterName) { CRISTUserAction predictedUserAction = null; CRISTUserAction currentUserAction = null; CRISTUserSituation currentUserSituation = null; //why not get from historylist? how to keep historylist updated? currentUserAction = this.currentUserActionMap.get(entityID); currentUserSituation = this.currentUserSituationMap.get(entityID); if (currentUserAction == null) { currentUserAction = retrieveCurrentUserAction(); if (currentUserAction == null) { LOG.info("currentUserAction is null, and no history action."); return null; } currentUserActionMap.put(entityID, currentUserAction); } if (currentUserSituation == null) { currentUserSituation = inferUserSituation(entityID); currentUserSituationMap.put(entityID, currentUserSituation); } if (this.intentModel == null) { // create intent model if (cristDiscovery == null) { LOG.info("The CRIST Discovery is NULL. "); return new CRISTUserAction(); } // this.cristDiscovery.enableCRISTUIDiscovery(true); //@@@ // Logging for test m = new PerformanceMessage(); m.setTestContext("Personalisation.CRISTUserIntent.HistoryList.Size"); m.setSourceComponent(this.getClass()+""); m.setOperationType("IntentModelLearningFromActionHistory");//? m.setD82TestTableName("S18"); m.setPerformanceType(IPerformanceMessage.Quanitative); m.setPerformanceNameValue("Size=" + historyList.size()); //LOG.info("#3#This is a test log for PerformanceMessage S18!"); PERF_LOG.trace(m.toString()); m = new PerformanceMessage(); m.setTestContext("Personalisation.CRISTUserIntent.ModelLearning.Delay"); m.setSourceComponent(this.getClass()+""); m.setOperationType("IntentModelLearningFromActionHistory");//? m.setD82TestTableName("S18"); m.setPerformanceType(IPerformanceMessage.Delay); long startTime = System.currentTimeMillis(); //@@@ tested method this.intentModel = this.cristDiscovery .generateNewCRISTUIModel(this.historyList); m.setPerformanceNameValue("Delay=" + (System.currentTimeMillis()-startTime)); PERF_LOG.trace(m.toString()); //Logging end //@@@ } if (currentUserAction != null && currentUserSituation != null && intentModel != null) { ArrayList<CRISTUserAction> results = getNextActions(entityID, currentUserAction, currentUserSituation); ServiceResourceIdentifier currentServiceID = null; String currentParameterName = null; for (int i = 0; i < results.size(); i++) { currentServiceID = results.get(i).getServiceID(); currentParameterName = results.get(i).getparameterName(); if (currentServiceID.equals(serviceID) && currentParameterName.equalsIgnoreCase(parameterName)) { predictedUserAction = results.get(i); break; } } } return predictedUserAction; } /* * (non-Javadoc) * ensure not return null * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #getNextActions(org.societies.personalisation.CRIST * .api.model.CRISTUserAction) */ @Override public ArrayList<CRISTUserAction> getNextActions(IIdentity entityID, // this // para // isn't // used CRISTUserAction currentAction, CRISTUserSituation currentSituation) { // null paras are handled in predictUserIntent method if (currentAction == null || currentSituation == null) { LOG.info("action or situation is null."); return new ArrayList<CRISTUserAction>(); } String actionID = currentAction.getActionID();// ensure do not return // null ArrayList<CRISTUserAction> predictedAction = new ArrayList<CRISTUserAction>(); HashMap<String, Integer> predictionResult = new HashMap<String, Integer>(); String currentPrediction = ""; Integer totalScore = 0; /* * update intent model locally, and do not store in DB. if * (this.intentModel == null) { // TODO: Retrieve intent model from * CtxBroker * LOG.info("Trying to retrieve the user's intent model from CtxBroker..." * ); // this.ctxBroker.retrieveCRISTUIModel(entityID); * * if (this.intentModel == null) { // In case there is no intent model * on the CtxBroker, generate a // new model // TODO: Retrieve the * user's history data from CtxBroker // this.historyList = * this.ctxBroker.retrieveHistory(entiryID); ArrayList<CRISTHistoryData> * historyData = this.historyList; * * this.cristDiscovery.enableCRISTUIDiscovery(true); this.intentModel = * this.cristDiscovery .generateNewCRISTUIModel(historyData); // TODO: * Upload the new intentModel to the CtxBroker } } */ // Get the next actions LinkedHashMap<String, Integer> candidateAction = new LinkedHashMap<String, Integer>(); if (currentSituation != null && currentSituation.toString().length() > 0) { // In case the user's current situation is available String situationValue = currentSituation.getSituationID(); String currentBehavior = actionID + "@" + situationValue; Set<String> modelKeys = this.intentModel.keySet(); Object[] keyArray = modelKeys.toArray(); for (int i = 0; i < keyArray.length; i++) { if (keyArray[i].toString().startsWith(currentBehavior)) { String oneCandidate = keyArray[i].toString().replace( currentBehavior, ""); Integer oneScore = this.intentModel.get(keyArray[i]); candidateAction.put(oneCandidate, oneScore); } } } else { // In case the user's current situation is not available, consider // all situations String currentBehavior = actionID; Set<String> modelKeys = this.intentModel.keySet(); Object[] keyArray = modelKeys.toArray(); for (int i = 0; i < keyArray.length; i++) { if (keyArray[i].toString().startsWith(currentBehavior)) { String oneCandidate = keyArray[i].toString().replace( currentBehavior, ""); oneCandidate = oneCandidate.substring( oneCandidate.indexOf('#'), oneCandidate.length()); Integer oneScore = this.intentModel.get(keyArray[i]); candidateAction.put(oneCandidate, oneScore); } } } // In case the predicted user intent action is not null if (candidateAction.size() > 0) { Set<String> candidateKeys = candidateAction.keySet(); Object[] candidateArray = candidateKeys.toArray(); for (int i = 0; i < CRISTUserIntentDiscovery.MAX_PREDICTION_STEP; i++) { LinkedHashMap<String, Integer> currentCandidate = new LinkedHashMap<String, Integer>(); for (int j = 0; j < candidateArray.length; j++) { if (candidateArray[j].toString().startsWith( currentPrediction)) { String[] candidates = candidateArray[j].toString() .substring(1).split("#"); Integer historyScore = candidateAction .get(candidateArray[j].toString()); if (candidates.length > i) { if (currentCandidate.containsKey(candidates[i])) { Integer currentScore = currentCandidate .get(candidates[i]); currentCandidate.put(candidates[i], currentScore + historyScore); } else { currentCandidate.put(candidates[i], historyScore); } } } } if (currentCandidate.size() > 0) { Set<String> currentCandidateKeys = currentCandidate .keySet(); Object[] currentCandidateArray = currentCandidateKeys .toArray(); Integer[] currentCandidateScore = new Integer[currentCandidate .size()]; for (int j = 0; j < currentCandidate.size(); j++) { currentCandidateScore[j] = currentCandidate .get(currentCandidateArray[j]); } int maxScore = 0; int maxIndex = 0; for (int j = 0; j < currentCandidateScore.length; j++) { if (currentCandidateScore[j] > maxScore) { maxScore = currentCandidateScore[j]; maxIndex = j; } } predictionResult.put( currentCandidateArray[maxIndex].toString(), maxScore); totalScore += maxScore; currentPrediction = currentPrediction + "#" + currentCandidateArray[maxIndex]; } } } if (predictionResult.size() > 0) { String[] predictionResultArray = currentPrediction.substring(1) .split("#"); for (int i = 0; i < predictionResult.size(); i++) { CRISTUserAction oneAction = new CRISTUserAction(); oneAction.setActionID(predictionResultArray[i]); // Double oneScore = // ((double)predictionResult.get(predictionResultArray[i]))/((double)totalScore); int confidenceLevel = predictionResult .get(predictionResultArray[i]); oneAction.setConfidenceLevel(confidenceLevel); predictedAction.add(oneAction); } } return predictedAction; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #getNextTasks(org.societies.personalisation.CRIST * .api.model.CRISTUserTask) */ @Override public ArrayList<CRISTUserTask> getNextTasks(CRISTUserTask arg0) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#getTask(java.lang.String) */ @Override public CRISTUserTask getTask(String arg0) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#getTaskModelData() */ @Override public CRISTUserTaskModelData getTaskModelData() { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #getTasks(org.societies.personalisation.CRIST.api.model.CRISTUserAction, * org.societies.personalisation.CRIST.api.model.CRISTUserSituation) */ @Override public ArrayList<CRISTUserTask> getTasks(CRISTUserAction arg0, CRISTUserSituation arg1) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#identifyActionTaskInModel(java.lang.String, * java.lang.String, java.util.HashMap) */ @Override public HashMap<CRISTUserAction, CRISTUserTask> identifyActionTaskInModel( String arg0, String arg1, HashMap<String, Serializable> arg2) { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#identifyActions() */ @Override public ArrayList<CRISTUserAction> identifyActions() { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#identifySituations() */ @Override public ArrayList<CRISTUserSituation> identifySituations() { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#identifyTasks() */ @Override public ArrayList<CRISTUserTask> identifyTasks() { // TODO Auto-generated method stub return null; } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager#resetTaskModelData() */ @Override public void resetTaskModelData() { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #setNextActionLink(org.societies.personalisation * .CRIST.api.model.CRISTUserAction, * org.societies.personalisation.CRIST.api.model.CRISTUserAction, * java.lang.Double) */ @Override public void setNextActionLink(CRISTUserAction arg0, CRISTUserAction arg1, Double arg2) { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #setNextSituationLink(org.societies.personalisation * .CRIST.api.model.CRISTUserSituation, * org.societies.personalisation.CRIST.api.model.CRISTUserSituation, * java.lang.Double) */ @Override public void setNextSituationLink(CRISTUserSituation arg0, CRISTUserSituation arg1, Double arg2) { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see org.societies.personalisation.CRIST.api.CRISTUserIntentTaskManager. * ICRISTUserIntentTaskManager * #setNextTaskLink(org.societies.personalisation. * CRIST.api.model.CRISTUserTask, * org.societies.personalisation.CRIST.api.model.CRISTUserTask, * java.lang.Double) */ @Override public void setNextTaskLink(CRISTUserTask arg0, CRISTUserTask arg1, Double arg2) { // TODO Auto-generated method stub } public void displayHistoryList() { System.out.println("This is the historyList: "); for (int i = 0; i < historyList.size(); i++) { System.out.println(historyList.get(i).toString()); } } public void displayIntentModel() { //System.out.println("This is the intentModel.toString(): " + intentModel.toString()); //nearly the same as below System.out.println(getCRISTUIModel(intentModel.toString()).toString()); System.out.println("This is the intentModel: "); Set<String> modelKeys = intentModel.keySet(); Object[] keyArray = modelKeys.toArray(); if (keyArray.length == 0) { System.out.println("intentModel is not null, but its length is zero."); } for (int i = 0; i < keyArray.length; i++) { System.out.println(keyArray[i].toString() + "=" + intentModel.get(keyArray[i])); } } //---------------------- for community model ------------------------- // create a community CRIST model, store in the contextDB, and return the communityCristModelCtxAttrId // may return null public CtxAttributeIdentifier createCommunityCRISTModel(IIdentity cisId) { try { CtxEntityIdentifier communityCtxEntityId; if (this.ctxBroker.retrieveCommunityEntityId(cisId) != null) { communityCtxEntityId = this.ctxBroker.retrieveCommunityEntityId(cisId).get(); } // what if no ctxEntity of this cisId in the contextDB else { System.out.println("ctxBroker.createEntity(cisId, CtxEntityTypes.COMMUNITY): " + ctxBroker.createEntity(cisId, CtxEntityTypes.COMMUNITY)); //null communityCtxEntityId = ctxBroker.createEntity(cisId, CtxEntityTypes.COMMUNITY).get().getId(); } CtxAttribute communityCristModelCtxAttr = this.ctxBroker.createAttribute(communityCtxEntityId, CtxAttributeTypes.CRIST_MODEL).get(); // what if already a CRIST_MODEL Attribute? // fill with local IndividualCRISTModel, because "The CSS who creates the CIS will be added as a member to the CIS and with the owner role." communityCristModelCtxAttr.setStringValue(intentModel.toString()); communityCristModelCtxAttr.setValueType(CtxAttributeValueType.STRING); CtxAttributeIdentifier communityCristModelCtxAttrId = communityCristModelCtxAttr.getId(); return communityCristModelCtxAttrId; } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (CtxException e) { e.printStackTrace(); } return null; } // update community CRIST model and store in the contextDB // may return null public CtxAttributeIdentifier updateCommunityCRISTModel(IIdentity cisId) { try { // retrieve CommunityCRISTModel List<CtxIdentifier> attrIds = this.ctxBroker.lookup(cisId, CtxModelType.ATTRIBUTE, CtxAttributeTypes.CRIST_MODEL).get(); // can this method lookup communityCristModelCtxAttrId? // what if attrIds == null? return createCommunityCRISTModel(cisId) CtxAttributeIdentifier communityCristModelCtxAttrId = (CtxAttributeIdentifier) attrIds.get(0); // if more than one CRIST_MODEL, only get the first one. CtxAttribute communityCristModelCtxAttr = (CtxAttribute) this.ctxBroker.retrieve(communityCristModelCtxAttrId).get(); LinkedHashMap<String, Integer> communityCRISTModel = retrieveCommunityCRISTModel(communityCristModelCtxAttrId); // merge CommunityCRISTModel and local IndividualCRISTModel for (String currentKey : intentModel.keySet()) { Integer individualScore = this.intentModel.get(currentKey); if (communityCRISTModel.containsKey(currentKey)) { communityCRISTModel.put(currentKey, individualScore + communityCRISTModel.get(currentKey)); } else { communityCRISTModel.put(currentKey, individualScore); } } // store to the contextDB communityCristModelCtxAttr.setStringValue(communityCRISTModel.toString()); communityCristModelCtxAttrId = (CtxAttributeIdentifier) this.ctxBroker.update(communityCristModelCtxAttr).get().getId(); return communityCristModelCtxAttrId; } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CtxException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } // merge Community CRIST Model with local Individual CRIST Model to a new Individual model, under the permission from the user. public void updateIndividualCRISTModelWithCommunity(IIdentity cisId) { try { // retrieve CommunityCRISTModel List<CtxIdentifier> attrIds = this.ctxBroker.lookup(cisId, CtxModelType.ATTRIBUTE, CtxAttributeTypes.CRIST_MODEL).get(); // can this method lookup communityCristModelCtxAttrId? // what if attrIds == null? return createCommunityCRISTModel(cisId) CtxAttributeIdentifier communityCristModelCtxAttrId = (CtxAttributeIdentifier) attrIds.get(0); // if more than one CRIST_MODEL, only get the first one. LinkedHashMap<String, Integer> communityCRISTModel = retrieveCommunityCRISTModel(communityCristModelCtxAttrId); // merge CommunityCRISTModel and local IndividualCRISTModel to a new local IndividualCRISTModel for (String currentKey : communityCRISTModel.keySet()) { Integer communityScore = communityCRISTModel.get(currentKey); if (this.intentModel.containsKey(currentKey)) { this.intentModel.put(currentKey, (int)Math.ceil(communityScore * COMMUNITY_MODEL_WEIGHT) + this.intentModel.get(currentKey)); } else { this.intentModel.put(currentKey, (int)Math.ceil(communityScore * COMMUNITY_MODEL_WEIGHT)); } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CtxException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // retrieve community CRIST model from the contextDB // may return null //ctxAttribute or ctxAttributeIdentifier is unique, related with its CtxEntity, not like ctxAttributeType, which is not unique. public LinkedHashMap<String, Integer> retrieveCommunityCRISTModel(CtxAttributeIdentifier communityCristModelCtxAttrId) { try { Future<CtxModelObject> ctxAttributeRetrievedStringFuture = this.ctxBroker .retrieve(communityCristModelCtxAttrId); CtxAttribute retrievedCtxAttribute = (CtxAttribute) ctxAttributeRetrievedStringFuture .get(); return getCRISTUIModel(getValue(retrievedCtxAttribute)); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (CtxException e) { e.printStackTrace(); } return null; } private LinkedHashMap<String, Integer> getCRISTUIModel(String UIModelString){ LinkedHashMap<String, Integer> UIModel = new LinkedHashMap<String, Integer>(); // UIModelString = {STARTING_ACTION@RoomA#http://testService_MyTV: TVService: channel: 1=1, http://testService_MyTV: TVService: channel: 1@RoomB#http://testService_MyTV: TVService: channel: 2=5, http://testService_MyTV: TVService: channel: 2@RoomA#http://testService_MyTV: TVService: channel: 1=4, http://testService_MyTV: TVService: channel: 2@RoomA#http://testService_MyTV: TVService: channel: 2=1, http://testService_MyTV: TVService: channel: 2@RoomB#http://testService_MyTV: TVService: channel: 1=5, http://testService_MyTV: TVService: channel: 1@RoomA#http://testService_MyTV: TVService: channel: 2=4} String UIModelString_clean = UIModelString.substring(1, UIModelString.length()-1); // no {...} String[] itemString = UIModelString_clean.split(", "); for (int i = 0; i < itemString.length; i++) { // itemString[0] = STARTING_ACTION@RoomA#http://testService_MyTV: TVService: channel: 1=1 int indexOfEqual = itemString[i].indexOf('='); UIModel.put(itemString[i].substring(0, indexOfEqual), Integer.parseInt(itemString[i].substring(indexOfEqual+1))); } return UIModel; } }