/** * 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.context.broker.impl; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; 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.broker.CtxAccessControlException; import org.societies.api.context.event.CtxChangeEventListener; import org.societies.api.context.model.CommunityCtxEntity; import org.societies.api.context.model.CtxAssociation; 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.CtxBond; import org.societies.api.context.model.CtxEntity; import org.societies.api.context.model.CtxEntityIdentifier; import org.societies.api.context.model.CtxEvaluationResults; 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.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.IdentityType; import org.societies.api.identity.InvalidFormatException; import org.societies.api.identity.Requestor; import org.societies.api.identity.util.DataTypeUtils; import org.societies.api.internal.comm.ICISCommunicationMgrFactory; 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.logging.IPerformanceMessage; import org.societies.api.internal.logging.PerformanceMessage; import org.societies.api.internal.privacytrust.privacyprotection.model.privacyassessment.IPrivacyLogAppender; import org.societies.api.schema.privacytrust.privacy.model.privacypolicy.ActionConstants; import org.societies.context.api.community.db.ICommunityCtxDBMgr; import org.societies.context.api.community.inference.ICommunityCtxInferenceMgr; import org.societies.context.api.event.CtxChangeEventTopic; import org.societies.context.api.event.ICtxEventMgr; import org.societies.context.api.similarity.ICtxSimilarityEvaluator; import org.societies.context.api.user.db.IUserCtxDBMgr; import org.societies.context.api.user.history.IUserCtxHistoryMgr; import org.societies.context.api.user.inference.IUserCtxInferenceMgr; import org.societies.context.broker.api.CtxBrokerException; import org.societies.context.broker.api.security.ICtxAccessController; import org.societies.context.broker.impl.comm.CtxBrokerClient; import org.societies.context.broker.impl.comm.callbacks.CreateAssociationCallback; import org.societies.context.broker.impl.comm.callbacks.CreateAttributeCallback; import org.societies.context.broker.impl.comm.callbacks.CreateEntityCallback; import org.societies.context.broker.impl.comm.callbacks.LookupCallback; import org.societies.context.broker.impl.comm.callbacks.RemoveCtxCallback; import org.societies.context.broker.impl.comm.callbacks.RetrieveCommunityEntityIdCallback; import org.societies.context.broker.impl.comm.callbacks.RetrieveCtxCallback; import org.societies.context.broker.impl.comm.callbacks.RetrieveIndividualEntCallback; import org.societies.context.broker.impl.comm.callbacks.UpdateCtxCallback; import org.societies.context.broker.impl.util.CtxBrokerUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.osgi.service.ServiceUnavailableException; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; /** * Internal Context Broker Implementation * This class implements the internal context broker interfaces and orchestrates the db * management */ @Service public class InternalCtxBroker implements ICtxBroker { /** The logging facility. */ private static final Logger LOG = LoggerFactory.getLogger(InternalCtxBroker.class); /** to define a dedicated Logger for Performance Testing */ private static Logger PERF_LOG = LoggerFactory.getLogger("PerformanceMessage"); /** The event topics to create for local CSSs and CISs */ public static final String[] EVENT_TOPICS = new String[] { CtxChangeEventTopic.CREATED, CtxChangeEventTopic.UPDATED, CtxChangeEventTopic.MODIFIED, CtxChangeEventTopic.REMOVED }; /** The Comms Mgr service reference. */ @Autowired(required=true) private ICommManager commMgr; /** The Comms Mgr Factory service reference. */ @Autowired(required=true) private ICISCommunicationMgrFactory commMgrFactory; /** The privacy logging facility. */ @Autowired(required=false) private IPrivacyLogAppender privacyLogAppender; /** The Context Event Mgmt service reference. */ @Autowired(required=true) private ICtxEventMgr ctxEventMgr; /** * The User Context History Mgmt service reference. * * @see {@link #setUserCtxHistoryMgr(IUserCtxHistoryMgr)} */ @Autowired(required=true) private IUserCtxHistoryMgr userCtxHistoryMgr; /** * The User Context DB Mgmt service reference. * * @see {@link #setUserCtxDBMgr(IUserCtxDBMgr)} */ @Autowired(required=true) private IUserCtxDBMgr userCtxDBMgr; /** * The Community Context DB Mgmt service reference. * * @see {@link #setCommunityCtxDBMgr(ICommunityCtxDBMgr)} */ @Autowired(required=true) private ICommunityCtxDBMgr communityCtxDBMgr; /** * The User Inference Mgmt service reference. * * @see {@link #setUserCtxInferenceMgr(IUserCtxInferenceMgr)} */ @Autowired(required=false) private IUserCtxInferenceMgr userCtxInferenceMgr; /** * The Community Inference Mgmt service reference. * * @see {@link #setCommunityCtxInferenceMgr(ICommunityCtxInferenceMgr)} */ @Autowired(required=false) private ICommunityCtxInferenceMgr communityCtxInferenceMgr; /** * The Context Similarity Evaluator service reference. * * @see {@link #setCtxSimilarityEvaluator(ICtxSimilarityEvaluator)} */ @Autowired(required=true) private ICtxSimilarityEvaluator ctxSimilarityEval; @Autowired(required=true) private CtxBrokerClient ctxBrokerClient; /** The ICtxAccessController service reference. */ @Autowired(required=true) private ICtxAccessController ctxAccessController; /** * Instantiates the platform Context Broker in Spring. * * @param ctxBootLoader */ @Autowired(required=true) InternalCtxBroker(CtxBootLoader ctxBootLoader) { LOG.info("{} instantiated", this.getClass()); } /* * Used for JUnit testing only. */ public InternalCtxBroker() { LOG.info("{} instantiated", this.getClass()); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#createEntity(java.lang.String) */ @Override @Async public Future<CtxEntity> createEntity(final String type) throws CtxException { final Requestor requestor = this.getLocalRequestor(); final IIdentity target = this.getLocalIdentity(); return this.createEntity(requestor, target, type); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#createEntity(org.societies.api.identity.IIdentity, java.lang.String) */ @Override @Async public Future<CtxEntity> createEntity(final IIdentity target, final String type) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.createEntity(requestor, target, type); } /* * @see org.societies.api.context.broker.ICtxBroker#createEntity(org.societies.api.identity.Requestor, org.societies.api.identity.IIdentity, java.lang.String) */ @Override @Async public Future<CtxEntity> createEntity(final Requestor requestor, final IIdentity target, final String type) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (target == null) { throw new NullPointerException("target can't be null"); } if (type == null) { throw new NullPointerException("type can't be null"); } LOG.debug("createEntity: requestor={}, target={}, type={}", new Object[] { requestor, target, type }); CtxEntity result = null; if (this.isLocalId(target)) { // L O C A L if (IdentityType.CIS != target.getType()) { // U S E R // TODO Add target parameter to UserCtxDBMgr interface result = this.userCtxDBMgr.createEntity(type); } else { // C O M M U N I T Y result = this.communityCtxDBMgr.createEntity(target.getBareJid(), type); } } else { // R E M O T E final CreateEntityCallback callback = new CreateEntityCallback(); this.ctxBrokerClient.createEntity(requestor, target, type, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result = callback.getResult(); } else { throw callback.getException(); } } catch (InterruptedException ie) { throw new CtxBrokerException("Interrupted while waiting for remote createEntity: " + ie.getLocalizedMessage(), ie); } } } LOG.debug("createEntity: result={}", result); return new AsyncResult<CtxEntity>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#createIndividualEntity(org.societies.api.identity.IIdentity, java.lang.String) */ @Override @Async public Future<IndividualCtxEntity> createIndividualEntity( final IIdentity cssId, final String ownerType) throws CtxException { if (cssId == null) { throw new NullPointerException("cssId can't be null"); } if (ownerType == null) { throw new NullPointerException("ownerType can't be null"); } LOG.debug("createIndividualEntity: cssId={}, ownerType={}", cssId, ownerType); IndividualCtxEntity result = null; try { LOG.info("Creating event topics '{}' for CSS owner {}", Arrays.toString(EVENT_TOPICS), cssId); this.ctxEventMgr.createTopics(cssId, EVENT_TOPICS); LOG.info("Checking if CSS owner context entity for {} exists...", cssId); result = this.retrieveIndividualEntity(cssId).get(); if (result != null) { LOG.info("Found CSS owner context entity {}", result); } else { result = this.userCtxDBMgr.createIndividualEntity( cssId.getBareJid(), ownerType); final CtxAttribute cssIdAttr = this.userCtxDBMgr.createAttribute( result.getId(), CtxAttributeTypes.ID); this.updateAttribute(cssIdAttr.getId(), cssId.toString()); LOG.info("Created CSS owner context entity {}" + result); } } catch (Exception e) { throw new CtxBrokerException("Could not create CSS owner context entity " + cssId + ": " + e.getLocalizedMessage(), e); } LOG.debug("createIndividualEntity: result={}", result); return new AsyncResult<IndividualCtxEntity>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#createCommunityEntity(org.societies.api.identity.IIdentity) */ @Override @Async public Future<CommunityCtxEntity> createCommunityEntity(IIdentity cisId) throws CtxException { if (cisId == null) { throw new NullPointerException("cisId can't be null"); } if (!IdentityType.CIS.equals(cisId.getType())) { throw new IllegalArgumentException("cisId is not of type CIS"); } LOG.debug("createCommunityEntity: cisId={}", cisId); LOG.info("Creating event topics '{}' for CIS {}", Arrays.toString(EVENT_TOPICS), cisId); this.ctxEventMgr.createTopics(cisId, EVENT_TOPICS); final CommunityCtxEntity result = this.communityCtxDBMgr.createCommunityEntity(cisId.toString()); LOG.debug("createCommunityEntity: result={}", result); return new AsyncResult<CommunityCtxEntity>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#createCssNode(org.societies.api.identity.INetworkNode) */ @Override @Async public Future<CtxEntity> createCssNode(final INetworkNode cssNodeId) throws CtxException { if (cssNodeId == null) { throw new NullPointerException("cssNodeId can't be null"); } CtxEntity result = null; try { LOG.info("Checking if CSS node context entity {} exists...", cssNodeId); result = this.retrieveCssNode(cssNodeId).get(); if (result != null) { LOG.info("Found CSS node context entity {}", result); } else { final IIdentity cssId = this.commMgr.getIdManager().fromJid( cssNodeId.getBareJid().replace('@', '.')); // Android JIDs contain '@' instead of '.' final IndividualCtxEntity cssEnt = this.retrieveIndividualEntity(cssId).get(); if (cssEnt == null) { throw new CtxBrokerException("The IndividualCtxEntity for CSS '" + cssId + "' could not be found. Does node " + cssNodeId + " belong to a local CSS?"); } final CtxAssociation ownsCssNodesAssoc; if (cssEnt.getAssociations(CtxAssociationTypes.OWNS_CSS_NODES).isEmpty()) { ownsCssNodesAssoc = this.userCtxDBMgr.createAssociation( CtxAssociationTypes.OWNS_CSS_NODES); } else { ownsCssNodesAssoc = (CtxAssociation) this.userCtxDBMgr.retrieve( cssEnt.getAssociations(CtxAssociationTypes.OWNS_CSS_NODES).iterator().next()); } ownsCssNodesAssoc.setParentEntity(cssEnt.getId()); result = this.userCtxDBMgr.createEntity(CtxEntityTypes.CSS_NODE); ownsCssNodesAssoc.addChildEntity(result.getId()); this.userCtxDBMgr.update(ownsCssNodesAssoc); final CtxAttribute cssNodeIdAttr = this.userCtxDBMgr.createAttribute( result.getId(), CtxAttributeTypes.ID); cssNodeIdAttr.setStringValue(cssNodeId.toString()); this.userCtxDBMgr.update(cssNodeIdAttr); LOG.info("Created CSS node context entity {}", result); } } catch (Exception e) { throw new CtxBrokerException("Could not create CSS node context entity " + cssNodeId + ": " + e.getLocalizedMessage(), e); } return new AsyncResult<CtxEntity>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#createAttribute(org.societies.api.context.model.CtxEntityIdentifier, java.lang.String) */ @Override @Async public Future<CtxAttribute> createAttribute(final CtxEntityIdentifier scope, final String type) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.createAttribute(requestor, scope, type); } /* * @see org.societies.api.context.broker.ICtxBroker#createAttribute(org.societies.api.identity.Requestor, org.societies.api.context.model.CtxEntityIdentifier, java.lang.String) */ @Override @Async public Future<CtxAttribute> createAttribute(final Requestor requestor, final CtxEntityIdentifier scope, final String type) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (scope == null) { throw new NullPointerException("scope can't be null"); } if (type == null) { throw new NullPointerException("type can't be null"); } LOG.debug("createAttribute: requestor={}, scope={}, type={}", new Object[] { requestor, scope, type }); CtxAttribute result = null; // Extract target IIdentity final IIdentity target = this.extractIIdentity(scope); if (this.isLocalId(target)) { // L O C A L if (IdentityType.CIS != target.getType()) { // U S E R result = this.userCtxDBMgr.createAttribute(scope, type); } else { // C O M M U N I T Y result = this.communityCtxDBMgr.createAttribute(scope, type); } } else { // R E M O T E final CreateAttributeCallback callback = new CreateAttributeCallback(); this.ctxBrokerClient.createAttribute(requestor, target, scope, type, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result = callback.getResult(); } else { throw callback.getException(); } } catch (InterruptedException ie) { throw new CtxBrokerException("Interrupted while waiting for remote createAttribute: " + ie.getLocalizedMessage(), ie); } } } LOG.debug("createAttribute: result={}", result); return new AsyncResult<CtxAttribute>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#createAssociation(java.lang.String) */ @Override @Async public Future<CtxAssociation> createAssociation(final String type) throws CtxException { final Requestor requestor = this.getLocalRequestor(); final IIdentity target = this.getLocalIdentity(); return this.createAssociation(requestor, target, type); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#createAssociation(org.societies.api.identity.IIdentity, java.lang.String) */ @Override @Async public Future<CtxAssociation> createAssociation(final IIdentity target, final String type) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.createAssociation(requestor, target, type); } /* * @see org.societies.api.context.broker.ICtxBroker#createAssociation(org.societies.api.identity.Requestor, org.societies.api.identity.IIdentity, java.lang.String) */ @Override @Async public Future<CtxAssociation> createAssociation(final Requestor requestor, final IIdentity target, final String type) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (target == null) { throw new NullPointerException("target can't be null"); } if (type == null) { throw new NullPointerException("type can't be null"); } LOG.debug("createAssociation: requestor={}, target={}, type={}", new Object[] { requestor, target, type }); CtxAssociation result = null; if (this.isLocalId(target)) { // L O C A L if (IdentityType.CIS != target.getType()) { // U S E R // TODO Add target parameter to UserCtxDBMgr interface result = this.userCtxDBMgr.createAssociation(type); } else { // C O M M U N I T Y result = this.communityCtxDBMgr.createAssociation(target.getBareJid(), type); } } else { // R E M O T E final CreateAssociationCallback callback = new CreateAssociationCallback(); this.ctxBrokerClient.createAssociation(requestor, target, type, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result = callback.getResult(); } else { throw callback.getException(); } } catch (InterruptedException ie) { throw new CtxBrokerException("Interrupted while waiting for remote createAssociation: " + ie.getLocalizedMessage(), ie); } } } LOG.debug("createAssociation: result={}", result); return new AsyncResult<CtxAssociation>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#lookup(org.societies.api.context.model.CtxModelType, java.lang.String) */ @Override @Async public Future<List<CtxIdentifier>> lookup(final CtxModelType modelType, String type) throws CtxException { final Requestor requestor = this.getLocalRequestor(); final IIdentity target = this.getLocalIdentity(); return this.lookup(requestor, target, modelType, type); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#lookup(org.societies.api.identity.IIdentity, java.lang.String) */ @Override public Future<List<CtxIdentifier>> lookup(final IIdentity target, final String type) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.lookup(requestor, target, type); } /* * @see org.societies.api.context.broker.ICtxBroker#lookup(org.societies.api.identity.Requestor, org.societies.api.identity.IIdentity, java.lang.String) */ @Override public Future<List<CtxIdentifier>> lookup(final Requestor requestor, final IIdentity target, final String type) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (target == null) { throw new NullPointerException("target can't be null"); } if (type == null) { throw new NullPointerException("type can't be null"); } LOG.debug("lookup: requestor={}, target={}, type={}", new Object[] { requestor, target, type }); final List<CtxIdentifier> result = new ArrayList<CtxIdentifier>(); if (this.isLocalId(target)) { // L O C A L // Retrieve sub-types final Set<String> subTypes = new DataTypeUtils().getLookableDataTypes(type); LOG.debug("lookup: type={}, subTypes={}", type, subTypes); if (IdentityType.CIS != target.getType()) { // U S E R result.addAll(this.userCtxDBMgr.lookup(target.getBareJid(), subTypes)); } else { // C O M M U N I T Y result.addAll(this.communityCtxDBMgr.lookup(target.getBareJid(), subTypes)); } } else { // R E M O T E final LookupCallback callback = new LookupCallback(); this.ctxBrokerClient.lookup(requestor, target, null, type, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result.addAll(callback.getResult()); } else { throw callback.getException(); } } catch (InterruptedException e) { throw new CtxBrokerException("Interrupted while waiting for remote lookup response"); } } } LOG.debug("lookup: result={}", result); return new AsyncResult<List<CtxIdentifier>>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#lookup(org.societies.api.identity.IIdentity, org.societies.api.context.model.CtxModelType, java.lang.String) */ @Override @Async public Future<List<CtxIdentifier>> lookup(final IIdentity target, final CtxModelType modelType, final String type) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.lookup(requestor, target, modelType, type); } /* * @see org.societies.api.context.broker.ICtxBroker#lookup(org.societies.api.identity.Requestor, org.societies.api.identity.IIdentity, org.societies.api.context.model.CtxModelType, java.lang.String) */ @Override @Async public Future<List<CtxIdentifier>> lookup(final Requestor requestor, final IIdentity target, final CtxModelType modelType, final String type) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (target == null) { throw new NullPointerException("target can't be null"); } if (modelType == null) { throw new NullPointerException("modelType can't be null"); } if (type == null) { throw new NullPointerException("type can't be null"); } LOG.debug("lookup: requestor={}, target={}, modelType={}, type={}", new Object[] { requestor, target, modelType, type }); final List<CtxIdentifier> result = new ArrayList<CtxIdentifier>(); if (this.isLocalId(target)) { final Set<String> types = new HashSet<String>(); types.add(type); // L O C A L if (IdentityType.CIS != target.getType()) { // U S E R result.addAll(this.userCtxDBMgr.lookup(target.getBareJid(), modelType, types)); } else { // C O M M U N I T Y result.addAll(this.communityCtxDBMgr.lookup(target.getBareJid(), modelType, types)); } } else { // R E M O T E final LookupCallback callback = new LookupCallback(); this.ctxBrokerClient.lookup(requestor, target, modelType, type, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result.addAll(callback.getResult()); } else { throw callback.getException(); } } catch (InterruptedException e) { throw new CtxBrokerException("Interrupted while waiting for remote lookup"); } } } LOG.debug("lookup: result={}", result); return new AsyncResult<List<CtxIdentifier>>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#lookup(org.societies.api.context.model.CtxEntityIdentifier, org.societies.api.context.model.CtxModelType, java.lang.String) */ @Override @Async public Future<List<CtxIdentifier>> lookup(final CtxEntityIdentifier scope, final CtxModelType modelType, final String type) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.lookup(requestor, scope, modelType, type); } /* * @see org.societies.api.context.broker.ICtxBroker#lookup(org.societies.api.identity.Requestor, org.societies.api.context.model.CtxEntityIdentifier, org.societies.api.context.model.CtxModelType, java.lang.String) */ @Override @Async public Future<List<CtxIdentifier>> lookup(final Requestor requestor, final CtxEntityIdentifier scope, final CtxModelType modelType, final String type) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (scope == null) { throw new NullPointerException("scope can't be null"); } if (modelType == null) { throw new NullPointerException("modelType can't be null"); } if (type == null) { throw new NullPointerException("type can't be null"); } if (!CtxModelType.ATTRIBUTE.equals(modelType) && !CtxModelType.ASSOCIATION.equals(modelType)) { throw new IllegalArgumentException("modelType is not ATTRIBUTE or ASSOCIATION"); } LOG.debug("lookup: requestor={}, scope={}, modelType={}, type={}", new Object[] { requestor, scope, modelType, type }); final List<CtxIdentifier> result = new ArrayList<CtxIdentifier>(); // Extract target IIdentity final IIdentity target = this.extractIIdentity(scope); if (this.isLocalId(target)) { final Set<String> types = new HashSet<String>(); types.add(type); // L O C A L if (IdentityType.CIS != target.getType()) { // U S E R result.addAll(this.userCtxDBMgr.lookup(scope, modelType, types)); } else { // C O M M U N I T Y result.addAll(this.communityCtxDBMgr.lookup(scope, modelType, types)); } } else { // R E M O T E final LookupCallback callback = new LookupCallback(); this.ctxBrokerClient.lookup(requestor, scope, modelType, type, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result.addAll(callback.getResult()); } else { throw callback.getException(); } } catch (InterruptedException e) { throw new CtxBrokerException("Interrupted while waiting for remote lookup"); } } } LOG.debug("lookup: result={}", result); return new AsyncResult<List<CtxIdentifier>>(result); } @Override @Async public Future<List<CtxEntityIdentifier>> lookupEntities(String entityType, String attribType, Serializable minAttribValue, Serializable maxAttribValue) throws CtxException { return this.lookupEntities(null, null, entityType, attribType, minAttribValue, maxAttribValue); } @Override @Async public Future<List<CtxEntityIdentifier>> lookupEntities(List<CtxEntityIdentifier> ctxEntityIDList, String ctxAttributeType, Serializable value){ List<CtxEntityIdentifier> entityList = new ArrayList<CtxEntityIdentifier>(); try { for(CtxEntityIdentifier entityId :ctxEntityIDList){ CtxEntity entity = (CtxEntity) this.retrieve(entityId).get(); Set<CtxAttribute> ctxAttrSet = entity.getAttributes(ctxAttributeType); for(CtxAttribute ctxAttr : ctxAttrSet){ if(CtxBrokerUtils.compareAttributeValues(ctxAttr,value)) { entityList.add(entityId); } } } } 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 new AsyncResult<List<CtxEntityIdentifier>>(entityList); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#retrieveIndividualEntity(org.societies.api.identity.IIdentity) */ @Override @Async public Future<IndividualCtxEntity> retrieveIndividualEntity( final IIdentity cssId) throws CtxException { if (cssId == null) { throw new NullPointerException("cssId can't be null"); } LOG.debug("retrieveIndividualEntity: cssId={}", cssId); this.logRequest(null, cssId); final IndividualCtxEntity result = this.userCtxDBMgr.retrieveIndividualEntity(cssId.getBareJid()); LOG.debug("retrieveIndividualEntity: result={}", result); return new AsyncResult<IndividualCtxEntity>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#retrieveCssOperator() */ @Override @Async @Deprecated public Future<IndividualCtxEntity> retrieveCssOperator() throws CtxException { LOG.debug("retrieveCssOperator"); final IIdentity localCssId = this.getLocalIdentity(); return this.retrieveIndividualEntity(localCssId); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#retrieveCssNode(org.societies.api.identity.INetworkNode) */ @Override @Async public Future<CtxEntity> retrieveCssNode(final INetworkNode cssNodeId) throws CtxException { if (cssNodeId == null) { throw new NullPointerException("cssNodeId can't be null"); } LOG.debug("retrieveCssNode: cssNodeId={}", cssNodeId); CtxEntity result = null; final List<CtxEntityIdentifier> entIds = this.userCtxDBMgr.lookupEntities( CtxEntityTypes.CSS_NODE, CtxAttributeTypes.ID, cssNodeId.toString(), cssNodeId.toString()); if (!entIds.isEmpty()) { try { result = (CtxEntity) this.retrieve(entIds.get(0)).get(); } catch (Exception e) { throw new CtxBrokerException("Failed to retrieve CSS node context entity " + cssNodeId + ": " + e.getLocalizedMessage(), e); } } LOG.debug("retrieveCssNode: result={}", result); return new AsyncResult<CtxEntity>(result); } private void storeHoc(CtxModelObject ctxModelObj) throws CtxException { // ********************** HISTORY CODE ******************************* // this part allows the storage of attribute updates to context history if (CtxModelType.ATTRIBUTE.equals(ctxModelObj.getModelType())) { final CtxAttribute ctxAttr = (CtxAttribute) ctxModelObj; try { if (ctxAttr.isHistoryRecorded() && this.userCtxHistoryMgr != null){ this.userCtxHistoryMgr.storeHoCAttribute(ctxAttr); } } catch (ServiceUnavailableException sue) { throw new CtxBrokerException("Could not update Context History: " + "Context History Mgr is not available"); } } } // ********************** HISTORY CODE *******************************end of hoc code @Override @Async public Future<CtxAttribute> updateAttribute( CtxAttributeIdentifier attributeId, Serializable value) throws CtxException { return this.updateAttribute(attributeId, value, null); } @Override @Async public Future<CtxAttribute> updateAttribute( CtxAttributeIdentifier attributeId, Serializable value, String valueMetric) throws CtxException { if (attributeId == null) throw new NullPointerException("attributeId can't be null"); // Will throw IllegalArgumentException if value type is not supported final CtxAttributeValueType valueType = CtxBrokerUtils.findAttributeValueType(value); final CtxAttribute attributeReturn ; final CtxAttribute currentAttribute ; try { currentAttribute = this.retrieveAttribute(attributeId, false).get(); //CtxAttribute attribute = (CtxAttribute) this.userCtxDBMgr.retrieve(attributeId); if (currentAttribute == null) { // Requested attribute not found return new AsyncResult<CtxAttribute>(null); } else { if (CtxAttributeValueType.EMPTY.equals(valueType)) currentAttribute.setStringValue(null); else if (CtxAttributeValueType.STRING.equals(valueType)) currentAttribute.setStringValue((String) value); else if (CtxAttributeValueType.INTEGER.equals(valueType)) currentAttribute.setIntegerValue((Integer) value); else if (CtxAttributeValueType.DOUBLE.equals(valueType)) currentAttribute.setDoubleValue((Double) value); else if (CtxAttributeValueType.BINARY.equals(valueType)){ currentAttribute.setBinaryValue((byte[]) value); currentAttribute.setValueType(valueType); } else throw new CtxBrokerException("unkown type of attribute value"); } attributeReturn = (CtxAttribute) this.update(currentAttribute).get(); String valueString = CtxBrokerUtils.attributeValueAsString(value); LOG.info("Context UPDATE performed for context ID:"+attributeReturn.getId()+" of type:"+attributeReturn.getType()+" with value:" + valueString); } catch (InterruptedException e) { throw new CtxBrokerException("updateAttribute including value failed " + e.getLocalizedMessage()); } catch (ExecutionException e) { throw new CtxBrokerException("updateAttribute including value failed " + e.getLocalizedMessage()); } return new AsyncResult<CtxAttribute>(attributeReturn); } //*********************************************** // Context Change Events Methods //*********************************************** /* * @see org.societies.api.internal.context.broker.ICtxBroker#registerForChanges(org.societies.api.context.event.CtxChangeEventListener, org.societies.api.identity.IIdentity) */ @Override public void registerForChanges(final CtxChangeEventListener listener, final IIdentity ownerId) throws CtxException { if (listener == null) { throw new NullPointerException("listener can't be null"); } if (ownerId == null) { throw new NullPointerException("ownerId can't be null"); } LOG.debug("registerForChanges: listener={}, ownerId={}", listener, ownerId); final String[] topics = new String[] { CtxChangeEventTopic.CREATED, CtxChangeEventTopic.UPDATED, CtxChangeEventTopic.MODIFIED, CtxChangeEventTopic.REMOVED, }; if (this.ctxEventMgr != null) { LOG.info("Registering context change event listener '{}' for IIdentity '{}'" + " to topics '{}'", new Object[] { listener, ownerId, Arrays.toString(topics) }); this.ctxEventMgr.registerChangeListener(listener, topics, ownerId); } else { throw new CtxBrokerException("ICtxEventMgr service is not available"); } } /* * @see org.societies.api.internal.context.broker.ICtxBroker#unregisterFromChanges(org.societies.api.context.event.CtxChangeEventListener, org.societies.api.identity.IIdentity) */ @Override public void unregisterFromChanges(final CtxChangeEventListener listener, final IIdentity ownerId) throws CtxException { if (listener == null) { throw new NullPointerException("listener can't be null"); } if (ownerId == null) { throw new NullPointerException("ownerId can't be null"); } LOG.debug("unregisterFromChanges: listener={}, ownerId={}", listener, ownerId); final String[] topics = new String[] { CtxChangeEventTopic.CREATED, CtxChangeEventTopic.UPDATED, CtxChangeEventTopic.MODIFIED, CtxChangeEventTopic.REMOVED, }; if (this.ctxEventMgr != null) { LOG.info("Unregistering context change event listener '{}' for IIdentity '{}'" + " from topics '{}'", new Object[] { listener, ownerId, Arrays.toString(topics) }); this.ctxEventMgr.unregisterChangeListener(listener, topics, ownerId); } else { throw new CtxBrokerException("ICtxEventMgr service is not available"); } } /* * @see org.societies.api.context.broker.ICtxBroker#registerForChanges(org.societies.api.context.event.CtxChangeEventListener, org.societies.api.context.model.CtxIdentifier) */ @Override public void registerForChanges(final CtxChangeEventListener listener, final CtxIdentifier ctxId) throws CtxException { final Requestor requestor = this.getLocalRequestor(); this.registerForChanges(requestor, listener, ctxId); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#unregisterFromChanges(org.societies.api.context.event.CtxChangeEventListener, org.societies.api.context.model.CtxIdentifier) */ @Override public void unregisterFromChanges(final CtxChangeEventListener listener, final CtxIdentifier ctxId) throws CtxException { final Requestor requestor = this.getLocalRequestor(); this.unregisterFromChanges(requestor, listener, ctxId); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#registerForChanges(org.societies.api.context.event.CtxChangeEventListener, org.societies.api.context.model.CtxEntityIdentifier, java.lang.String) */ @Override public void registerForChanges(final CtxChangeEventListener listener, final CtxEntityIdentifier scope, final String attrType) throws CtxException { final Requestor requestor = this.getLocalRequestor(); this.registerForChanges(requestor, listener, scope, attrType); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#unregisterFromChanges(org.societies.api.context.event.CtxChangeEventListener, org.societies.api.context.model.CtxEntityIdentifier, java.lang.String) */ @Override public void unregisterFromChanges(final CtxChangeEventListener listener, final CtxEntityIdentifier scope, final String attrType) throws CtxException { final Requestor requestor = this.getLocalRequestor(); this.unregisterFromChanges(requestor, listener, scope, attrType); } //*********************************************** // Context Inference Methods //*********************************************** @Override @Async public Future<List<CtxAttribute>> retrieveFuture( CtxAttributeIdentifier attrId, Date date) throws CtxException { LOG.debug("retrieveFuture: attrId={}, date={}", attrId, date); final IIdentity target = this.extractIIdentity(attrId); this.logRequest(null, target); final List<CtxAttribute> result = new ArrayList<CtxAttribute>(); if (this.isLocalId(target)) { // L O C A L if (IdentityType.CIS != target.getType()) { // U S E R result.add(this.userCtxInferenceMgr.predictContext(attrId, date)); } else { // C O M M U N I T Y result.add(this.communityCtxInferenceMgr.predictContext(attrId, date)); } } LOG.debug("retrieveFuture: result={}", result); return new AsyncResult<List<CtxAttribute>>(result); } @Override @Async public Future<List<CtxAttribute>> retrieveFuture( CtxAttributeIdentifier attrId, int modificationIndex) throws CtxException { LOG.debug("retrieveFuture: attrId={}, modificationIndex={}", attrId, modificationIndex); final IIdentity target = this.extractIIdentity(attrId); this.logRequest(null, target); final List<CtxAttribute> result = new ArrayList<CtxAttribute>(); Date date = new Date(); try { result.addAll(this.retrieveFuture(attrId, date).get()); } catch (Exception e) { LOG.error("Exception on predicting context attribute :"+attrId+". "+ e.getLocalizedMessage()); e.printStackTrace(); } LOG.debug("retrieveFuture: result={}", result); return new AsyncResult<List<CtxAttribute>>(result); } //*********************************************** // Community Context Management Methods //*********************************************** @Override @Async public Future<CtxEntityIdentifier> retrieveCommunityEntityId( final IIdentity cisId) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.retrieveCommunityEntityId(requestor, cisId); } @Override @Async public Future<List<CtxEntityIdentifier>> retrieveCommunityMembers( CtxEntityIdentifier communityId) throws CtxException { List<CtxEntityIdentifier> result = null; if (communityId == null) throw new NullPointerException("communityId can't be null"); try { final CommunityCtxEntity communityEntity = (CommunityCtxEntity) this.retrieve(communityId).get(); Set<CtxEntityIdentifier> commMembersSet = communityEntity.getMembers(); result = new ArrayList<CtxEntityIdentifier>(commMembersSet); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new AsyncResult<List<CtxEntityIdentifier>>(result); } @Override @Async public Future<List<CtxEntityIdentifier>> retrieveParentCommunities( CtxEntityIdentifier community) throws CtxException { // TODO Auto-generated method stub return null; } @Override @Async public Future<List<CtxEntityIdentifier>> retrieveSubCommunities( CtxEntityIdentifier community) throws CtxException { // TODO Auto-generated method stub return null; } @Override @Async public Future<IndividualCtxEntity> retrieveAdministratingCSS( CtxEntityIdentifier community) throws CtxException { // TODO Auto-generated method stub return null; } @Override @Async public Future<Set<CtxBond>> retrieveBonds(CtxEntityIdentifier community) throws CtxException { // TODO Auto-generated method stub return null; } //*********************************************** // Context History Management Methods //*********************************************** @Override @Async public Future<List<CtxHistoryAttribute>> retrieveHistory( CtxAttributeIdentifier attrId, Date startDate, Date endDate) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.retrieveHistory(requestor, attrId, startDate, endDate); } @Override @Async public Future<Integer> removeHistory(String type, Date startDate, Date endDate) throws CtxException { // TODO Auto-generated method stub return null; } @Override @Async public Future<List<CtxHistoryAttribute>> retrieveHistory( CtxAttributeIdentifier attrId, int arg1) throws CtxException { // TODO Auto-generated method stub IIdentity targetCss; try { targetCss = this.commMgr.getIdManager().fromJid(attrId.getOwnerId()); } catch (InvalidFormatException ife) { throw new CtxBrokerException("Could not create IIdentity from JID '" + attrId.getOwnerId() + "': " + ife.getLocalizedMessage(), ife); } this.logRequest(null, targetCss); return null; } @Override @Async public Future<List<CtxAttributeIdentifier>> getHistoryTuples( CtxAttributeIdentifier primaryAttrIdentifier, List<CtxAttributeIdentifier> arg1) throws CtxException { List<CtxAttributeIdentifier> tupleAttrIDs = new ArrayList<CtxAttributeIdentifier>(); // final String tupleAttrType = "tupleIds_" + primaryAttrIdentifier.getType(); //final String tupleAttrType = "tupleIds_" + primaryAttrIdentifier.toString(); final String tupleAttrType = "tuple_"+primaryAttrIdentifier.getType().toString()+"_"+primaryAttrIdentifier.getObjectNumber().toString(); List<CtxIdentifier> ls; try { //ls = this.lookup(CtxModelType.ATTRIBUTE, tupleAttrType).get(); ls = this.lookup(primaryAttrIdentifier.getScope(), CtxModelType.ATTRIBUTE, tupleAttrType).get(); if (ls.size() > 0) { CtxIdentifier id = ls.get(0); final CtxAttribute tupleIdsAttribute = (CtxAttribute) this.userCtxDBMgr.retrieve(id); //deserialise object tupleAttrIDs = (List<CtxAttributeIdentifier>) SerialisationHelper.deserialise(tupleIdsAttribute.getBinaryValue(), this.getClass().getClassLoader()); } } catch (Exception e) { LOG.error("Exception when trying to get the history tuples identifiers for attrID: "+primaryAttrIdentifier+". "+e.getLocalizedMessage()); e.printStackTrace(); } return new AsyncResult<List<CtxAttributeIdentifier>>(tupleAttrIDs); } @Override @Async public Future<Boolean> removeHistoryTuples(CtxAttributeIdentifier arg0, List<CtxAttributeIdentifier> arg1) throws CtxException { // TODO Auto-generated method stub return null; } @Override @Async public Future<Boolean> setHistoryTuples(CtxAttributeIdentifier primaryAttrIdentifier, List<CtxAttributeIdentifier> listOfEscortingAttributeIds) throws CtxException { boolean result = false; result = this.userCtxHistoryMgr.setCtxHistoryTuples(primaryAttrIdentifier, listOfEscortingAttributeIds); return new AsyncResult<Boolean>(result); } @Override @Async public Future<List<CtxAttributeIdentifier>> updateHistoryTuples( CtxAttributeIdentifier primaryAttrIdentifier, List<CtxAttributeIdentifier> newAttrList) throws CtxException { List<CtxAttributeIdentifier> results = new ArrayList<CtxAttributeIdentifier>(); try { for (CtxAttributeIdentifier escortingAttrID : newAttrList) { // set history flag for all escorting attributes CtxAttribute attr = (CtxAttribute) this.userCtxDBMgr.retrieve(escortingAttrID); if(attr != null && attr.isHistoryRecorded() == false){ attr.setHistoryRecorded(true); this.update(attr); } } // set hoc recording flag for the attributes contained in tuple list --end final String tupleAttrType = "tuple_"+primaryAttrIdentifier.getType().toString()+"_"+primaryAttrIdentifier.getObjectNumber().toString(); List<CtxAttributeIdentifier> newTupleAttrIDs = new ArrayList<CtxAttributeIdentifier>(); newTupleAttrIDs.add(0,primaryAttrIdentifier); newTupleAttrIDs.addAll(newAttrList); List<CtxIdentifier> ls; //ls = this.lookup(CtxModelType.ATTRIBUTE, tupleAttrType).get(); ls = this.lookup(primaryAttrIdentifier.getScope(), CtxModelType.ATTRIBUTE, tupleAttrType).get(); if (ls.size() > 0) { CtxIdentifier id = ls.get(0); final CtxAttribute tupleIdsAttribute = (CtxAttribute) this.userCtxDBMgr.retrieve(id); //deserialise object byte[] attrIdsBlob = SerialisationHelper.serialise((Serializable) newTupleAttrIDs); tupleIdsAttribute.setBinaryValue(attrIdsBlob); CtxAttribute updatedAttr = (CtxAttribute) this.update(tupleIdsAttribute).get(); if(updatedAttr != null && updatedAttr.getType().contains("tuple_")) { results = (List<CtxAttributeIdentifier>) SerialisationHelper.deserialise(updatedAttr.getBinaryValue(), this.getClass().getClassLoader()); } } } catch (Exception e) { LOG.error("Exception when trying to updateHistoryTuples for attrID: "+primaryAttrIdentifier+". "+e.getLocalizedMessage()); e.printStackTrace(); } return new AsyncResult<List<CtxAttributeIdentifier>>(results); } @Override @Async public Future<Map<CtxHistoryAttribute, List<CtxHistoryAttribute>>> retrieveHistoryTuples( String attributeType, List<CtxAttributeIdentifier> escortingAttrIds, Date startDate, Date endDate) { Map<CtxHistoryAttribute, List<CtxHistoryAttribute>> tupleResults = new LinkedHashMap<CtxHistoryAttribute, List<CtxHistoryAttribute>>(); try { IIdentity localID = this.getLocalIdentity(); //List<CtxIdentifier> ctxAttrListIds = this.lookup(CtxModelType.ATTRIBUTE, attributeType).get(); List<CtxIdentifier> ctxAttrListIds = this.lookup(localID, CtxModelType.ATTRIBUTE, attributeType).get(); //LOG.info("ctxAttribute list "+ctxAttrListIds); CtxAttributeIdentifier primaryAttrId = null; for(int i=0; i< ctxAttrListIds.size(); i++){ primaryAttrId = (CtxAttributeIdentifier) ctxAttrListIds.get(i); IIdentity targetCss; try { targetCss = this.commMgr.getIdManager().fromJid(primaryAttrId.getOwnerId()); } catch (InvalidFormatException ife) { throw new CtxBrokerException("Could not create IIdentity from JID", ife); } this.logRequest(null, targetCss); List<CtxAttributeIdentifier> listOfEscortingAttributeIds = new ArrayList<CtxAttributeIdentifier>(); Map<CtxHistoryAttribute, List<CtxHistoryAttribute>> tempTupleResults = new HashMap<CtxHistoryAttribute, List<CtxHistoryAttribute>>(); tempTupleResults = retrieveHistoryTuples(primaryAttrId, listOfEscortingAttributeIds, startDate, endDate).get(); tupleResults.putAll(tempTupleResults); } // short tupleResults data based on timestamps tupleResults = shortByTime((HashMap<CtxHistoryAttribute, List<CtxHistoryAttribute>>) tupleResults); } catch (Exception e) { LOG.error("Exception when trying to retrieve history tuples for attribute Type: "+attributeType+". "+e.getLocalizedMessage()); e.printStackTrace(); } return new AsyncResult<Map<CtxHistoryAttribute, List<CtxHistoryAttribute>>>(tupleResults); } @Override @Async public Future<Map<CtxHistoryAttribute, List<CtxHistoryAttribute>>> retrieveHistoryTuples( CtxAttributeIdentifier primaryAttrId, List<CtxAttributeIdentifier> escortingAttrIds, Date startDate, Date endDate) throws CtxException { Map<CtxHistoryAttribute, List<CtxHistoryAttribute>> results = new LinkedHashMap<CtxHistoryAttribute, List<CtxHistoryAttribute>>(); //LOG.info("retrieveHistoryTuples updating hocAttrs primaryAttr: "+primaryAttrId); if (primaryAttrId == null) { throw new NullPointerException("primary CtxAttribute Id can't be null"); } if(primaryAttrId!= null){ IIdentity targetCss; try { targetCss = this.commMgr.getIdManager().fromJid(primaryAttrId.getOwnerId()); } catch (InvalidFormatException ife) { throw new CtxBrokerException("Could not create IIdentity from JID", ife); } this.logRequest(null, targetCss); String tupleAttrType = "tuple_"+primaryAttrId.getType().toString()+"_"+primaryAttrId.getObjectNumber().toString(); //LOG.info("retrieve: tuple attr type "+ tupleAttrType); List<CtxIdentifier> listIds; try { listIds = this.lookup(primaryAttrId.getScope(), CtxModelType.ATTRIBUTE,tupleAttrType).get(); //listIds = this.lookup(CtxModelType.ATTRIBUTE,tupleAttrType).get(); if( listIds.size()>0){ CtxAttributeIdentifier tupleAttrTypeID = (CtxAttributeIdentifier) listIds.get(0); // retrieve historic attrs of type "tuple_action" // each hoc attr contains a value (blob) list of historic attrs store together List<CtxHistoryAttribute> hocResults = retrieveHistory(tupleAttrTypeID,startDate,endDate).get(); // for each "tuple_status" hoc attr for (CtxHistoryAttribute hocAttr : hocResults) { // get the list of hoc attrs stored as BlobValue List<CtxHistoryAttribute> tupleValueList = (List<CtxHistoryAttribute>) SerialisationHelper.deserialise(hocAttr.getBinaryValue(), this.getClass().getClassLoader()); // list of historic attributes contained in "tuple_status" retrieved //LOG.info("retrieveHistoryTuples tupleValueList: "+tupleValueList); //for each historic attr for (CtxHistoryAttribute tupledHoCAttrTemp : tupleValueList){ //the key , primary historic attribute CtxHistoryAttribute keyAttr = null; //the escorting historic attributes List<CtxHistoryAttribute> listEscHocAttrs = new ArrayList<CtxHistoryAttribute>(); //for each historic attr in blob value check if the identifier equals the primary identifier if (tupledHoCAttrTemp.getId().toString().equals(primaryAttrId.toString())){ // ia++; keyAttr = tupledHoCAttrTemp; for (CtxHistoryAttribute tupledHoCAttrEscorting : tupleValueList){ if (!(tupledHoCAttrEscorting.getId().toString().equals(primaryAttrId.toString()))){ listEscHocAttrs.add(tupledHoCAttrEscorting); } } results.put(keyAttr, listEscHocAttrs); } }// end of for loop } }//if size } catch (Exception e) { LOG.error("Exception when trying to retrieve history tuples for attribute id: "+primaryAttrId+". "+e.getLocalizedMessage()); e.printStackTrace(); } } //if(results == null){ // results = new LinkedHashMap<CtxHistoryAttribute, List<CtxHistoryAttribute>>(); //} //LOG.info("retrieveHistoryTuples results: "+results); return new AsyncResult<Map<CtxHistoryAttribute, List<CtxHistoryAttribute>>>(results); } private LinkedHashMap<CtxHistoryAttribute, List<CtxHistoryAttribute>> shortByTime(HashMap<CtxHistoryAttribute, List<CtxHistoryAttribute>> data){ LinkedHashMap<CtxHistoryAttribute, List<CtxHistoryAttribute>> result = new LinkedHashMap<CtxHistoryAttribute, List<CtxHistoryAttribute>>(); TreeMap<Date,CtxHistoryAttribute> tempHocDataTreeMap = new TreeMap<Date,CtxHistoryAttribute>(); for(CtxHistoryAttribute hocAttr: data.keySet()){ tempHocDataTreeMap.put(hocAttr.getLastUpdated(),hocAttr); } for(Date date :tempHocDataTreeMap.keySet()){ CtxHistoryAttribute keyHocAttr = tempHocDataTreeMap.get(date); result.put(keyHocAttr, data.get(keyHocAttr)); } return result; } @Override @Async public Future<CtxHistoryAttribute> createHistoryAttribute(CtxAttributeIdentifier attID, Date date, Serializable value, CtxAttributeValueType valueType){ CtxHistoryAttribute hocAttr = null; try { hocAttr = this.userCtxHistoryMgr.createHistoryAttribute(attID,date,value,valueType); } catch (CtxException e) { LOG.error("context attribute not stored in context DB" + attID + ": " + e.getLocalizedMessage(), e); } return new AsyncResult<CtxHistoryAttribute>(hocAttr); } /* * HoC tuples will be stored in an attribute of type "tuple_attibuteType" (tuple_status) * the value will contain a list of ICtxHistoricAttribute * * tupleAttrIDs the list of escorting attributes (also contains primary attribute id) * ctxHocAttr primary attribute to be stored */ //******************************************************************** //**************** end of hoc code ********************************** //****************************************** // service refs used by junit tests //****************************************** /** * Sets the User Context DB Mgmt service reference. * * @param userDB * the User Context DB Mgmt service reference to set. */ public void setUserCtxDBMgr(IUserCtxDBMgr userDB) { this.userCtxDBMgr = userDB; } /** * Sets the Community Context DB Mgmt service reference. * * @param userDB * the User Context DB Mgmt service reference to set. */ public void setCommunityCtxDBMgr(ICommunityCtxDBMgr communityCtxDBMgr) { this.communityCtxDBMgr = communityCtxDBMgr; } /** * Sets the User Context History Mgmt service reference. * * @param userCtxHistoryMgr * the User Context History Mgmt service reference to set */ public void setUserCtxHistoryMgr(IUserCtxHistoryMgr userCtxHistoryMgr) { this.userCtxHistoryMgr = userCtxHistoryMgr; } /** * Sets the UserCtxInferenceMgr service reference. * * @param idMgr * the UserCtxInferenceMgr service reference to set. */ public void setUserCtxInferenceMgr(IUserCtxInferenceMgr userCtxInferenceMgr) { this.userCtxInferenceMgr = userCtxInferenceMgr; } /** * Sets the UserCtxInferenceMgr service reference. * * @param ICtxSimilarityEvaluator * the ctxSimilarityEval service reference to set. */ public void setCtxSimilarityEvaluator(ICtxSimilarityEvaluator ICSE) { this.ctxSimilarityEval = ICSE; } /** * Sets the {@link IPrivacyLogAppender} service reference. * * @param privacyLogAppender * the {@link IPrivacyLogAppender} service reference to set */ public void setPrivacyLogAppender(IPrivacyLogAppender privacyLogAppender) { this.privacyLogAppender = privacyLogAppender; } //****************************************** // service refs used by junit tests //****************************************** @Override public CtxAttribute estimateCommunityContext(CtxEntityIdentifier communityCtxEntityID, CtxAttributeIdentifier ctxAttrId) { CtxAttribute returnCtxAttr = this.communityCtxInferenceMgr.estimateCommunityContext(communityCtxEntityID, ctxAttrId); // TODO at this point check if inference (estimation) outcome is acceptable and if yes persist ctxAttribute if(returnCtxAttr != null) try { returnCtxAttr = (CtxAttribute) this.update(returnCtxAttr).get(); } catch (CtxException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } return returnCtxAttr; } private void logRequest(final Requestor requestor, final IIdentity target) { try { if (this.privacyLogAppender != null) this.privacyLogAppender.logContext(requestor, target); } catch (ServiceUnavailableException sue) { // do nothing } } /* * @see org.societies.api.internal.context.broker.ICtxBroker#retrieve(org.societies.api.context.model.CtxIdentifier) */ @Override @Async public Future<CtxModelObject> retrieve(final CtxIdentifier ctxId) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.retrieve(requestor, ctxId); } /* * @see org.societies.api.context.broker.ICtxBroker#retrieve(org.societies.api.identity.Requestor, org.societies.api.context.model.CtxIdentifier) */ @Override @Async public Future<CtxModelObject> retrieve(final Requestor requestor, final CtxIdentifier ctxId) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (ctxId == null) { throw new NullPointerException("ctxId can't be null"); } LOG.debug("retrieve: requestor={}, ctxId={}", requestor, ctxId); CtxModelObject result = null; // Extract target IIdentity final IIdentity target = this.extractIIdentity(ctxId); // Log with Privacy Log Appender this.logRequest(requestor, target); if (this.isLocalId(target)) { // L O C A L // Check if access control is required. if(!requestor.equals(this.getLocalRequestor())) { // Check READ permission this.ctxAccessController.checkPermission(requestor, ctxId, ActionConstants.READ); } // No CtxAccessControlException thrown implies READ access has been granted if (IdentityType.CIS != target.getType()) { // U S E R if (ctxId instanceof CtxAttributeIdentifier) { // I N F E R E N C E result = this.inferUserAttribute((CtxAttributeIdentifier) ctxId); } else { result = this.userCtxDBMgr.retrieve(ctxId); } } else { // C O M M U N I T Y if (ctxId instanceof CtxAttributeIdentifier) { // I N F E R E N C E result = this.inferCommunityAttribute((CtxAttributeIdentifier) ctxId); } else { result = this.communityCtxDBMgr.retrieve(ctxId); } } // Obfuscate non-null result if requestor is not local if (result != null && !requestor.equals(this.getLocalRequestor())) { result = this.ctxAccessController.obfuscate(requestor, result); } } else { // R E M O T E // Needed for performance test long initTimestamp = System.nanoTime(); final RetrieveCtxCallback callback = new RetrieveCtxCallback(); this.ctxBrokerClient.retrieve(requestor, ctxId, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result = callback.getResult(); } else { throw callback.getException(); } // Needed for performance test if (PERF_LOG.isTraceEnabled()) { final IPerformanceMessage m = new PerformanceMessage(); m.setTestContext("ContextBroker_Delay_RemoteContextRetrieval"); m.setSourceComponent(this.getClass().getName()); m.setPerformanceType(IPerformanceMessage.Delay); m.setOperationType("RemoteCSS_ContextRetrieval"); m.setD82TestTableName("S11"); long delay = System.nanoTime() - initTimestamp; m.setPerformanceNameValue("Delay="+(delay)); PERF_LOG.trace(m.toString()); } } catch (InterruptedException e) { throw new CtxBrokerException("Interrupted while waiting for remote retrieve"); } } } LOG.debug("retrieve: result={}", result); return new AsyncResult<CtxModelObject>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#retrieveAttribute(org.societies.api.context.model.CtxAttributeIdentifier, boolean) */ @Override @Async public Future<CtxAttribute> retrieveAttribute( final CtxAttributeIdentifier ctxAttrId, final boolean enableInference) throws CtxException { if (ctxAttrId == null) { throw new NullPointerException("ctxAttrId can't be null"); } LOG.debug("retrieveAttribute: ctxAttrId={}, enableInference={}", ctxAttrId, enableInference); CtxAttribute result = null; // Extract target IIdentity final IIdentity target = this.extractIIdentity(ctxAttrId); // Log with Privacy Log Appender this.logRequest(null, target); if (this.isLocalId(target)) { // L O C A L if (IdentityType.CIS != target.getType()) { // U S E R if (enableInference) { // I N F E R E N C E result = this.inferUserAttribute(ctxAttrId); } else { result = (CtxAttribute) this.userCtxDBMgr.retrieve(ctxAttrId); } } else { // C O M M U N I T Y if (enableInference) { // I N F E R E N C E result = this.inferCommunityAttribute(ctxAttrId); } else { result = (CtxAttribute) this.communityCtxDBMgr.retrieve(ctxAttrId); } } } else { // R E M O T E throw new IllegalArgumentException("'" + ctxAttrId + "' owned by '" + target + "' is not managed locally"); } LOG.debug("retrieveAttribute: result={}", result); return new AsyncResult<CtxAttribute>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#retrieve(java.util.List) */ @Override public Future<List<CtxModelObject>> retrieve( final List<CtxIdentifier> ctxIdList) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.retrieve(requestor, ctxIdList); } /* * @see org.societies.api.context.broker.ICtxBroker#retrieve(org.societies.api.identity.Requestor, java.util.List) */ @Override public Future<List<CtxModelObject>> retrieve(final Requestor requestor, final List<CtxIdentifier> ctxIdList) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (ctxIdList == null) { throw new NullPointerException("ctxIdList can't be null"); } LOG.debug("retrieve: requestor={}, ctxIdList={}", requestor, ctxIdList); final List<CtxModelObject> result = new ArrayList<CtxModelObject>( ctxIdList.size()); // Indicates whether a CtxAccessControlException has been thrown boolean isAccessControlExceptionThrown = false; // The local user context IDs specified in the request final List<CtxIdentifier> localUserCtxIdList = new ArrayList<CtxIdentifier>(ctxIdList.size()); // The local community context IDs specified in the request final List<CtxIdentifier> localCommunityCtxIdList = new ArrayList<CtxIdentifier>(ctxIdList.size()); // The remote context IDs specified in the request final List<CtxIdentifier> remoteCtxIdList = new ArrayList<CtxIdentifier>(ctxIdList.size()); for (final CtxIdentifier ctxId : ctxIdList) { final IIdentity target = this.extractIIdentity(ctxId); if (this.isLocalId(target)) { // L O C A L if (IdentityType.CIS != target.getType()) { // U S E R // Collect all local user context IDs to be retrieved localUserCtxIdList.add(ctxId); } else { // C O M M U N I T Y // Collect all local community context IDs to be retrieved localCommunityCtxIdList.add(ctxId); } } else { // R E M O T E // Collect all remote context IDs to be retrieved remoteCtxIdList.add(ctxId); } } if (!localUserCtxIdList.isEmpty()) { // L O C A L U S E R // Check if access control is required. if(!requestor.equals(this.getLocalRequestor())) { // Check READ permission List<CtxIdentifier> allowedUserCtxIdList = new ArrayList<CtxIdentifier>(); try { allowedUserCtxIdList = this.ctxAccessController.checkPermission( requestor, localUserCtxIdList, ActionConstants.READ); } catch (CtxAccessControlException cace) { // Flag that a CtxAccessControlException has been thrown isAccessControlExceptionThrown = true; } // Retain only allowed user context IDs localUserCtxIdList.retainAll(allowedUserCtxIdList); } for (final CtxIdentifier localUserCtxId : localUserCtxIdList) { final CtxModelObject ctxModelObject = this.userCtxDBMgr.retrieve(localUserCtxId); if (ctxModelObject != null) { result.add(ctxModelObject); } } } if (!localCommunityCtxIdList.isEmpty()) { // L O C A L C O M M U N I T Y // Check if access control is required. if(!requestor.equals(this.getLocalRequestor())) { // Check READ permission List<CtxIdentifier> allowedCommunityCtxIdList = new ArrayList<CtxIdentifier>(); try { allowedCommunityCtxIdList = this.ctxAccessController.checkPermission( requestor, localCommunityCtxIdList, ActionConstants.READ); } catch (CtxAccessControlException cace) { // Flag that a CtxAccessControlException has been thrown isAccessControlExceptionThrown = true; } // Retain only allowed community context IDs localCommunityCtxIdList.retainAll(allowedCommunityCtxIdList); } for (final CtxIdentifier localCommunityCtxId : localCommunityCtxIdList) { final CtxModelObject ctxModelObject = this.communityCtxDBMgr.retrieve(localCommunityCtxId); if (ctxModelObject != null) { result.add(ctxModelObject); } } } // Obfuscate non-empty result if requestor is not local if(!result.isEmpty() && !requestor.equals(this.getLocalRequestor())) { result.retainAll(this.ctxAccessController.obfuscate(requestor, result)); } if (!remoteCtxIdList.isEmpty()) { // R E M O T E final List<Future<CtxModelObject>> remoteResults = new ArrayList<Future<CtxModelObject>>(remoteCtxIdList.size()); // Perform remote retrieve asynchronously for (final CtxIdentifier remoteCtxId : remoteCtxIdList) { remoteResults.add(this.retrieve(requestor, remoteCtxId)); } for (final Future<CtxModelObject> remoteResult : remoteResults) { try { final CtxModelObject ctxModelObject = remoteResult.get(); if (ctxModelObject != null) result.add(ctxModelObject); // TODO } catch (CtxAccessControlException cace) { // Flag that a CtxAccessControlException has been thrown // isAccessControlExceptionThrown = true; } catch (Exception e) { throw new CtxBrokerException("Could not perform remote retrieve for '" + remoteCtxIdList + "': " + e.getLocalizedMessage(), e); } } } if (isAccessControlExceptionThrown && result.isEmpty()) { throw new CtxAccessControlException("'" + ActionConstants.READ.name() + "' access to '" + ctxIdList + "' denied for requestor '" + requestor + "'"); } LOG.debug("retrieve: result={}", result); return new AsyncResult<List<CtxModelObject>>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#update(org.societies.api.context.model.CtxModelObject) */ @Override @Async public Future<CtxModelObject> update(final CtxModelObject ctxModelObject) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.update(requestor, ctxModelObject); } /* * @see org.societies.api.context.broker.ICtxBroker#update(org.societies.api.identity.Requestor, org.societies.api.context.model.CtxModelObject) */ @Override @Async public Future<CtxModelObject> update(final Requestor requestor, final CtxModelObject ctxModelObject) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (ctxModelObject == null) { throw new NullPointerException("ctxModelObject can't be null"); } LOG.debug("update: requestor={}, ctxModelObject={}", requestor, ctxModelObject); CtxModelObject result = null; // Extract target IIdentity final IIdentity target = this.extractIIdentity(ctxModelObject); if (this.isLocalId(target)) { // L O C A L // Check if access control is required if (!requestor.equals(this.getLocalRequestor())) { // Check WRITE permission this.ctxAccessController.checkPermission(requestor, ctxModelObject.getId(), ActionConstants.WRITE); } // No CtxAccessControlException thrown implies WRITE access has been granted if (IdentityType.CIS != target.getType()) { // U S E R result = this.userCtxDBMgr.update(ctxModelObject); } else { // C O M M U N I T Y result = this.communityCtxDBMgr.update(ctxModelObject); } // Update HoC this.storeHoc(ctxModelObject); } else { // R E M O T E final UpdateCtxCallback callback = new UpdateCtxCallback(); this.ctxBrokerClient.update(requestor, ctxModelObject, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result = callback.getResult(); } else { throw callback.getException(); } } catch (InterruptedException e) { throw new CtxBrokerException("Interrupted while waiting for remote update"); } } } LOG.debug("update: result={}", result); return new AsyncResult<CtxModelObject>(result); } /* * @see org.societies.api.internal.context.broker.ICtxBroker#remove(org.societies.api.context.model.CtxIdentifier) */ @Override @Async public Future<CtxModelObject> remove(final CtxIdentifier ctxId) throws CtxException { final Requestor requestor = this.getLocalRequestor(); return this.remove(requestor, ctxId); } /* * @see org.societies.api.context.broker.ICtxBroker#remove(org.societies.api.identity.Requestor, org.societies.api.context.model.CtxIdentifier) */ @Override @Async public Future<CtxModelObject> remove(final Requestor requestor, final CtxIdentifier ctxId) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (ctxId == null) { throw new NullPointerException("ctxId can't be null"); } LOG.debug("remove: reqeustor={}, ctxId={}", requestor, ctxId); CtxModelObject result = null; // Extract target IIdentity final IIdentity target = this.extractIIdentity(ctxId); // Log with Privacy Log Appender this.logRequest(requestor, target); if (this.isLocalId(target)) { // L O C A L // Check if access control is required if(!requestor.equals(this.getLocalRequestor())) { // Check DELETE permission this.ctxAccessController.checkPermission(requestor, ctxId, ActionConstants.DELETE); } // No CtxAccessControlException thrown implies DELETE access has been granted if (IdentityType.CIS != target.getType()) { // U S E R result = this.userCtxDBMgr.remove(ctxId); } else { // C O M M U N I T Y result = this.communityCtxDBMgr.remove(ctxId); } } else { // R E M O T E final RemoveCtxCallback callback = new RemoveCtxCallback(); this.ctxBrokerClient.remove(requestor, ctxId, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result = callback.getResult(); } else { throw callback.getException(); } } catch (InterruptedException e) { throw new CtxBrokerException("Interrupted while waiting for remote remove"); } } } LOG.debug("remove: result={}", result); return new AsyncResult<CtxModelObject>(result); } @Override @Async public Future<List<CtxEntityIdentifier>> lookupEntities( Requestor requestor, IIdentity targetCss, String entityType, String attribType, Serializable minAttribValue, Serializable maxAttribValue) throws CtxException { if (requestor == null) requestor = this.getLocalRequestor(); if (targetCss == null) targetCss = this.getLocalIdentity(); final List<CtxEntityIdentifier> results = new ArrayList<CtxEntityIdentifier>(); results.addAll( this.userCtxDBMgr.lookupEntities(entityType, attribType, minAttribValue, maxAttribValue)); return new AsyncResult<List<CtxEntityIdentifier>>(results); } /* * @see org.societies.api.context.broker.ICtxBroker#registerForChanges(org.societies.api.identity.Requestor, org.societies.api.context.event.CtxChangeEventListener, org.societies.api.context.model.CtxIdentifier) */ @Override public void registerForChanges(final Requestor requestor, final CtxChangeEventListener listener, final CtxIdentifier ctxId) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (listener == null) { throw new NullPointerException("listener can't be null"); } if (ctxId == null) { throw new NullPointerException("ctxId can't be null"); } LOG.debug("registerForChanges: requestor={}, listener={}, ctxId={}", new Object[] { requestor, listener, ctxId }); final String[] topics = new String[] { CtxChangeEventTopic.UPDATED, CtxChangeEventTopic.MODIFIED, CtxChangeEventTopic.REMOVED, }; if (this.ctxEventMgr != null) { LOG.info("Registering context change event listener '{}'" + " for object '{}' to topics '{}'", new Object[] { listener, ctxId, Arrays.toString(topics) }); this.ctxEventMgr.registerChangeListener(listener, topics, ctxId); try { if (ctxId instanceof CtxAttributeIdentifier && this.userCtxInferenceMgr.getInferrableTypes().contains(ctxId.getType())) { LOG.info("Triggering continuous inference of attribute '{}'", ctxId); this.userCtxInferenceMgr.refineContinuously( (CtxAttributeIdentifier) ctxId, new Double(0)); // TODO handle updateFreq } } catch (ServiceUnavailableException sue) { LOG.warn("Could not check if attribute requires inference: " + "User Context Inference Mgr is not available"); } } else { throw new CtxBrokerException("ICtxEventMgr service is not available"); } } /* * @see org.societies.api.context.broker.ICtxBroker#unregisterFromChanges(org.societies.api.identity.Requestor, org.societies.api.context.event.CtxChangeEventListener, org.societies.api.context.model.CtxIdentifier) */ @Override public void unregisterFromChanges(final Requestor requestor, final CtxChangeEventListener listener, final CtxIdentifier ctxId) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (listener == null) { throw new NullPointerException("listener can't be null"); } if (ctxId == null) { throw new NullPointerException("ctxId can't be null"); } LOG.debug("unregisterFromChanges: requestor={}, listener={}, ctxId={}", new Object[] { requestor, listener, ctxId }); final String[] topics = new String[] { CtxChangeEventTopic.UPDATED, CtxChangeEventTopic.MODIFIED, CtxChangeEventTopic.REMOVED, }; if (this.ctxEventMgr != null) { LOG.info("Unregistering context change event listener '{}'" + " for object '{}' from topics '{}'", new Object[] { listener, ctxId, Arrays.toString(topics) }); this.ctxEventMgr.unregisterChangeListener(listener, topics, ctxId); /* TODO try { if (ctxId instanceof CtxAttributeIdentifier && this.userCtxInferenceMgr.getInferrableTypes().contains(ctxId.getType())) { if (LOG.isInfoEnabled()) // TODO DEBUG LOG.info("Triggering continuous inference of attribute '" + ctxId + "'"); this.userCtxInferenceMgr.refineContinuously( (CtxAttributeIdentifier) ctxId, new Double(0)); // TODO handle updateFreq } } catch (ServiceUnavailableException sue) { LOG.warn("Could not check if attribute requires inference: " + "User Context Inference Mgr is not available"); } */ } else { throw new CtxBrokerException("ICtxEventMgr service is not available"); } } /* * @see org.societies.api.context.broker.ICtxBroker#registerForChanges(org.societies.api.identity.Requestor, org.societies.api.context.event.CtxChangeEventListener, org.societies.api.context.model.CtxEntityIdentifier, java.lang.String) */ @Override public void registerForChanges(final Requestor requestor, final CtxChangeEventListener listener, final CtxEntityIdentifier scope, final String attrType) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (listener == null) { throw new NullPointerException("listener can't be null"); } if (scope == null) { throw new NullPointerException("scope can't be null"); } LOG.debug("registerForChanges: requestor={}, listener={}, scope={}, attrType={}", new Object[] { requestor, listener, scope, attrType }); final String[] topics = new String[] { CtxChangeEventTopic.CREATED, CtxChangeEventTopic.UPDATED, CtxChangeEventTopic.MODIFIED, CtxChangeEventTopic.REMOVED, }; if (this.ctxEventMgr != null) { LOG.info("Registering context change event listener '{}' for attributes with scope '{}'" + " and type '{}' to topics '{}'", new Object[] { listener, scope, attrType, Arrays.toString(topics) }); this.ctxEventMgr.registerChangeListener(listener, topics, scope, attrType ); } else { throw new CtxBrokerException("ICtxEventMgr service is not available"); } } /* * @see org.societies.api.context.broker.ICtxBroker#unregisterFromChanges(org.societies.api.identity.Requestor, org.societies.api.context.event.CtxChangeEventListener, org.societies.api.context.model.CtxEntityIdentifier, java.lang.String) */ @Override public void unregisterFromChanges(final Requestor requestor, final CtxChangeEventListener listener, final CtxEntityIdentifier scope, final String attrType) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (listener == null) { throw new NullPointerException("listener can't be null"); } if (scope == null) { throw new NullPointerException("scope can't be null"); } LOG.debug("unregisterFromChanges: requestor={}, listener={}, scope={}, attrType={}", new Object[] { requestor, listener, scope, attrType }); final String[] topics = new String[] { CtxChangeEventTopic.CREATED, CtxChangeEventTopic.UPDATED, CtxChangeEventTopic.MODIFIED, CtxChangeEventTopic.REMOVED, }; if (this.ctxEventMgr != null) { LOG.info("Unregistering context change event listener '{}' for attributes with scope '{}'" + " and type '{}' from topics '{}'", new Object[] { listener, scope, attrType, Arrays.toString(topics) }); this.ctxEventMgr.unregisterChangeListener(listener, topics, scope, attrType ); } else { throw new CtxBrokerException("ICtxEventMgr service is not available"); } } @Override @Async public Future<CtxEntityIdentifier> retrieveIndividualEntityId( Requestor requestor, final IIdentity cssId) throws CtxException { if (requestor == null) { // TODO throw new NullPointerException("requestor can't be null"); requestor = this.getLocalRequestor(); } if (cssId == null) { throw new NullPointerException("cssId can't be null"); } LOG.debug("retrieveIndividualEntityId: requestor={}. cssId={}", requestor, cssId); CtxEntityIdentifier result = null; if (this.isLocalCssId(cssId)) { // L O C A L try { final IndividualCtxEntity indiEnt = this.retrieveIndividualEntity(cssId).get(); if (indiEnt != null) { result = indiEnt.getId(); } } catch (Exception e) { throw new CtxBrokerException( "Could not retrieve IndividualCtxEntity from platform Context Broker: " + e.getLocalizedMessage(), e); } } else { // R E M O T E final RetrieveIndividualEntCallback callback = new RetrieveIndividualEntCallback(); this.ctxBrokerClient.retrieveIndividualEntityId(requestor, cssId, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result = callback.getResult(); } else { throw callback.getException(); } } catch (InterruptedException e) { throw new CtxBrokerException("Interrupted while waiting for remote IndvidualCtxEntity id"); } } } LOG.debug("retrieveIndividualEntityId: result={}", result); return new AsyncResult<CtxEntityIdentifier>(result); } @Override public Future<CtxEntityIdentifier> retrieveCommunityEntityId( final Requestor requestor, final IIdentity cisId) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } if (cisId == null) { throw new NullPointerException("cisId can't be null"); } LOG.debug("retrieveCommunityEntityId: requestor={}, cisId={}", requestor, cisId); CtxEntityIdentifier result = null; try { if (this.isLocalCisId(cisId)) { // L O C A L final CommunityCtxEntity communityEntity = this.communityCtxDBMgr.retrieveCommunityEntity(cisId.getBareJid()); if (communityEntity != null) { result = communityEntity.getId(); } } else { // R E M O T E final RetrieveCommunityEntityIdCallback callback = new RetrieveCommunityEntityIdCallback(); this.ctxBrokerClient.retrieveCommunityEntityId(requestor, cisId, callback); synchronized (callback) { try { callback.wait(); if (callback.getException() == null) { result = callback.getResult(); } else { throw callback.getException(); } } catch (InterruptedException e) { throw new CtxBrokerException("Interrupted while waiting for remote CommunityCtxEntity id"); } } } } catch (Exception e) { throw new CtxBrokerException(e.getLocalizedMessage(), e); } LOG.debug("retrieveCommunityEntityId: result={}", result); return new AsyncResult<CtxEntityIdentifier>(result); } @Override public Future<List<CtxAttribute>> retrieveFuture(Requestor requestor, CtxAttributeIdentifier attrId, Date date) throws CtxException { LOG.debug("retrieveFuture: attrId={}, date={}", attrId, date); final IIdentity target = this.extractIIdentity(attrId); this.logRequest(null, target); List<CtxAttribute> result = new ArrayList<CtxAttribute>(); try { result = this.retrieveFuture(attrId, date).get(); } catch (Exception e) { LOG.error("Exception on predicting context attribute :"+attrId+". "+ e.getLocalizedMessage()); e.printStackTrace(); } LOG.debug("retrieveFuture: result={}", result); return new AsyncResult<List<CtxAttribute>>(result); } @Override public Future<List<CtxAttribute>> retrieveFuture(Requestor requestor, CtxAttributeIdentifier attrId, int modificationIndex) throws CtxException { LOG.debug("retrieveFuture: attrId={}, modificationIndex={}", attrId, modificationIndex); final IIdentity target = this.extractIIdentity(attrId); this.logRequest(null, target); List<CtxAttribute> result = new ArrayList<CtxAttribute>(); try { result = this.retrieveFuture(attrId, null).get(); } catch (Exception e) { LOG.error("Exception on predicting context attribute :"+attrId+" for modification index : "+modificationIndex+". "+ e.getLocalizedMessage()); e.printStackTrace(); } LOG.debug("retrieveFuture: result={}", result); return new AsyncResult<List<CtxAttribute>>(result); } @Override public Future<List<CtxHistoryAttribute>> retrieveHistory( Requestor requestor, CtxAttributeIdentifier attrId, int modificationIndex) throws CtxException { // TODO Auto-generated method stub return null; } @Override public Future<List<CtxHistoryAttribute>> retrieveHistory( final Requestor requestor, CtxAttributeIdentifier attrId, Date startDate, Date endDate) throws CtxException { if (requestor == null) { throw new NullPointerException("requestor can't be null"); } LOG.debug("retrieveHistory: requestor={}, attrId={}, startDate={}, endDate={}", new Object[] { requestor, attrId, startDate, endDate }); final List<CtxHistoryAttribute> result = new ArrayList<CtxHistoryAttribute>(); final IIdentity target = this.extractIIdentity(attrId); this.logRequest(requestor, target); if (IdentityType.CSS.equals(target.getType()) || IdentityType.CSS_RICH.equals(target.getType()) || IdentityType.CSS_LIGHT.equals(target.getType())) { if (this.commMgr.getIdManager().isMine(target) ) { result.addAll(this.userCtxHistoryMgr.retrieveHistory(attrId, startDate, endDate)); } else { LOG.error("remote call is not supported for ctx history data"); } } else if (IdentityType.CIS.equals(target.getType())){ if (isLocalCisId(target) ) { result.addAll(this.userCtxHistoryMgr.retrieveHistory(attrId, startDate, endDate)); } else { LOG.error("remote call is not supported for ctx history data"); } } LOG.debug("retrieveHistory: requestor={}", result); return new AsyncResult<List<CtxHistoryAttribute>>(result); } @Override public Future<CtxEntity> retrieveAdministratingCSS(Requestor requestor, CtxEntityIdentifier communityEntId) throws CtxException { // TODO Auto-generated method stub return null; } @Override public Future<Set<CtxBond>> retrieveBonds(Requestor requestor, CtxEntityIdentifier communityID) throws CtxException { // TODO check if idMgr.isMine(targetCis) expression is valid Set<CtxBond> bondsSet = null; IIdentity targetCis; try { targetCis = this.commMgr.getIdManager().fromJid(communityID.getOwnerId()); } catch (InvalidFormatException ife) { throw new CtxBrokerException("Could not create IIdentity from JID", ife); } if (this.commMgr.getIdManager().isMine(targetCis)) { CommunityCtxEntity commEntity; try { commEntity = (CommunityCtxEntity) this.retrieve(communityID).get(); bondsSet = commEntity.getBonds(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return new AsyncResult<Set<CtxBond>>(bondsSet); } @Override public Future<List<CtxEntityIdentifier>> retrieveSubCommunities( Requestor requestor, CtxEntityIdentifier community) throws CtxException { // TODO Auto-generated method stub return null; } @Override public Future<List<CtxEntityIdentifier>> retrieveCommunityMembers( Requestor requestor, CtxEntityIdentifier community) throws CtxException { // TODO Auto-generated method stub return null; } @Override public Future<List<CtxEntityIdentifier>> retrieveParentCommunities( Requestor requestor, CtxEntityIdentifier community) throws CtxException { // TODO Auto-generated method stub return null; } public Requestor getLocalRequestor() throws CtxBrokerException { final INetworkNode cssNodeId = this.commMgr.getIdManager().getThisNetworkNode(); try { final IIdentity cssOwnerId = this.commMgr.getIdManager().fromJid(cssNodeId.getBareJid()); return new Requestor(cssOwnerId); } catch (InvalidFormatException e) { throw new CtxBrokerException("requestor could not be set for local network node '" + cssNodeId + "': " + e.getLocalizedMessage(), e); } } private IIdentity getLocalIdentity() throws CtxBrokerException { final INetworkNode cssNodeId = this.commMgr.getIdManager().getThisNetworkNode(); try { return this.commMgr.getIdManager().fromJid(cssNodeId.getBareJid()); } catch (InvalidFormatException e) { throw new CtxBrokerException(" cssOwnerId could not be set: " + e.getLocalizedMessage(), e); } } //control monitoring classes @Override public void disableCtxMonitoring(CtxAttributeValueType type) throws CtxException { // TODO Auto-generated method stub } @Override public void disableCtxRecording() throws CtxException { // TODO Auto-generated method stub } @Override public void enableCtxMonitoring(CtxAttributeValueType type) throws CtxException { // TODO Auto-generated method stub } @Override public void enableCtxRecording() throws CtxException { // TODO Auto-generated method stub } /** * Sets the {@link ICtxAccessController} service reference. * * @param ctxAccessController * the {@link ICtxAccessController} service reference to set */ public void setCtxAccessController(ICtxAccessController ctxAccessController) { this.ctxAccessController = ctxAccessController; } /** * added by eboylan for CSE integration test */ @Override public CtxEvaluationResults evaluateSimilarity(String[] ids, ArrayList<String> attrib) throws CtxException { //LOG.info("EBOYLANLOGFOOTPRINT: ctxSimilarity broker = " + ctxSimilarityEval); //LOG.info("EBOYLANLOGFOOTPRINT internalCtxBroker.evaluateSimilarity called"); CtxEvaluationResults evalResult = (CtxEvaluationResults) this.ctxSimilarityEval.evaluateSimilarity(ids, attrib); //this. return evalResult; } private CtxAttribute inferUserAttribute( final CtxAttributeIdentifier ctxAttrId) throws CtxException { if (ctxAttrId == null) { throw new NullPointerException("ctxAttrId can't be null"); } CtxAttribute result = (CtxAttribute) this.userCtxDBMgr.retrieve(ctxAttrId); // Check if inference is applicable/required: // 1. inferrable attribute type AND // 2. existing attribute either has no value OR a value of poor quality try { if (result != null && this.userCtxInferenceMgr.getInferrableTypes().contains(result.getType()) && (!CtxBrokerUtils.hasValue(result) || this.userCtxInferenceMgr.isPoorQuality(result.getQuality()))) { LOG.debug("Inferring user context attribute with id '{}'", ctxAttrId); final CtxAttribute inferredAttribute = this.userCtxInferenceMgr.refineOnDemand(ctxAttrId); LOG.debug("Inferred user context attribute '{}'", inferredAttribute); if (inferredAttribute != null) { result = inferredAttribute; } } } catch (ServiceUnavailableException sue) { throw new CtxBrokerException("User Context Inference Mgr is not available"); } return result; } private CtxAttribute inferCommunityAttribute( final CtxAttributeIdentifier ctxAttrId) throws CtxException { if (ctxAttrId == null) { throw new NullPointerException("ctxAttrId can't be null"); } CtxAttribute result = (CtxAttribute) this.communityCtxDBMgr.retrieve(ctxAttrId); // Check if inference is applicable/required: // 1. inferrable attribute type try { if (this.communityCtxInferenceMgr.getInferrableTypes().contains(ctxAttrId.getType())) { LOG.debug("Inferring community context attribute with id '{}'", ctxAttrId); final CtxAttribute inferredAttribute = this.communityCtxInferenceMgr.estimateCommunityContext(ctxAttrId.getScope(), ctxAttrId); LOG.debug("Inferred community context attribute '{}'", inferredAttribute); if (inferredAttribute != null && CtxBrokerUtils.hasValue(inferredAttribute)) { // TODO The Community Inference Mgr should persist the estimated attribute in the Community DB - *not* the Context Broker try { result = (CtxAttribute) this.update(inferredAttribute).get(); } catch (InterruptedException ie) { throw new CtxBrokerException("Interrupted while updating inferred community context attribute '" + inferredAttribute.getId() + "': " + ie.getLocalizedMessage(), ie); } catch (ExecutionException ee) { throw new CtxBrokerException("Could not update inferred community context attribute '" + inferredAttribute.getId() + "': " + ee.getLocalizedMessage(), ee); } } } } catch (ServiceUnavailableException sue) { throw new CtxBrokerException("Community Context Inference Mgr is not available"); } return result; } private boolean isLocalId(final IIdentity id) { if (id == null) { throw new NullPointerException("id can't be null"); } if (IdentityType.CIS != id.getType()) { // U S E R I D return this.isLocalCssId(id); } else { // C O M M U N I T Y I D return this.isLocalCisId(id); } } private boolean isLocalCssId(final IIdentity cssId) { if (cssId == null) { throw new NullPointerException("cssId can't be null"); } if (IdentityType.CIS == cssId.getType()) { throw new IllegalArgumentException("cssId IdentityType is not CSS"); } return this.commMgr.getIdManager().isMine(cssId); } private boolean isLocalCisId(final IIdentity cisId) { if (cisId == null) { throw new NullPointerException("cisId can't be null"); } if (IdentityType.CIS != cisId.getType()) { throw new IllegalArgumentException("cisId IdentityType is not CIS"); } return (this.commMgrFactory.getAllCISCommMgrs().get(cisId) != null); } private IIdentity extractIIdentity(CtxIdentifier ctxId) throws CtxBrokerException { if (ctxId == null) { throw new NullPointerException("ctxId can't be null"); } final IIdentity target; try { target = this.commMgr.getIdManager().fromJid(ctxId.getOwnerId()); } catch (InvalidFormatException ife) { throw new CtxBrokerException("Could not create IIdentity from JID '" + ctxId.getOwnerId() + "': " + ife.getLocalizedMessage(), ife); } return target; } private IIdentity extractIIdentity(CtxModelObject ctxModelObject) throws CtxBrokerException { if (ctxModelObject == null) { throw new NullPointerException("ctxModelObject can't be null"); } return this.extractIIdentity(ctxModelObject.getId()); } @Override public CtxAttribute communityInheritance(CtxAttributeIdentifier ctxAttrID) { if (ctxAttrID == null) throw new NullPointerException("Exception while initiating context inheritance, ctxAttrID can't be null"); //TODO add more controls CtxAttribute ctxAttribute = this.userCtxInferenceMgr.inheritContext(ctxAttrID); return ctxAttribute; } }