/** * Copyright (c) 2011, SOCIETIES Consortium (WATERFORD INSTITUTE OF TECHNOLOGY (TSSG), HERIOT-WATT UNIVERSITY (HWU), SOLUTA.NET * (SN), GERMAN AEROSPACE CENTRE (Deutsches Zentrum fuer Luft- und Raumfahrt e.V.) (DLR), Zavod za varnostne tehnologije * informacijske družbe in elektronsko poslovanje (SETCCE), INSTITUTE OF COMMUNICATION AND COMPUTER SYSTEMS (ICCS), LAKE * COMMUNICATIONS (LAKE), INTEL PERFORMANCE LEARNING SOLUTIONS LTD (INTEL), PORTUGAL TELECOM INOVAÇÃO, SA (PTIN), IBM Corp., * INSTITUT TELECOM (ITSUD), AMITEC DIACHYTI EFYIA PLIROFORIKI KAI EPIKINONIES ETERIA PERIORISMENIS EFTHINIS (AMITEC), TELECOM * ITALIA S.p.a.(TI), TRIALOG (TRIALOG), Stiftelsen SINTEF (SINTEF), NEC EUROPE LTD (NEC)) * 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.useragent.monitoring; import java.io.IOException; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.societies.api.context.CtxException; 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.CtxEntity; 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.internal.context.broker.ICtxBroker; import org.societies.api.internal.context.model.CtxAssociationTypes; import org.societies.api.internal.context.model.CtxAttributeTypes; import org.societies.api.internal.context.model.CtxEntityTypes; import org.societies.api.internal.servicelifecycle.ServiceModelUtils; import org.societies.api.personalisation.model.IAction; import org.societies.api.schema.servicelifecycle.model.ServiceResourceIdentifier; public class ContextCommunicator { private static Logger LOG = LoggerFactory.getLogger(ContextCommunicator.class); ICtxBroker ctxBroker; SnapshotManager snpshtMgr; Hashtable<String, CtxAttributeIdentifier> mappings; public ContextCommunicator(ICtxBroker ctxBroker, IIdentity myCssID){ this.ctxBroker = ctxBroker; snpshtMgr = new SnapshotManager(ctxBroker, myCssID); mappings = new Hashtable<String, CtxAttributeIdentifier>(); //quick lookup for serviceId.paramName -> ctxAttrIdentifier } public void updateHistory(IIdentity owner, IAction action){ //check cache first for ctxAttrIdentifier to update ServiceResourceIdentifier serviceID = action.getServiceID(); String parameterName = action.getparameterName(); String key = serviceID+"|"+parameterName; if(mappings.containsKey(key)){ //already has service attribute LOG.debug("Mapping exists for key: "+key); //update attribute CtxAttributeIdentifier attrID = mappings.get(key); try { ctxBroker.updateAttribute(attrID, SerialisationHelper.serialise(action)); } catch (CtxException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }else{ LOG.debug("Mapping doesn't yet exist for key: "+key); //check context second for ctx attribute to update try { //get cssOperator (Person) IndividualCtxEntity cssOperator = ctxBroker.retrieveIndividualEntity(owner).get(); if(cssOperator != null){ LOG.debug("Retrieved PERSON entity with ID: "+cssOperator.getId()); //get USES_SERVICE associations for this person entity Set<CtxAssociationIdentifier> usesServiceAssocIDs = cssOperator.getAssociations(CtxAssociationTypes.USES_SERVICES); if(usesServiceAssocIDs.size() > 0){ //USES_SERVICE associations found! LOG.debug("Found USES_SERVICES association under PERSON entity"); CtxAssociation usesServiceAssoc = (CtxAssociation)ctxBroker.retrieve(usesServiceAssocIDs.iterator().next()).get(); //Get SERVICE entities under USES_SERVICE association Set<CtxEntityIdentifier> serviceEntityIDs = usesServiceAssoc.getChildEntities(); //find SERVICE entity with correct ID List<CtxEntityIdentifier> serviceEntityIDsList = new ArrayList<CtxEntityIdentifier>(serviceEntityIDs); List<CtxEntityIdentifier> returnedServiceIDs = ctxBroker.lookupEntities(serviceEntityIDsList, CtxAttributeTypes.ID, ServiceModelUtils.serviceResourceIdentifierToString(serviceID)).get(); if(returnedServiceIDs.size() > 0){ //SERVICE entity with this serviceID found! LOG.debug("Found SERVICE entity with serviceID: "+serviceID); CtxEntity serviceEntity = (CtxEntity)ctxBroker.retrieve(returnedServiceIDs.get(0)).get(); //Get HAS_PARAMETER associations for this service entity Set<CtxAssociationIdentifier> hasParamAssocIDs = serviceEntity.getAssociations(CtxAssociationTypes.HAS_PARAMETERS); if(hasParamAssocIDs.size() > 0){ //HAS_PARAMETER associations found! LOG.debug("Found HAS_PARAMETER association under SERVICE entity"); CtxAssociation hasParamAssoc = (CtxAssociation)ctxBroker.retrieve(hasParamAssocIDs.iterator().next()).get(); //Get SERVICE_PARAMETER entities under HAS_PARAMETER association Set<CtxEntityIdentifier> paramEntityIDs = hasParamAssoc.getChildEntities(); //find SERVICE_PARAMETER entity with correct name List<CtxEntityIdentifier> paramEntityIDsList = new ArrayList<CtxEntityIdentifier>(paramEntityIDs); List<CtxEntityIdentifier> returnedParamIDs = ctxBroker.lookupEntities(paramEntityIDsList, CtxAttributeTypes.PARAMETER_NAME, parameterName).get(); if(returnedParamIDs.size() > 0){ //SERVICE_PARAMETER entity with this name found! LOG.debug("Found SERVICE_PARAMETER entity with parameterName: "+parameterName); CtxEntity parameterEntity = (CtxEntity)ctxBroker.retrieve(returnedParamIDs.get(0)).get(); //Get LAST_ACTION attribute Set<CtxAttribute> returnedAttributes = parameterEntity.getAttributes(CtxAttributeTypes.LAST_ACTION); CtxAttribute lastActionAttr = returnedAttributes.iterator().next(); //update LAST_ACTION value LOG.debug("Updating LAST_ACTION attribute with action"); ctxBroker.updateAttribute(lastActionAttr.getId(), SerialisationHelper.serialise(action)); //update mappings LOG.debug("Updating mappings table with key: "+key+" and attributeID: "+lastActionAttr.getId()); mappings.put(key, lastActionAttr.getId()); }else{ //no SERVICE_PARAMETER entity found :( //CREATING NEW SERVICE_PARAMETER //setting as child of HAS_PARAMETER association //adding PARAMETER_NAME attribute //adding LAST_ACTION attribute //adding to mappings with key createServiceParameter(key, hasParamAssoc, parameterName, action); } }else{ //no HAS_PARAMETER associations found :( //creating new HAS_PARAMETER association and setting SERVICE entity as parent CtxAssociation newHasParamAssoc = createHasParameterAssociation(serviceEntity); //creating new SERVICE_PARAMETER entity, setting as child of HAS_PARAMETER association //adding ID and PARAMETER_NAME attributes createServiceParameter(key, newHasParamAssoc, parameterName, action); } }else{ //no SERVICE entity with this serviceID found :( //creating new SERVICE entity CtxEntity newServiceEntity = createServiceEntity(usesServiceAssoc, serviceID); //creating new HAS_PARAMETER association and setting service entity as parent CtxAssociation newHasParamAssoc = createHasParameterAssociation(newServiceEntity); //creating new SERVICE_PARAMETER entity, setting as child of HAS_PARAMETER association //adding ID and PARAMETER_NAME attributes createServiceParameter(key, newHasParamAssoc, parameterName, action); } }else{ //no USES_SERVICE associations found :( //creating new USE_SERVICE ASSOCATION CtxAssociation newUsesServiceAssoc = createUsesServiceAssociation(cssOperator); //creating new SERVICE entity CtxEntity newServiceEntity = createServiceEntity(newUsesServiceAssoc, serviceID); //creating new HAS_PARAMETER association and setting service entity as parent CtxAssociation newHasParamAssoc = createHasParameterAssociation(newServiceEntity); //creating new SERVICE_PARAMETER entity, setting as child of HAS_PARAMETER association //adding ID and PARAMETER_NAME attributes createServiceParameter(key, newHasParamAssoc, parameterName, action); } }else{ LOG.error("Could not retrieve Person EntityIdentifier from JID"); } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (CtxException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } private CtxAssociation createUsesServiceAssociation(CtxEntity parent){ CtxAssociation usesServiceAssoc = null; try { //create USES_SERVICE association LOG.debug("Creating USE_SERVICES association with parent: "+parent.getType()); usesServiceAssoc = ctxBroker.createAssociation(CtxAssociationTypes.USES_SERVICES).get(); //set parent entity usesServiceAssoc.setParentEntity(parent.getId()); ctxBroker.update(usesServiceAssoc); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (CtxException e) { e.printStackTrace(); } return usesServiceAssoc; } private CtxEntity createServiceEntity(CtxAssociation usesServiceAssoc, ServiceResourceIdentifier serviceID){ CtxEntity serviceEntity = null; try { //create new SERVICE entity LOG.debug("Creating SERVICE entity and adding as child to association: "+usesServiceAssoc.getType()); serviceEntity = ctxBroker.createEntity(CtxEntityTypes.SERVICE).get(); //add as child to USES_SERVICE association usesServiceAssoc.addChildEntity(serviceEntity.getId()); ctxBroker.update(usesServiceAssoc); //create new ID attribute, update and add to entity LOG.debug("Creating ID attribute under SERVICE entity"); CtxAttribute newIDAttr = ctxBroker.createAttribute(serviceEntity.getId(), CtxAttributeTypes.ID).get(); LOG.debug("Setting value of ID attribute to: "+serviceID); ctxBroker.updateAttribute(newIDAttr.getId(), ServiceModelUtils.serviceResourceIdentifierToString(serviceID)); /*LOG.debug("Testing serialisation and deserialisation"); byte[] serialised = SerialisationHelper.serialise(serviceID); LOG.debug("SERIALISED: "+serialised); try { ServiceResourceIdentifier deserialised = (ServiceResourceIdentifier)SerialisationHelper.deserialise(serialised, this.getClass().getClassLoader()); LOG.debug("DESERIALISED: "+deserialised); } catch (ClassNotFoundException e) { e.printStackTrace(); }*/ } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (CtxException e) { e.printStackTrace(); } return serviceEntity; } private CtxAssociation createHasParameterAssociation(CtxEntity parentEntity){ CtxAssociation hasParameterAssoc = null; try { //create new HAS_PARAMETER association LOG.debug("Creating HAS_PARAMETER association with parent: "+parentEntity.getType()); hasParameterAssoc = ctxBroker.createAssociation(CtxAssociationTypes.HAS_PARAMETERS).get(); //set parent entity hasParameterAssoc.setParentEntity(parentEntity.getId()); ctxBroker.update(hasParameterAssoc); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (CtxException e) { e.printStackTrace(); } return hasParameterAssoc; } private void createServiceParameter(String key, CtxAssociation hasParameterAssoc, String parameterName, IAction lastAction){ try { //create new SERVICE_PARAMETER entity LOG.debug("Creating SERVICE_PARAMETER entity and adding as child to association: "+hasParameterAssoc.getType()); CtxEntity serviceParamEntity = ctxBroker.createEntity(CtxEntityTypes.SERVICE_PARAMETER).get(); //add as child to HAS_PARAMETER association hasParameterAssoc.addChildEntity(serviceParamEntity.getId()); ctxBroker.update(hasParameterAssoc); //create new PARAMETER_NAME attribute, update and add to entity LOG.debug("Creating PARAMETER_NAME attribute under SERVICE_PARAMETER entity with value: "+parameterName); CtxAttribute newParamAttr = ctxBroker.createAttribute(serviceParamEntity.getId(), CtxAttributeTypes.PARAMETER_NAME).get(); ctxBroker.updateAttribute(newParamAttr.getId(), parameterName); //create new LAST_ACTION attribute, update and add to entity LOG.debug("Creating LAST_ACTION attribute under SERVICE_PARAMETER entity with value: "+lastAction); CtxAttribute newLastActionAttr = ctxBroker.createAttribute(serviceParamEntity.getId(), CtxAttributeTypes.LAST_ACTION).get(); boolean completed = ctxBroker.setHistoryTuples(newLastActionAttr.getId(), snpshtMgr.getSnapshot(newLastActionAttr.getId()).getIDList()).get(); if(!completed){ LOG.error("context tuples not set for action: "+newLastActionAttr.getType()); } ctxBroker.updateAttribute(newLastActionAttr.getId(), SerialisationHelper.serialise(lastAction)); //update mappings LOG.debug("Updating mappings table with key: "+key+" and attributeID: "+newLastActionAttr.getId()); mappings.put(key, newLastActionAttr.getId()); } catch (CtxException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public void updateUID(IIdentity owner, String myDeviceID){ try { List<CtxIdentifier> attrIds = ctxBroker.lookup(CtxModelType.ATTRIBUTE, CtxAttributeTypes.UID).get(); if(attrIds.size() > 0){ //found existing UID - update CtxAttributeIdentifier uidAttrID = (CtxAttributeIdentifier)attrIds.get(0); ctxBroker.updateAttribute(uidAttrID, myDeviceID); }else{ //no existing UID - create and populate CtxEntity personEntity = ctxBroker.retrieveIndividualEntity(owner).get(); if(personEntity != null){ ctxBroker.createAttribute(personEntity.getId(), CtxAttributeTypes.UID); }else{ LOG.error("Could not retrieve Person EntityIdentifier from JID"); } } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (CtxException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }