/**
* 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.privacytrust.trust.impl.repo;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.societies.api.privacytrust.trust.event.TrustUpdateEvent;
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.privacytrust.trust.api.event.ITrustEventMgr;
import org.societies.privacytrust.trust.api.event.TrustEventTopic;
import org.societies.privacytrust.trust.api.model.ITrustedCss;
import org.societies.privacytrust.trust.api.model.ITrustedEntity;
import org.societies.privacytrust.trust.api.repo.ITrustRepository;
import org.societies.privacytrust.trust.api.repo.TrustRepositoryException;
import org.societies.privacytrust.trust.impl.repo.model.TrustedCis;
import org.societies.privacytrust.trust.impl.repo.model.TrustedCss;
import org.societies.privacytrust.trust.impl.repo.model.TrustedEntity;
import org.societies.privacytrust.trust.impl.repo.model.TrustedService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
/**
* Implementation of the {@link ITrustRepository} interface.
*
* @author <a href="mailto:nicolas.liampotis@cn.ntua.gr">Nicolas Liampotis</a> (ICCS)
* @since 0.0.5
*/
@Repository
@Lazy(value = false)
public class TrustRepository implements ITrustRepository {
/** The logging facility. */
private static final Logger LOG = LoggerFactory.getLogger(TrustRepository.class);
private static Comparator<ITrustedCss> CssSimilarityComparator =
new Comparator<ITrustedCss>() {
/*
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
@Override
public int compare(ITrustedCss css1, ITrustedCss css2) {
// null_css == null_css
if (css1 == null && css2 == null)
return 0;
// css1 > null_css
if (css1 != null && css2 == null)
return +1;
// null_css < css2
if (css1 == null && css2 != null)
return -1;
// null_simil == null_simil
if (css1.getSimilarity() == null && css2.getSimilarity() == null)
return 0;
// simil1 > null_simil
if (css1.getSimilarity() != null && css2.getSimilarity() == null)
return +1;
// null_simil < simil2
if (css1.getSimilarity() == null && css2.getSimilarity() != null)
return -1;
return css1.getSimilarity().compareTo(css2.getSimilarity());
}
};
/** The Trust Event Mgr service reference. */
@Autowired
private ITrustEventMgr trustEventMgr;
/** The Hibernate session factory. */
@Autowired
private SessionFactory sessionFactory;
TrustRepository() {
LOG.info("{} instantiated", this.getClass());
}
/*
* @see org.societies.privacytrust.trust.api.repo.ITrustRepository#createEntity(org.societies.api.privacytrust.trust.model.TrustedEntityId, org.societies.api.privacytrust.trust.model.TrustedEntityId)
*/
@Override
public ITrustedEntity createEntity(final TrustedEntityId trustorId,
final TrustedEntityId trusteeId) throws TrustRepositoryException {
if (trustorId == null) {
throw new NullPointerException("trustorId can't be null");
}
if (trusteeId == null) {
throw new NullPointerException("trusteeId can't be null");
}
final ITrustedEntity entity;
switch (trusteeId.getEntityType()) {
case CSS:
entity = new TrustedCss(trustorId, trusteeId);
break;
case CIS:
entity = new TrustedCis(trustorId, trusteeId);
break;
case SVC:
entity = new TrustedService(trustorId, trusteeId);
break;
default:
throw new TrustRepositoryException("Unsupported trustee entity type: "
+ trusteeId.getEntityType());
}
LOG.debug("Adding trusted entity {} to the Trust Repository...", entity);
Session session = null;
Transaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
session.save(entity);
session.flush();
tx.commit();
} catch (ConstraintViolationException cve) {
LOG.warn("Entity " + entity + " already exists");
if (tx != null) {
tx.rollback();
}
} catch (Exception e) {
LOG.warn("Rolling back transaction for entity " + entity);
if (tx != null) {
tx.rollback();
}
throw new TrustRepositoryException(e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
return this.retrieveEntity(trustorId, trusteeId);
}
/*
* @see org.societies.privacytrust.trust.api.repo.ITrustRepository#retrieveEntity(org.societies.api.privacytrust.trust.model.TrustedEntityId, org.societies.api.privacytrust.trust.model.TrustedEntityId)
*/
@Override
public ITrustedEntity retrieveEntity(final TrustedEntityId trustorId,
final TrustedEntityId trusteeId)
throws TrustRepositoryException {
if (trustorId == null) {
throw new NullPointerException("trustorId can't be null");
}
if (trusteeId == null) {
throw new NullPointerException("trusteeId can't be null");
}
Class<? extends TrustedEntity> entityClass = TrustedEntity.class;
if (TrustedEntityType.CSS.equals(trusteeId.getEntityType())) {
entityClass = TrustedCss.class;
} else if (TrustedEntityType.CIS.equals(trusteeId.getEntityType())) {
entityClass = TrustedCis.class;
} else if (TrustedEntityType.SVC.equals(trusteeId.getEntityType())) {
entityClass = TrustedService.class;
}
// TODO TrustedEntityType.LGC
final ITrustedEntity result;
Session session = null;
try {
session = sessionFactory.openSession();
final Criteria criteria = session.createCriteria(entityClass)
.add(Restrictions.and(
Restrictions.eq("trustorId", trustorId),
Restrictions.eq("trusteeId", trusteeId)));
//if (TrustedCss.class.equals(entityClass))
// criteria.setFetchMode("communities", FetchMode.SELECT);
//if (TrustedCis.class.equals(entityClass))
// criteria.setFetchMode("members", FetchMode.SELECT);
result = (ITrustedEntity) criteria.uniqueResult();
} catch (Exception e) {
throw new TrustRepositoryException(e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
return result;
}
/*
* @see org.societies.privacytrust.trust.api.repo.ITrustRepository#updateEntity(org.societies.privacytrust.trust.api.model.TrustedEntity)
*/
@Override
public ITrustedEntity updateEntity(ITrustedEntity entity)
throws TrustRepositoryException {
if (entity == null) {
throw new NullPointerException("entity can't be null");
}
TrustedEntity result = null;
final Session session = this.sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
result = (TrustedEntity) session.merge(entity);
tx.commit();
} catch (Exception e) {
LOG.warn("Rolling back transaction for entity " + entity);
if (tx != null) {
tx.rollback();
}
throw new TrustRepositoryException(e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
while (!result.getUpdateEventQueue().isEmpty()) {
final TrustUpdateEvent event = result.getUpdateEventQueue().poll();
final String eventTopic;
if (TrustValueType.DIRECT == event.getTrustRelationship().getTrustValueType()) {
eventTopic = TrustEventTopic.DIRECT_TRUST_UPDATED;
} else if (TrustValueType.INDIRECT == event.getTrustRelationship().getTrustValueType()) {
eventTopic = TrustEventTopic.INDIRECT_TRUST_UPDATED;
} else { //if (TrustValueType.USER_PERCEIVED == event.getTrustRelationship().getTrustValueType())
eventTopic = TrustEventTopic.USER_PERCEIVED_TRUST_UPDATED;
}
if (this.trustEventMgr == null) {
LOG.error("Could not post TrustUpdateEvent " + event
+ " to topic '" + eventTopic + "': "
+ "Trust Event Mgr is not available");
} else {
LOG.debug("Posting TrustUpdateEvent {} to topic '{}'",
event, eventTopic);
this.trustEventMgr.postEvent(event, new String[] { eventTopic });
}
}
return result;
}
/*
* @see org.societies.privacytrust.trust.api.repo.ITrustRepository#removeEntity(org.societies.api.privacytrust.trust.model.TrustedEntityId, org.societies.api.privacytrust.trust.model.TrustedEntityId)
*/
@Override
public boolean removeEntity(final TrustedEntityId trustorId,
final TrustedEntityId trusteeId) throws TrustRepositoryException {
if (trustorId == null) {
throw new NullPointerException("trustorId can't be null");
}
if (trusteeId == null) {
throw new NullPointerException("trusteeId can't be null");
}
final ITrustedEntity entity = this.retrieveEntity(trustorId, trusteeId);
if (entity == null) {
return false;
}
Session session = null;
Transaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
session.delete(entity);
tx.commit();
} catch (Exception e) {
LOG.warn("Rolling back transaction for entity " + entity);
if (tx != null) {
tx.rollback();
}
throw new TrustRepositoryException(e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
return true;
}
/*
* @see org.societies.privacytrust.trust.api.repo.ITrustRepository#retrieveEntities(org.societies.api.privacytrust.trust.model.TrustedEntityId, org.societies.api.privacytrust.trust.model.TrustedEntityType, org.societies.api.privacytrust.trust.model.TrustValueType)
*/
@Override
public Set<ITrustedEntity> retrieveEntities(final TrustedEntityId trustorId,
final TrustedEntityType entityType, final TrustValueType valueType)
throws TrustRepositoryException {
if (trustorId == null) {
throw new NullPointerException("trustorId can't be null");
}
final Class<? extends TrustedEntity> daClass;
if (null == entityType) {
daClass = null;
} else if (TrustedEntityType.CSS == entityType) {
daClass = TrustedCss.class;
} else if (TrustedEntityType.CIS == entityType) {
daClass = TrustedCis.class;
} else if (TrustedEntityType.SVC == entityType) {
daClass = TrustedService.class;
} else {
throw new TrustRepositoryException("Unsupported entityType: "
+ entityType);
}
final Set<ITrustedEntity> result = new LinkedHashSet<ITrustedEntity>();
if (null != daClass) {
result.addAll(this.doRetrieveEntities(trustorId, daClass, valueType));
} else {
result.addAll(this.doRetrieveEntities(trustorId, TrustedCss.class, valueType));
result.addAll(this.doRetrieveEntities(trustorId, TrustedCis.class, valueType));
result.addAll(this.doRetrieveEntities(trustorId, TrustedService.class, valueType));
}
return result;
}
/*
* @see org.societies.privacytrust.trust.api.repo.ITrustRepository#retrieveMeanTrustValue(org.societies.api.privacytrust.trust.model.TrustedEntityId, org.societies.api.privacytrust.trust.model.TrustValueType, org.societies.api.privacytrust.trust.model.TrustedEntityType)
*/
@Override
public double retrieveMeanTrustValue(final TrustedEntityId trustorId,
final TrustValueType valueType, final TrustedEntityType entityType)
throws TrustRepositoryException {
if (trustorId == null) {
throw new NullPointerException("trustorId can't be null");
}
if (valueType == null) {
throw new NullPointerException("valueType can't be null");
}
final String valueProperty;
if (TrustValueType.DIRECT == valueType) {
valueProperty = "directTrust.value";
} else if (TrustValueType.INDIRECT == valueType) {
valueProperty = "indirectTrust.value";
} else { // if (TrustValueType.USER_PERCEIVED == valueType)
valueProperty = "userPerceivedTrust.value";
}
double sumValue = 0.0d;
int countValue = 0;
if (null == entityType) {
final SumN cssSumN = this.retrieveSumNTrustValue(
trustorId, valueProperty, TrustedCss.class);
final SumN cisSumN = this.retrieveSumNTrustValue(
trustorId, valueProperty, TrustedCis.class);
final SumN svcSumN = this.retrieveSumNTrustValue(
trustorId, valueProperty, TrustedService.class);
sumValue += cssSumN.sum + cisSumN.sum + svcSumN.sum;
countValue += cssSumN.n + cisSumN.n + svcSumN.n;
} else if (TrustedEntityType.CSS == entityType) {
final SumN sumN = this.retrieveSumNTrustValue(
trustorId, valueProperty, TrustedCss.class);
sumValue += sumN.sum;
countValue += sumN.n;
} else if (TrustedEntityType.CIS == entityType) {
final SumN sumN = this.retrieveSumNTrustValue(
trustorId, valueProperty, TrustedCis.class);
sumValue += sumN.sum;
countValue += sumN.n;
} else if (TrustedEntityType.SVC == entityType) {
final SumN sumN = this.retrieveSumNTrustValue(
trustorId, valueProperty, TrustedService.class);
sumValue += sumN.sum;
countValue += sumN.n;
} else {
throw new TrustRepositoryException("Unsupported entityType: "
+ entityType);
}
return (countValue > 0) ? sumValue / countValue : 0.0d;
}
/*
* @see org.societies.privacytrust.trust.api.repo.ITrustRepository#retrieveCssBySimilarity(org.societies.api.privacytrust.trust.model.TrustedEntityId, java.lang.Double, java.lang.Integer)
*/
@SuppressWarnings("unchecked")
@Override
public SortedSet<ITrustedCss> retrieveCssBySimilarity(
final TrustedEntityId trustorId, final Double similarityThreshold,
final Integer maxResults) throws TrustRepositoryException {
if (trustorId == null) {
throw new NullPointerException("trustorId can't be null");
}
if (maxResults != null && maxResults < 1) {
throw new IllegalArgumentException("maxResults can't be less than 1");
}
final SortedSet<ITrustedCss> result =
new TreeSet<ITrustedCss>(CssSimilarityComparator);
Session session = null;
try {
session = sessionFactory.openSession();
final Criteria criteria = session.createCriteria(TrustedCss.class)
.add(Restrictions.eq("trustorId", trustorId))
.addOrder(Order.desc("similarity"));
if (similarityThreshold != null) {
criteria.add(Restrictions.ge("similarity", similarityThreshold));
}
if (maxResults != null) {
criteria.setMaxResults(maxResults);
}
result.addAll(criteria.list());
} catch (Exception e) {
throw new TrustRepositoryException(e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
return result;
}
/*
* @see org.societies.privacytrust.trust.api.repo.ITrustRepository#removeEntities(org.societies.api.privacytrust.trust.model.TrustedEntityId, org.societies.api.privacytrust.trust.model.TrustedEntityType, org.societies.api.privacytrust.trust.model.TrustValueType)
*/
@Override
public boolean removeEntities(final TrustedEntityId trustorId,
final TrustedEntityType entityType, final TrustValueType valueType)
throws TrustRepositoryException {
final Class<? extends TrustedEntity> daClass;
if (null == entityType) {
daClass = null;
} else if (TrustedEntityType.CSS == entityType) {
daClass = TrustedCss.class;
} else if (TrustedEntityType.CIS == entityType) {
daClass = TrustedCis.class;
} else if (TrustedEntityType.SVC == entityType) {
daClass = TrustedService.class;
} else {
throw new TrustRepositoryException("Unsupported entityType: "
+ entityType);
}
final Set<ITrustedEntity> entities = new LinkedHashSet<ITrustedEntity>();
if (null != daClass) {
entities.addAll(this.doRetrieveEntities(trustorId, daClass, valueType));
} else {
entities.addAll(this.doRetrieveEntities(trustorId, TrustedCss.class, valueType));
entities.addAll(this.doRetrieveEntities(trustorId, TrustedCis.class, valueType));
entities.addAll(this.doRetrieveEntities(trustorId, TrustedService.class, valueType));
}
for (final ITrustedEntity entity : entities) {
this.removeEntity(entity.getTrustorId(), entity.getTrusteeId());
}
return (entities.isEmpty()) ? false : true;
}
@SuppressWarnings("unchecked")
private <T extends TrustedEntity> Set<T> doRetrieveEntities(
final TrustedEntityId trustorId, final Class<T> entityClass,
final TrustValueType valueType) throws TrustRepositoryException {
final Set<T> result = new LinkedHashSet<T>();
Session session = null;
try {
session = sessionFactory.openSession();
final Criteria criteria = session.createCriteria(entityClass);
if (trustorId != null) {
criteria.add(Restrictions.eq("trustorId", trustorId));
}
if (TrustValueType.DIRECT == valueType) {
criteria.add(Restrictions.isNotNull("directTrust.value"));
} else if (TrustValueType.INDIRECT == valueType) {
criteria.add(Restrictions.isNotNull("indirectTrust.value"));
} else if (TrustValueType.USER_PERCEIVED == valueType) {
criteria.add(Restrictions.isNotNull("userPerceivedTrust.value"));
}
result.addAll(criteria.list());
} catch (Exception e) {
throw new TrustRepositoryException(e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
return result;
}
@SuppressWarnings("unchecked")
private SumN retrieveSumNTrustValue(
final TrustedEntityId trustorId, final String valueProperty,
final Class<? extends TrustedEntity> entityClass)
throws TrustRepositoryException {
Session session = null;
try {
session = sessionFactory.openSession();
final Criteria criteria = session.createCriteria(entityClass)
.add(Restrictions.eq("trustorId", trustorId));
final ProjectionList projList = Projections.projectionList();
projList.add(Projections.sum(valueProperty));
projList.add(Projections.count(valueProperty));
criteria.setProjection(projList);
final List<Object[]> results = criteria.list();
double totalSum = 0.0d;
int totalCount = 0;
for (Object[] resultsEntry : results) {
if (resultsEntry[0] != null) {
totalSum += (Double) resultsEntry[0];
totalCount += (Integer) resultsEntry[1];
}
}
return new SumN(totalSum, totalCount);
} catch (Exception e) {
throw new TrustRepositoryException(e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
}
/**
* Utility class to calculate the mean.
*
* mean = sum / n;
*
* @since 1.1
*/
private class SumN {
private final double sum;
private final int n;
private SumN(final double sum, final int n) {
this.sum = sum;
this.n = n;
}
}
}