/** * 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.webapp.controller; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.ManagedProperty; import javax.faces.bean.ViewScoped; import org.primefaces.event.RateEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.societies.api.cis.directory.ICisDirectoryCallback; import org.societies.api.cis.directory.ICisDirectoryRemote; import org.societies.api.internal.privacytrust.trust.ITrustBroker; import org.societies.api.internal.privacytrust.trust.evidence.ITrustEvidenceCollector; import org.societies.api.internal.privacytrust.trust.model.ExtTrustRelationship; import org.societies.api.internal.servicelifecycle.IServiceDiscovery; import org.societies.api.privacytrust.trust.TrustQuery; import org.societies.api.privacytrust.trust.event.ITrustUpdateEventListener; import org.societies.api.privacytrust.trust.event.TrustUpdateEvent; import org.societies.api.privacytrust.trust.evidence.TrustEvidenceType; import org.societies.api.privacytrust.trust.model.TrustEvidence; import org.societies.api.privacytrust.trust.model.TrustValueType; import org.societies.api.privacytrust.trust.model.TrustedEntityId; import org.societies.api.privacytrust.trust.model.TrustedEntityType; import org.societies.api.privacytrust.trust.model.util.TrustValueFormat; import org.societies.api.schema.cis.directory.CisAdvertisementRecord; import org.societies.api.services.ServiceUtils; import org.societies.webapp.models.TrustedEntity; import org.societies.webapp.service.UserService; @ManagedBean(name = "trustController") @ViewScoped public class TrustController extends BasePageController { private static final long serialVersionUID = -1250855340010366453L; private static Logger LOG = LoggerFactory.getLogger(TrustController.class); /** The time to wait for CIS Directory responses in milliseconds. */ private static final long WAIT_CIS_DIR = 1000l; @ManagedProperty(value = "#{trustBroker}") private ITrustBroker trustBroker; @ManagedProperty(value = "#{trustEvidenceCollector}") private ITrustEvidenceCollector trustEvidenceCollector; @ManagedProperty(value = "#{userService}") private UserService userService; /** The CIS Directory service reference. */ @ManagedProperty(value = "#{cisDirectoryRemote}") private ICisDirectoryRemote cisDirectory; /** The Service Discovery service reference. */ @ManagedProperty(value = "#{serviceDiscovery}") private IServiceDiscovery serviceDiscovery; private List<TrustedEntity> users = new ArrayList<TrustedEntity>(); private List<TrustedEntity> filteredUsers = new ArrayList<TrustedEntity>(); private List<TrustedEntity> communities = new ArrayList<TrustedEntity>(); private List<TrustedEntity> filteredCommunities = new ArrayList<TrustedEntity>(); private List<TrustedEntity> services = new ArrayList<TrustedEntity>(); private List<TrustedEntity> filteredServices = new ArrayList<TrustedEntity>(); private TrustedEntity selectedEntity; public TrustController() { // controller constructor - called every time this page is requested! LOG.info("{} instantiated", this.getClass()); } @PostConstruct public void init() { LOG.debug("init"); this.users.addAll(this.retrieveTrustedEntities(TrustedEntityType.CSS)); this.filteredUsers.addAll(this.users); this.communities.addAll(this.retrieveTrustedEntities(TrustedEntityType.CIS)); this.filteredCommunities.addAll(this.communities); this.services.addAll(this.retrieveTrustedEntities(TrustedEntityType.SVC)); this.filteredServices.addAll(this.services); } public ITrustBroker getTrustBroker() { return this.trustBroker; } public void setTrustBroker(ITrustBroker trustBroker) { this.trustBroker = trustBroker; } public ITrustEvidenceCollector getTrustEvidenceCollector() { return this.trustEvidenceCollector; } public void setTrustEvidenceCollector(ITrustEvidenceCollector trustEvidenceCollector) { this.trustEvidenceCollector = trustEvidenceCollector; } public UserService getUserService() { return this.userService; } public void setUserService(UserService userService) { this.userService = userService; } public ICisDirectoryRemote getCisDirectory() { return this.cisDirectory; } public void setCisDirectory(ICisDirectoryRemote cisDirectory) { this.cisDirectory = cisDirectory; } public IServiceDiscovery getServiceDiscovery() { return this.serviceDiscovery; } public void setServiceDiscovery(IServiceDiscovery serviceDiscovery) { this.serviceDiscovery = serviceDiscovery; } public List<TrustedEntity> getUsers() { LOG.debug("getUsers"); return this.users; } public List<TrustedEntity> getFilteredUsers() { return this.filteredUsers; } public void setFilteredUsers(List<TrustedEntity> filteredUsers) { this.filteredUsers = filteredUsers; } public List<TrustedEntity> getCommunities() { LOG.debug("getCommunities"); return this.communities; } public List<TrustedEntity> getFilteredCommunities() { return this.filteredCommunities; } public void setFilteredCommunities(List<TrustedEntity> filteredCommunities) { this.filteredCommunities = filteredCommunities; } public List<TrustedEntity> getServices() { LOG.debug("getServices"); return this.services; } public List<TrustedEntity> getFilteredServices() { return this.filteredServices; } public void setFilteredServices(List<TrustedEntity> filteredServices) { this.filteredServices = filteredServices; } public TrustedEntity getSelectedEntity() { LOG.debug("getSelectedEntity={}", this.selectedEntity); return this.selectedEntity; } public void setSelectedEntity(TrustedEntity selectedEntity) { LOG.debug("setSelectedEntity={}", selectedEntity); this.selectedEntity = selectedEntity; } public void onRating(RateEvent rateEvent) { LOG.debug("onRating: event={}", rateEvent); try { if (this.selectedEntity == null) { throw new IllegalStateException("No trusted entity selected!"); } final TrustedEntityId ratedTeid = this.selectedEntity.getTrusteeId(); final Double rating = 0.2d * new Double((Integer) rateEvent.getRating()); this.updateTrustRating(ratedTeid, rating); } catch (Exception e) { super.addGlobalMessage("A surprising new problem has occurred!", e.getLocalizedMessage(), FacesMessage.SEVERITY_ERROR); return; } } private List<TrustedEntity> retrieveTrustedEntities( final TrustedEntityType entityType) { final List<TrustedEntity> result = new ArrayList<TrustedEntity>(); if (this.userService.isUserLoggedIn()) { try { final TrustedEntityId myTeid = new TrustedEntityId( TrustedEntityType.CSS, this.userService.getUserID()); final List<ExtTrustRelationship> dbResult = new ArrayList<ExtTrustRelationship>(); dbResult.addAll(this.trustBroker.retrieveExtTrustRelationships( new TrustQuery(myTeid).setTrusteeType(entityType)).get()); final Map<TrustedEntityId, TrustedEntity> trustedEntities = new HashMap<TrustedEntityId, TrustedEntity>(); for (final ExtTrustRelationship tr : dbResult) { // Omit *my* CSS from the list of trusted entities! if (myTeid.equals(tr.getTrusteeId())) { continue; } TrustedEntity trustedEntity = trustedEntities.get(tr.getTrusteeId()); if (trustedEntity == null) { final String trusteeName = this.formatTeid(tr.getTrusteeId()); trustedEntity = new TrustedEntity(myTeid, tr.getTrusteeId(), trusteeName); } if (TrustValueType.DIRECT == tr.getTrustValueType()) { trustedEntity.getDirectTrust().setValue(tr.getTrustValue()); trustedEntity.getDirectTrust().setStringValue( this.formatTrustValue(tr.getTrustValue())); trustedEntity.getDirectTrust().setLastUpdated(tr.getTimestamp()); } else if (TrustValueType.INDIRECT == tr.getTrustValueType()) { trustedEntity.getIndirectTrust().setValue(tr.getTrustValue()); trustedEntity.getIndirectTrust().setStringValue( this.formatTrustValue(tr.getTrustValue())); trustedEntity.getIndirectTrust().setLastUpdated(tr.getTimestamp()); } else if (TrustValueType.USER_PERCEIVED == tr.getTrustValueType()) { trustedEntity.getUserPerceivedTrust().setValue(tr.getTrustValue()); trustedEntity.getUserPerceivedTrust().setStringValue( this.formatTrustValue(tr.getTrustValue())); trustedEntity.getUserPerceivedTrust().setLastUpdated(tr.getTimestamp()); } LOG.debug("retrieveTrustedEntities: trusteeId={}, evidence={}", tr.getTrusteeId(), tr.getTrustEvidence()); for (final TrustEvidence evidence : tr.getTrustEvidence()) { // Handle RATED evidence if (TrustEvidenceType.RATED == evidence.getType() && evidence.getInfo() instanceof Double) { final Double dblRating = (Double) evidence.getInfo() * 5.0d; final Integer intRating = dblRating.intValue(); LOG.debug("retrieveTrustedEntities: trusteeId={}, rating={}", tr.getTrusteeId(), intRating); trustedEntity.setRating(intRating); } } trustedEntities.put(tr.getTrusteeId(), trustedEntity); } result.addAll(trustedEntities.values()); } catch (Exception e) { super.addGlobalMessage("A surprising new problem has occurred!", e.getLocalizedMessage(), FacesMessage.SEVERITY_ERROR); } } // end if userIsLoggedIn return result; } private String formatTeid(final TrustedEntityId teid) { final String entityId = teid.getEntityId(); try { if (TrustedEntityType.CSS == teid.getEntityType()) { return entityId; } else if (TrustedEntityType.CIS == teid.getEntityType()) { final CisDirCallback cisDirCallback = new CisDirCallback(); this.cisDirectory.searchByID(entityId, cisDirCallback); synchronized (cisDirCallback) { cisDirCallback.wait(WAIT_CIS_DIR); final List<CisAdvertisementRecord> cisAds = cisDirCallback.getCisAds(); if (cisAds != null && !cisAds.isEmpty() && cisAds.get(0).getName() != null) { return cisAds.get(0).getName(); } } } else if (TrustedEntityType.SVC == teid.getEntityType()) { final org.societies.api.schema.servicelifecycle.model.Service service = this.serviceDiscovery.getService(ServiceUtils .generateServiceResourceIdentifierFromString(entityId)).get(); if (service != null && service.getServiceName() != null) { return service.getServiceName(); } } } catch (Exception e) { LOG.warn("Could not format TEID '" + teid + "': " + e.getLocalizedMessage()); return entityId; } return teid.toString(); } private String formatTrustValue(Double trustValue) { return TrustValueFormat.formatPercent(trustValue); } private void updateTrustRating(final TrustedEntityId ratedTeid, final Double rating) { if (this.userService.isUserLoggedIn()) { try { final TrustedEntityId myTeid = new TrustedEntityId( TrustedEntityType.CSS, this.userService.getUserID()); final CountDownLatch cdLatch = new CountDownLatch(1); final TrustUpdateListener listener = new TrustUpdateListener(cdLatch); this.trustBroker.registerTrustUpdateListener(listener, new TrustQuery(myTeid).setTrusteeId(ratedTeid) .setTrustValueType(TrustValueType.USER_PERCEIVED)); LOG.debug("Adding trust evidence: '{}' rated '{}' with {}", new Object[] { myTeid, ratedTeid, rating }); this.trustEvidenceCollector.addDirectEvidence(myTeid, ratedTeid, TrustEvidenceType.RATED, new Date(), rating); cdLatch.await(2, TimeUnit.SECONDS); this.trustBroker.unregisterTrustUpdateListener(listener, new TrustQuery(myTeid).setTrusteeId(ratedTeid) .setTrustValueType(TrustValueType.USER_PERCEIVED)); if (TrustedEntityType.CSS == ratedTeid.getEntityType()) { this.users = this.retrieveTrustedEntities(TrustedEntityType.CSS); } else if (TrustedEntityType.CIS == ratedTeid.getEntityType()) { this.communities = this.retrieveTrustedEntities(TrustedEntityType.CIS); } else if (TrustedEntityType.SVC == ratedTeid.getEntityType()) { this.services = this.retrieveTrustedEntities(TrustedEntityType.SVC); } } catch (Exception e) { super.addGlobalMessage("A surprising new problem has occurred!", e.getLocalizedMessage(), FacesMessage.SEVERITY_ERROR); return; } super.addGlobalMessage("Thanks for your feedback", "We love you!", FacesMessage.SEVERITY_INFO); } // end if userIsLoggedIn } private class TrustUpdateListener implements ITrustUpdateEventListener { private final CountDownLatch cdLatch; private TrustUpdateListener(CountDownLatch cdLatch) { this.cdLatch = cdLatch; } /* * @see org.societies.api.privacytrust.trust.event.ITrustUpdateEventListener#onUpdate(org.societies.api.privacytrust.trust.event.TrustUpdateEvent) */ @Override public void onUpdate(TrustUpdateEvent trustUpdateEvent) { LOG.debug("onUpdate: trustUpdateEvent={}", trustUpdateEvent); this.cdLatch.countDown(); } } private class CisDirCallback implements ICisDirectoryCallback { private List<CisAdvertisementRecord> cisAds; /* * @see org.societies.api.cis.directory.ICisDirectoryCallback#getResult(java.util.List) */ @Override public void getResult(List<CisAdvertisementRecord> cisAds) { LOG.debug("CisDirCallback.getResult: cisAds={}", cisAds); this.cisAds = cisAds; synchronized (this) { this.notifyAll(); } } private List<CisAdvertisementRecord> getCisAds() { return this.cisAds; } } }