/** * 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.integration.test.bit.ctx_locationRefiner; import static org.junit.Assert.*; import java.util.Set; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.societies.api.comm.xmpp.interfaces.ICommManager; import org.societies.api.context.event.CtxChangeEvent; import org.societies.api.context.event.CtxChangeEventListener; import org.societies.api.context.model.CtxAttribute; import org.societies.api.context.model.CtxAttributeIdentifier; import org.societies.api.context.model.CtxAttributeTypes; import org.societies.api.context.model.CtxEntity; import org.societies.api.context.model.CtxOriginType; import org.societies.api.context.model.IndividualCtxEntity; import org.societies.api.context.source.CtxSourceNames; import org.societies.api.identity.IIdentity; import org.societies.api.identity.INetworkNode; import org.societies.api.internal.context.broker.ICtxBroker; /** * * * @author nikosk * */ public class Tester { private static Logger LOG = LoggerFactory.getLogger(Tester.class); private ICtxBroker internalCtxBroker; private ICommManager commMgr; private INetworkNode cssNodeId; private IIdentity cssOwnerId; private CtxAttributeIdentifier userSymbolicLocationAttrId; private CtxAttributeIdentifier pzNodeSymbolicLocationAttrId; private CtxAttributeIdentifier rfidNodeSymbolicLocationAttrId; public Tester() { } @Before public void setUp() throws Exception { this.internalCtxBroker = TestLocationRefiner.getCtxBroker(); this.commMgr = TestLocationRefiner.getCommManager(); this.cssNodeId = this.commMgr.getIdManager().getThisNetworkNode(); LOG.info("*** cssNodeId = " + this.cssNodeId); final String cssOwnerStr = this.cssNodeId.getBareJid(); this.cssOwnerId = this.commMgr.getIdManager().fromJid(cssOwnerStr); LOG.info("*** cssOwnerId = " + this.cssOwnerId); this.userSymbolicLocationAttrId = this.getUserSymbolicLocationAttributeId(); assertNotNull(this.userSymbolicLocationAttrId); LOG.info("*** userSymbolicLocationAttrId = " + this.userSymbolicLocationAttrId); this.createCSSNodeLocationAttributes(); assertNotNull(this.pzNodeSymbolicLocationAttrId); LOG.info("*** pzNodeSymbolicLocationAttrId = " + this.pzNodeSymbolicLocationAttrId); assertNotNull(this.rfidNodeSymbolicLocationAttrId); LOG.info("*** rfidNodeSymbolicLocationAttrId = " + this.rfidNodeSymbolicLocationAttrId); } @Test public void TestLocationRefinement() throws Exception { LOG.info("*** Start testing ..."); //1. retrieve symbolic location (on-demand inference) this.testOnDemandInference(); //2. registerForChanges(locationAttrId) this.testContiniousInferenceByAttrId(); //3. registerForChanges(indiEntId, LOCATION_SYMBOLIC) //this.testContiniousInferenceByAttrType(); } private void testOnDemandInference() throws Exception { LOG.info("start testing testOnDemandInference..."); CtxAttribute userSymbolicLocationAttr = this.internalCtxBroker.retrieveAttribute( this.userSymbolicLocationAttrId, false).get(); assertNotNull(userSymbolicLocationAttr); LOG.info("1 indi entity current location :"+ userSymbolicLocationAttr.getStringValue()); LOG.info("----- 1st set of updates: PZ should be fresh -----"); // 1 update pz LOG.info("1 PZ will update the CSS node entity with location value:Room1PZ and FreqId:1/5"); CtxAttribute locationCssNodeAttrPZ = this.updateLocationCSSNode("room1PZ", CtxSourceNames.PZ, 1d/5); assertEquals("room1PZ", locationCssNodeAttrPZ.getStringValue()); assertTrue(locationCssNodeAttrPZ.getSourceId().contains(CtxSourceNames.PZ)); assertEquals(1d/5, locationCssNodeAttrPZ.getQuality().getUpdateFrequency(), 1e-3); // 1 update rfid LOG.info("1 RFID will update the CSS node entity with location value:Room1RFID and FreqId:1/2"); CtxAttribute locationCssNodeAttrRFID = this.updateLocationCSSNode("room1RFID", CtxSourceNames.RFID, 1d/2); assertEquals("room1RFID", locationCssNodeAttrRFID.getStringValue()); assertTrue(locationCssNodeAttrRFID.getSourceId().contains(CtxSourceNames.RFID)); assertEquals(1d/2, locationCssNodeAttrRFID.getQuality().getUpdateFrequency(), 1e-3); LOG.info("---- waiting 3 sec ----"); Thread.sleep(3000); // 1 verify LOG.info("1 Calling internalCtxBroker.retrieve(" + this.userSymbolicLocationAttrId + ") to trigger on-demand inference"); userSymbolicLocationAttr = (CtxAttribute) this.internalCtxBroker.retrieve(this.userSymbolicLocationAttrId).get(); LOG.info("1-------> individual entity current location:" + userSymbolicLocationAttr.getStringValue() + " should be " + locationCssNodeAttrPZ.getStringValue()); assertEquals(locationCssNodeAttrPZ.getStringValue(), userSymbolicLocationAttr.getStringValue()); assertEquals(CtxOriginType.INFERRED, userSymbolicLocationAttr.getQuality().getOriginType()); assertEquals(locationCssNodeAttrPZ.getQuality().getUpdateFrequency(), userSymbolicLocationAttr.getQuality().getUpdateFrequency(), 1e-3); LOG.info("----- 2nd set of updates: Both PZ and RFID should be fresh -----"); // 2 update pz LOG.info("2 PZ will update the CSS node entity with location value:Room2PZ and FreqId:1/60"); locationCssNodeAttrPZ = this.updateLocationCSSNode("room2PZ", CtxSourceNames.PZ, 1d/60); assertEquals("room2PZ", locationCssNodeAttrPZ.getStringValue()); assertTrue(locationCssNodeAttrPZ.getSourceId().contains(CtxSourceNames.PZ)); assertEquals(1d/60, locationCssNodeAttrPZ.getQuality().getUpdateFrequency(), 1e-3); // 2 update rfid LOG.info("2 RFID will update the CSS node entity with location value:Room2RFID and FreqId:1/60"); locationCssNodeAttrRFID = this.updateLocationCSSNode("room2RFID", CtxSourceNames.RFID, 1d/60); assertEquals("room2RFID", locationCssNodeAttrRFID.getStringValue()); assertTrue(locationCssNodeAttrRFID.getSourceId().contains(CtxSourceNames.RFID)); assertEquals(1d/60, locationCssNodeAttrRFID.getQuality().getUpdateFrequency(), 1e-3); LOG.info("---- waiting 3 sec ----"); Thread.sleep(3000); // 2 verify LOG.info("2 Calling internalCtxBroker.retrieve(" + this.userSymbolicLocationAttrId + ") to trigger on-demand inference"); userSymbolicLocationAttr = (CtxAttribute) this.internalCtxBroker.retrieve(this.userSymbolicLocationAttrId).get(); LOG.info("2-------> individual entity current location:" + userSymbolicLocationAttr.getStringValue() + " should be " + locationCssNodeAttrRFID.getStringValue()); assertEquals(locationCssNodeAttrRFID.getStringValue(), userSymbolicLocationAttr.getStringValue()); assertEquals(CtxOriginType.INFERRED, userSymbolicLocationAttr.getQuality().getOriginType()); assertEquals(locationCssNodeAttrRFID.getQuality().getUpdateFrequency(), userSymbolicLocationAttr.getQuality().getUpdateFrequency(), 1e-3); } private void testContiniousInferenceByAttrId() throws Exception { LOG.info("start testing testContiniousInferenceByAttrID..."); //1. register for changes on individual entity location //2. update location in css node //3. receive update in listener and verify value final MyCtxChangeEventListener listener = new MyCtxChangeEventListener("room3RFID"); LOG.info("registering for changes of " + this.userSymbolicLocationAttrId); this.internalCtxBroker.registerForChanges(listener, this.userSymbolicLocationAttrId); this.updateLocationCSSNode("room3RFID", CtxSourceNames.RFID, 1d/60); LOG.info("at this point a location update event is expected to be received"); LOG.info("*** Sleeping for 10 sec"); Thread.sleep(10000); final CtxAttribute userSymLocAttr = this.internalCtxBroker.retrieveAttribute(this.userSymbolicLocationAttrId, false).get(); final String userSymLocValue = userSymLocAttr.getStringValue(); LOG.info("unregistering from changes of " + this.userSymbolicLocationAttrId); this.internalCtxBroker.unregisterFromChanges(listener, this.userSymbolicLocationAttrId); assertEquals("room3RFID", userSymLocValue); } // helper methods /* * retrieve css node entity and update symbolic location */ private CtxAttribute updateLocationCSSNode(String locationValue, String source, Double updateFreq) throws Exception { LOG.info("*** updateLocationCSSNode: locationValue=" + locationValue + ", source=" + source); CtxAttribute result = null; if (CtxSourceNames.PZ.equals(source)) result = this.internalCtxBroker.retrieveAttribute(this.pzNodeSymbolicLocationAttrId, false).get(); else if (CtxSourceNames.RFID.equals(source)) result = this.internalCtxBroker.retrieveAttribute(this.rfidNodeSymbolicLocationAttrId, false).get(); else fail("Failed to update SYMBOLIC_LOCATION under CSS node entity"); result.setStringValue(locationValue); result.getQuality().setUpdateFrequency(updateFreq); return (CtxAttribute) this.internalCtxBroker.update(result).get(); } private void createCSSNodeLocationAttributes() throws Exception { boolean createLocAttrRFID = true; boolean createLocAttrPZ = true; final CtxEntity cssNodeEntity = this.internalCtxBroker.retrieveCssNode(this.cssNodeId).get(); final Set<CtxAttribute> attrLocSet = cssNodeEntity.getAttributes(CtxAttributeTypes.LOCATION_SYMBOLIC); for (final CtxAttribute attrLoc : attrLocSet) { if(attrLoc.getSourceId().contains(CtxSourceNames.RFID)) { this.rfidNodeSymbolicLocationAttrId = attrLoc.getId(); createLocAttrRFID = false; } else if(attrLoc.getSourceId().contains(CtxSourceNames.PZ)) { this.pzNodeSymbolicLocationAttrId = attrLoc.getId(); createLocAttrPZ = false; } } if (createLocAttrRFID) { LOG.info("create RFID location attribute"); final CtxAttribute loc_rfid = this.internalCtxBroker.createAttribute(cssNodeEntity.getId(), CtxAttributeTypes.LOCATION_SYMBOLIC).get(); loc_rfid.setSourceId(CtxSourceNames.RFID+"0"); this.internalCtxBroker.update(loc_rfid); this.rfidNodeSymbolicLocationAttrId = loc_rfid.getId(); } if (createLocAttrPZ) { LOG.info("create PZ location attribute"); final CtxAttribute loc_pz = this.internalCtxBroker.createAttribute(cssNodeEntity.getId(), CtxAttributeTypes.LOCATION_SYMBOLIC).get(); loc_pz.setSourceId(CtxSourceNames.PZ+"0"); this.internalCtxBroker.update(loc_pz); this.pzNodeSymbolicLocationAttrId = loc_pz.getId(); } } /* * retrieve individual entity symbolic location attribute id */ private CtxAttributeIdentifier getUserSymbolicLocationAttributeId() throws Exception { final IndividualCtxEntity cssOwnerEntity = this.internalCtxBroker.retrieveIndividualEntity(this.cssOwnerId).get(); final Set<CtxAttribute> locationAttrSet = cssOwnerEntity.getAttributes(CtxAttributeTypes.LOCATION_SYMBOLIC); assertFalse("CSS owner entity does not contain LOCATION_SYMBOLIC attribute", locationAttrSet.isEmpty()); assertTrue("CSS owner entity should contain exactly one LOCATION_SYMBOLIC attribute", locationAttrSet.size() == 1); return locationAttrSet.iterator().next().getId(); } private class MyCtxChangeEventListener implements CtxChangeEventListener { private final String expectedValue; private MyCtxChangeEventListener(String value) { this.expectedValue = value; } @Override public void onCreation(CtxChangeEvent event) { // TODO Auto-generated method stub } @Override public void onModification(CtxChangeEvent event) { LOG.info(event.getId() + ": *** MODIFIED event ***"); } @Override public void onRemoval(CtxChangeEvent event) { // TODO Auto-generated method stub } @Override public void onUpdate(CtxChangeEvent event) { LOG.info(event.getId() + ": *** UPDATED event ***"); try { CtxAttribute locationAttr = (CtxAttribute) internalCtxBroker.retrieve(event.getId()).get(); LOG.info("location value expected:"+ expectedValue); LOG.info("location value received:"+ locationAttr.getStringValue()); assertEquals(this.expectedValue, locationAttr.getStringValue()); } catch (Exception e) { fail("onUpdate threw exception: " + e.getLocalizedMessage()); } } } }