/**
* 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.user.db.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
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.event.CtxChangeEvent;
import org.societies.api.context.model.CtxAssociation;
import org.societies.api.context.model.CtxAssociationIdentifier;
import org.societies.api.context.model.CtxAttribute;
import org.societies.api.context.model.CtxAttributeIdentifier;
import org.societies.api.context.model.CtxEntity;
import org.societies.api.context.model.CtxEntityIdentifier;
import org.societies.api.context.model.CtxIdentifier;
import org.societies.api.context.model.CtxModelObject;
import org.societies.api.context.model.CtxModelType;
import org.societies.api.context.model.IndividualCtxEntity;
import org.societies.api.internal.context.model.CtxAssociationTypes;
import org.societies.context.api.event.CtxChangeEventTopic;
import org.societies.context.api.event.CtxEventScope;
import org.societies.context.api.event.ICtxEventMgr;
import org.societies.context.api.user.db.IUserCtxDBMgr;
import org.societies.context.user.db.impl.model.CtxAssociationDAO;
import org.societies.context.user.db.impl.model.CtxAttributeDAO;
import org.societies.context.user.db.impl.model.CtxEntityDAO;
import org.societies.context.user.db.impl.model.CtxModelDAOTranslator;
import org.societies.context.user.db.impl.model.CtxModelObjectDAO;
import org.societies.context.user.db.impl.model.CtxQualityDAO;
import org.societies.context.user.db.impl.model.IndividualCtxEntityDAO;
import org.societies.context.user.db.impl.model.UserCtxModelObjectNumberDAO;
import org.societies.context.user.db.impl.model.hibernate.CtxEntityIdentifierType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Implementation of the {@link IUserCtxDBMgr} interface.
*
* @author
* @since 0.0.1
*/
@Service("userCtxDBMgr")
public class UserCtxDBMgr implements IUserCtxDBMgr {
/** The logging facility. */
private static final Logger LOG = LoggerFactory.getLogger(UserCtxDBMgr.class);
@Autowired
private SessionFactory sessionFactory;
/** The Context Event Mgmt service reference. */
@Autowired(required=true)
private ICtxEventMgr ctxEventMgr;
private final String privateId;
@Autowired(required=true)
UserCtxDBMgr (ICommManager commMgr) {
LOG.info("{} instantiated", this.getClass());
this.privateId = commMgr.getIdManager().getThisNetworkNode().getBareJid();
LOG.debug("privateId={}", this.privateId);
}
/*
* Used for JUnit testing only
*/
public UserCtxDBMgr() {
LOG.info("{} instantiated - fooId", this.getClass());
// TODO !!!!!! Identity should be instantiated properly
this.privateId = null;
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#createAssociation(java.lang.String)
*/
@Override
public CtxAssociation createAssociation(String type) throws CtxException {
if (type == null) {
throw new NullPointerException("type can't be null");
}
final Long modelObjectNumber = this.generateNextObjectNumber();
final CtxAssociationIdentifier id = new CtxAssociationIdentifier(
this.privateId, type, modelObjectNumber);
final CtxAssociationDAO associationDAO = new CtxAssociationDAO(id);
final Session session = sessionFactory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
session.save(associationDAO);
tx.commit();
}
catch (Exception e) {
if (tx != null) {
tx.rollback();
}
throw new UserCtxDBMgrException("Could not create association of type '"
+ type + "': " + e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
if (!associationDAO.getEventTopics().isEmpty()) {
final CtxChangeEvent event = new CtxChangeEvent(associationDAO.getId());
final String[] eventTopics = associationDAO.getEventTopics().toArray(new String[0]);
final CtxEventScope eventScope = CtxEventScope.BROADCAST;
if (LOG.isDebugEnabled())
LOG.debug("Sending context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "'");
if (this.ctxEventMgr != null)
this.ctxEventMgr.post(event, eventTopics, eventScope);
else
LOG.error("Could not send context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "': "
+ "ICtxEventMgr service is not available");
}
return (CtxAssociation) this.retrieve(id);
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#createAttribute(org.societies.api.context.model.CtxEntityIdentifier, java.lang.String)
*/
@Override
public CtxAttribute createAttribute(final CtxEntityIdentifier scope,
final String type) throws CtxException {
if (scope == null) {
throw new NullPointerException("scope can't be null");
}
if (type == null) {
throw new NullPointerException("type can't be null");
}
final CtxEntityDAO entityDAO;
try {
entityDAO = this.retrieve(CtxEntityDAO.class, scope);
} catch (Exception e) {
throw new UserCtxDBMgrException("Could not create attribute of type '"
+ type + "': " + e.getLocalizedMessage(), e);
}
if (entityDAO == null) {
throw new UserCtxDBMgrException("Could not create attribute of type '"
+ type + "': Scope not found: " + scope);
}
final Long modelObjectNumber = this.generateNextObjectNumber();
final CtxAttributeIdentifier id =
new CtxAttributeIdentifier(scope, type, modelObjectNumber);
final CtxAttributeDAO attributeDAO = new CtxAttributeDAO(id);
final CtxQualityDAO qualityDAO = new CtxQualityDAO(id);
attributeDAO.setQuality(qualityDAO);
entityDAO.addAttribute(attributeDAO);
final Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.save(attributeDAO);
tx.commit();
} catch (Exception e) {
if (tx != null) {
tx.rollback();
}
throw new UserCtxDBMgrException("Could not create attribute of type '"
+ type + "': " + e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
if (!attributeDAO.getEventTopics().isEmpty()) {
final CtxChangeEvent event = new CtxChangeEvent(attributeDAO.getId());
final String[] eventTopics = attributeDAO.getEventTopics().toArray(new String[0]);
final CtxEventScope eventScope = CtxEventScope.BROADCAST;
if (LOG.isDebugEnabled())
LOG.debug("Sending context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "'");
if (this.ctxEventMgr != null)
this.ctxEventMgr.post(event, eventTopics, eventScope);
else
LOG.error("Could not send context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "': "
+ "ICtxEventMgr service is not available");
}
return (CtxAttribute) this.retrieve(id);
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#createEntity(java.lang.String)
*/
@Override
public CtxEntity createEntity(String type) throws CtxException {
if (type == null) {
throw new NullPointerException("type can't be null");
}
final Long modelObjectNumber = this.generateNextObjectNumber();
final CtxEntityIdentifier id =
new CtxEntityIdentifier(this.privateId, type, modelObjectNumber);
final CtxEntityDAO entityDAO = new CtxEntityDAO(id);
final Session session = sessionFactory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
session.save(entityDAO);
tx.commit();
}
catch (Exception e) {
if (tx != null) {
tx.rollback();
}
throw new UserCtxDBMgrException("Could not create entity of type '"
+ "': " + e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
if (!entityDAO.getEventTopics().isEmpty()) {
final CtxChangeEvent event = new CtxChangeEvent(entityDAO.getId());
final String[] eventTopics = entityDAO.getEventTopics().toArray(new String[0]);
final CtxEventScope eventScope = CtxEventScope.BROADCAST;
if (LOG.isDebugEnabled())
LOG.debug("Sending context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "'");
if (this.ctxEventMgr != null)
this.ctxEventMgr.post(event, eventTopics, eventScope);
else
LOG.error("Could not send context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "': "
+ "ICtxEventMgr service is not available");
}
return (CtxEntity) this.retrieve(id);
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#createIndividualEntity(java.lang.String, java.lang.String)
*/
@Override
public IndividualCtxEntity createIndividualEntity(final String ownerId,
final String type) throws CtxException {
if (ownerId == null) {
throw new NullPointerException("ownerId can't be null");
}
if (type == null) {
throw new NullPointerException("type can't be null");
}
final Long modelObjectNumber = this.generateNextObjectNumber();
final CtxEntityIdentifier id =
new CtxEntityIdentifier(ownerId, type, modelObjectNumber);
final IndividualCtxEntityDAO entityDAO = new IndividualCtxEntityDAO(id);
final Session session = sessionFactory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
session.save(entityDAO);
tx.commit();
}
catch (Exception e) {
if (tx != null) {
tx.rollback();
}
throw new UserCtxDBMgrException("Could not create individual entity of type '"
+ type + "': " + e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
// create IS_MEMBER_OF association for new IndividualCtxEntity
final CtxAssociation isMemberOfAssoc = this.createAssociation(CtxAssociationTypes.IS_MEMBER_OF);
isMemberOfAssoc.setParentEntity(id);
this.update(isMemberOfAssoc);
// create IS_ADMIN_OF association for new IndividualCtxEntity
final CtxAssociation isAdminOfAssoc = this.createAssociation(CtxAssociationTypes.IS_ADMIN_OF);
isAdminOfAssoc.setParentEntity(id);
this.update(isAdminOfAssoc);
if (!entityDAO.getEventTopics().isEmpty()) {
final CtxChangeEvent event = new CtxChangeEvent(entityDAO.getId());
final String[] eventTopics = entityDAO.getEventTopics().toArray(new String[0]);
final CtxEventScope eventScope = CtxEventScope.BROADCAST;
if (LOG.isDebugEnabled())
LOG.debug("Sending context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "'");
if (this.ctxEventMgr != null)
this.ctxEventMgr.post(event, eventTopics, eventScope);
else
LOG.error("Could not send context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "': "
+ "ICtxEventMgr service is not available");
}
return (IndividualCtxEntity) this.retrieve(id);
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#retrieveIndividualEntity(java.lang.String)
*/
@Override
public IndividualCtxEntity retrieveIndividualEntity(final String ownerId)
throws CtxException {
if (ownerId == null) {
throw new NullPointerException("ownerId can't be null");
}
final IndividualCtxEntity entity;
final Session session = this.sessionFactory.openSession();
try {
final Query query = session.getNamedQuery("getIndividualCtxEntityIdByOwnerId");
query.setParameter("ownerId", ownerId, Hibernate.STRING);
final CtxEntityIdentifier entityId = (CtxEntityIdentifier) query.uniqueResult();
if (entityId != null) {
entity = (IndividualCtxEntity) this.retrieve(entityId);
} else {
entity = null;
}
} catch (Exception e) {
throw new UserCtxDBMgrException("Could not retrieve individual entity for CSS '"
+ ownerId + "': " + e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
return entity;
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#lookup(java.lang.String, java.util.Set)
*/
@Override
public Set<CtxIdentifier> lookup(final String ownerId, final Set<String> types)
throws CtxException {
if (ownerId == null) {
throw new NullPointerException("ownerId can't be null");
}
if (types == null) {
throw new NullPointerException("types can't be null");
}
if (types.isEmpty()) {
throw new IllegalArgumentException("types can't be empty");
}
LOG.debug("lookup: ownerId={}, types={}", ownerId, types);
final Set<CtxIdentifier> result = new LinkedHashSet<CtxIdentifier>();
result.addAll(this.lookup(ownerId, CtxModelType.ENTITY, types));
result.addAll(this.lookup(ownerId, CtxModelType.ATTRIBUTE, types));
result.addAll(this.lookup(ownerId, CtxModelType.ASSOCIATION, types));
LOG.debug("lookup: result={}", result);
return result;
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#lookup(java.lang.String, org.societies.api.context.model.CtxModelType, java.util.Set)
*/
@SuppressWarnings("unchecked")
@Override
public Set<CtxIdentifier> lookup(final String ownerId,
final CtxModelType modelType, final Set<String> types)
throws CtxException {
if (ownerId == null) {
throw new NullPointerException("ownerId can't be null");
}
if (modelType == null) {
throw new NullPointerException("modelType can't be null");
}
if (types == null) {
throw new NullPointerException("types can't be null");
}
if (types.isEmpty()) {
throw new IllegalArgumentException("types can't be empty");
}
LOG.debug("lookup: ownerId={}, modelType={}, types={}",
new Object[] { ownerId, modelType, types });
final Set<CtxIdentifier> result = new LinkedHashSet<CtxIdentifier>();
final Session session = sessionFactory.openSession();
try {
final Query query;
switch (modelType) {
case ENTITY:
// lookup for entities
query = session.getNamedQuery("getCtxEntityIdsByOwnerIdAndType");
break;
case ATTRIBUTE:
// lookup for attributes
query = session.getNamedQuery("getCtxAttributeIdsByOwnerIdAndType");
break;
case ASSOCIATION:
// lookup for associations
query = session.getNamedQuery("getCtxAssociationIdsByOwnerIdAndType");
break;
default:
throw new IllegalArgumentException("Unsupported context model type: " + modelType);
}
for (final String type : types) {
query.setParameter("ownerId", ownerId, Hibernate.STRING);
query.setParameter("type", type, Hibernate.STRING);
result.addAll(query.list());
}
} catch (Exception e) {
throw new UserCtxDBMgrException(e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
LOG.debug("lookup: result={}", result);
return result;
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#lookup(CtxEntityIdentifier, CtxModelType, Set)
*/
@SuppressWarnings("unchecked")
@Override
public Set<CtxIdentifier> lookup(final CtxEntityIdentifier scope,
final CtxModelType modelType, final Set<String> types) throws CtxException {
if (scope == null) {
throw new NullPointerException("scope can't be null");
}
if (modelType == null) {
throw new NullPointerException("modelType can't be null");
}
if (types == null) {
throw new NullPointerException("types can't be null");
}
if (types.isEmpty()) {
throw new IllegalArgumentException("types can't be empty");
}
LOG.debug("lookup: scope={}, modelType={}, types={}",
new Object[] { scope, modelType, types });
final Set<CtxIdentifier> result = new LinkedHashSet<CtxIdentifier>();
final Session session = sessionFactory.openSession();
try {
for (final String type : types) {
switch (modelType) {
case ATTRIBUTE:
// lookup for attributes
final Query query = session.getNamedQuery("getCtxAttributeIdsByScopeAndType");
query.setParameter("scope", scope.toString(), Hibernate.STRING);
query.setParameter("type", type, Hibernate.STRING);
result.addAll(query.list());
break;
case ASSOCIATION:
// lookup for associations
final Query childQuery = session.getNamedQuery("getCtxAssociationIdsByChildEntityIdAndType");
childQuery.setParameter("childEntId", scope, Hibernate.custom(CtxEntityIdentifierType.class));
childQuery.setParameter("type", type, Hibernate.STRING);
result.addAll(childQuery.list());
final Query parentQuery = session.getNamedQuery("getCtxAssociationsByParentEntityIdAndType");
parentQuery.setParameter("parentEntId", scope, Hibernate.custom(CtxEntityIdentifierType.class));
parentQuery.setParameter("type", type, Hibernate.STRING);
result.addAll(parentQuery.list());
break;
default:
throw new IllegalArgumentException("Unsupported context model type: " + modelType);
}
}
} catch (Exception e) {
throw new UserCtxDBMgrException(e.getLocalizedMessage(), e);
} finally {
if (session != null) {
session.close();
}
}
LOG.debug("lookup: result={}", result);
return result;
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#lookupEntities(java.lang.String, java.lang.String, java.io.Serializable, java.io.Serializable)
*/
@SuppressWarnings("unchecked")
@Override
public List<CtxEntityIdentifier> lookupEntities(String entityType,
String attribType, Serializable minAttribValue,
Serializable maxAttribValue) throws CtxException {
if (entityType == null)
throw new NullPointerException("entityType can't be null");
if (attribType == null)
throw new NullPointerException("attribType can't be null");
final List<CtxEntityIdentifier> foundList = new ArrayList<CtxEntityIdentifier>();
final Session session = sessionFactory.openSession();
final Query query;
try {
if (minAttribValue instanceof String && maxAttribValue instanceof String) {
query = session.getNamedQuery("getCtxEntityIdsByAttrStringValue");
query.setParameter("entType", entityType, Hibernate.STRING);
query.setParameter("attrType", attribType, Hibernate.STRING);
query.setParameter("minAttribValue", (String) minAttribValue, Hibernate.STRING);
query.setParameter("maxAttribValue", (String) maxAttribValue, Hibernate.STRING);
} else if (minAttribValue instanceof Integer && maxAttribValue instanceof Integer) {
query = session.getNamedQuery("getCtxEntityIdsByAttrIntegerValue");
query.setParameter("entType", entityType, Hibernate.STRING);
query.setParameter("attrType", attribType, Hibernate.STRING);
query.setParameter("minAttribValue", (Integer) minAttribValue, Hibernate.INTEGER);
query.setParameter("maxAttribValue", (Integer) maxAttribValue, Hibernate.INTEGER);
} else if (minAttribValue instanceof Double && maxAttribValue instanceof Double) {
query = session.getNamedQuery("getCtxEntityIdsByAttrDoubleValue");
query.setParameter("entType", entityType, Hibernate.STRING);
query.setParameter("attrType", attribType, Hibernate.STRING);
query.setParameter("minAttribValue", (Double) minAttribValue, Hibernate.DOUBLE);
query.setParameter("maxAttribValue", (Double) maxAttribValue, Hibernate.DOUBLE);
} else if (minAttribValue instanceof byte[]) {
query = session.getNamedQuery("getCtxEntityIdsByAttrBinaryValue");
query.setParameter("entType", entityType, Hibernate.STRING);
query.setParameter("attrType", attribType, Hibernate.STRING);
query.setParameter("minAttribValue", (byte[]) minAttribValue, Hibernate.BINARY);
} else {
throw new UserCtxDBMgrException("Unsupported attribute value types: "
+ "minAttribValue=" + minAttribValue.getClass().getName()
+ ", maxAttribValue=" + maxAttribValue.getClass().getName());
}
foundList.addAll(query.list());
} catch (Exception e) {
throw new UserCtxDBMgrException("Could not lookup context entities of type '"
+ entityType + "': " + e.getLocalizedMessage(), e);
} finally {
if (session != null)
session.close();
}
return foundList;
}
@Override
public CtxModelObject remove(CtxIdentifier id) throws CtxException {
if (id == null)
throw new NullPointerException("id can't be null");
final CtxModelObject result = this.retrieve(id);
if (result == null)
return null;
final Session session = sessionFactory.openSession();
Transaction tx = null;
CtxModelObjectDAO dao = CtxModelDAOTranslator.getInstance().fromCtxModelObject(result);
try{
tx = session.beginTransaction();
session.delete(dao);
session.flush();
tx.commit();
}
catch (Exception e) {
if (tx != null)
tx.rollback();
throw new UserCtxDBMgrException("Could not remove entity '" + id
+ "': " + e.getLocalizedMessage(), e);
} finally {
if (session != null)
session.close();
}
if (!dao.getEventTopics().isEmpty()) {
final CtxChangeEvent event = new CtxChangeEvent(dao.getId());
final String[] eventTopics = dao.getEventTopics().toArray(new String[0]);
final CtxEventScope eventScope = CtxEventScope.BROADCAST;
if (LOG.isDebugEnabled())
LOG.debug("Sending context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "'");
if (this.ctxEventMgr != null)
this.ctxEventMgr.post(event, eventTopics, eventScope);
else
LOG.error("Could not send context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "': "
+ "ICtxEventMgr service is not available");
}
return result;
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#retrieve(org.societies.api.context.model.CtxIdentifier)
*/
@SuppressWarnings("unchecked")
@Override
public CtxModelObject retrieve(CtxIdentifier id) throws CtxException {
final CtxModelObject result;
final CtxModelObjectDAO dao;
try {
switch (id.getModelType()) {
case ENTITY:
dao = this.retrieve(CtxEntityDAO.class, id);
if (dao == null)
break;
final Session session = this.sessionFactory.openSession();
Query query;
// CtxAssociations where this entity is member of
final Set<CtxAssociationIdentifier> associationIds =
new HashSet<CtxAssociationIdentifier>();
try {
if (dao instanceof IndividualCtxEntityDAO) {
final Set<CtxEntityIdentifier> communityIds =
new HashSet<CtxEntityIdentifier>();
// Retrieve CtxAssociations where this entity is parent
query = session.getNamedQuery("getCtxAssociationsByParentEntityId");
query.setParameter("parentEntId", ((CtxEntityDAO) dao).getId(),
Hibernate.custom(CtxEntityIdentifierType.class));
final List<CtxAssociationDAO> associations = query.list();
for (final CtxAssociationDAO association : associations) {
associationIds.add(association.getId());
if (CtxAssociationTypes.IS_MEMBER_OF.equals(association.getId().getType()))
communityIds.addAll(association.getChildEntities());
}
((IndividualCtxEntityDAO) dao).setCommunities(communityIds);
// Retrieve CtxAssociationIds where this entity is child
query = session.getNamedQuery("getCtxAssociationIdsByChildEntityId");
query.setParameter("childEntId", ((CtxEntityDAO) dao).getId(),
Hibernate.custom(CtxEntityIdentifierType.class));
associationIds.addAll(query.list());
} else if (dao instanceof CtxEntityDAO) {
// Retrieve CtxAssociationIds where this entity is parent
query = session.getNamedQuery("getCtxAssociationIdsByParentEntityId");
query.setParameter("parentEntId", ((CtxEntityDAO) dao).getId(),
Hibernate.custom(CtxEntityIdentifierType.class));
associationIds.addAll(query.list());
// Retrieve CtxAssociationIds where this entity is child
query = session.getNamedQuery("getCtxAssociationIdsByChildEntityId");
query.setParameter("childEntId", ((CtxEntityDAO) dao).getId(),
Hibernate.custom(CtxEntityIdentifierType.class));
associationIds.addAll(query.list());
}
((CtxEntityDAO) dao).setAssociations(associationIds);
} finally {
if (session != null)
session.close();
}
break;
case ATTRIBUTE:
dao = this.retrieve(CtxAttributeDAO.class, id);
break;
case ASSOCIATION:
dao = this.retrieve(CtxAssociationDAO.class, id);
break;
default:
throw new UserCtxDBMgrException("Could not retrieve '"
+ id + "': Unsupported CtxModelType: " + id.getModelType());
}
if (dao == null)
return null;
result = CtxModelDAOTranslator.getInstance().fromCtxModelObjectDAO(dao);
} catch (Exception e) {
throw new UserCtxDBMgrException("Could not retrieve '"
+ id + "': " + e.getLocalizedMessage(), e);
}
return result;
}
/*
* @see org.societies.context.api.user.db.IUserCtxDBMgr#update(org.societies.api.context.model.CtxModelObject)
*/
@Override
public CtxModelObject update(CtxModelObject modelObject) throws CtxException {
if (modelObject == null)
throw new NullPointerException("modelObject can't be null");
final Session session = sessionFactory.openSession();
Transaction tx = null;
CtxModelObjectDAO modelObjectDAO = CtxModelDAOTranslator.getInstance().fromCtxModelObject(modelObject);
try {
tx = session.beginTransaction();
modelObjectDAO = (CtxModelObjectDAO) session.merge(modelObjectDAO);
session.flush();
tx.commit();
} catch (Exception e) {
if (tx != null)
tx.rollback();
throw new UserCtxDBMgrException("Could not update '"
+ modelObject + "': " + e.getLocalizedMessage(), e);
} finally {
if (session != null)
session.close();
}
final CtxChangeEvent event = new CtxChangeEvent(modelObjectDAO.getId());
modelObjectDAO.getEventTopics().add(CtxChangeEventTopic.UPDATED);
final String[] eventTopics = modelObjectDAO.getEventTopics().toArray(new String[0]);
final CtxEventScope eventScope = CtxEventScope.BROADCAST;
if (LOG.isDebugEnabled())
LOG.debug("Sending context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "'");
if (this.ctxEventMgr != null)
this.ctxEventMgr.post(event, eventTopics, eventScope);
else
LOG.error("Could not send context change event " + event
+ " to topics '" + Arrays.toString(eventTopics)
+ "' with scope '" + eventScope + "': "
+ "ICtxEventMgr service is not available");
return this.retrieve(modelObject.getId());
}
@SuppressWarnings("unchecked")
private <T extends CtxModelObjectDAO> T retrieve(
final Class<T> modelObjectClass,
final CtxIdentifier ctxId) throws Exception {
T result = null;
final Session session = sessionFactory.openSession();
try {
final Criteria criteria = session.createCriteria(modelObjectClass)
.add(Restrictions.eq("ctxId", ctxId));
result = (T) criteria.uniqueResult();
} finally {
if (session != null)
session.close();
}
return result;
}
@SuppressWarnings({ "unchecked", "unused" })
private <T extends CtxModelObjectDAO> Set<T> retrieve(
final Class<T> modelObjectClass,
final String type, final Date startDate,
final Date endDate) throws Exception {
final Set<T> result = new HashSet<T>();
final Session session = sessionFactory.openSession();
try {
final Criteria criteria = session.createCriteria(modelObjectClass);
if (type != null)
criteria.add(Restrictions.eq("type", type));
if (startDate != null)
criteria.add(Restrictions.ge("lastModified", startDate));
if (endDate != null)
criteria.add(Restrictions.le("lastModified", endDate));
result.addAll(criteria.list());
} finally {
if (session != null)
session.close();
}
return result;
}
private Long generateNextObjectNumber() throws UserCtxDBMgrException {
final UserCtxModelObjectNumberDAO objectNumberDAO =
new UserCtxModelObjectNumberDAO();
final Session session = this.sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.save(objectNumberDAO);
tx.commit();
} catch (Exception e) {
if (tx != null)
tx.rollback();
throw new UserCtxDBMgrException(
"Could not generate next context model object number");
} finally {
if (session != null)
session.close();
}
return objectNumberDAO.getNextValue();
}
}