package io.lumify.sql.model.notification; import com.google.inject.Inject; import com.google.inject.Singleton; import io.lumify.core.exception.LumifyException; import io.lumify.core.model.lock.LockRepository; import io.lumify.core.model.notification.*; import io.lumify.core.model.user.UserRepository; import io.lumify.core.model.workQueue.WorkQueueRepository; import io.lumify.core.user.User; import io.lumify.core.util.LumifyLogger; import io.lumify.core.util.LumifyLoggerFactory; import io.lumify.sql.model.HibernateSessionManager; import org.hibernate.HibernateException; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.json.JSONObject; import java.util.Date; import java.util.List; import java.util.UUID; @Singleton public class SqlUserNotificationRepository extends UserNotificationRepository { private static final LumifyLogger LOGGER = LumifyLoggerFactory.getLogger(SqlUserNotificationRepository.class); private final HibernateSessionManager sessionManager; @Inject public SqlUserNotificationRepository(HibernateSessionManager sessionManager) { this.sessionManager = sessionManager; } @Override public UserNotification createNotification(String userId, String title, String message, String actionEvent, JSONObject actionPayload, ExpirationAge expirationAge) { Date now = new Date(); String id = Long.toString(now.getTime()) + ":" + UUID.randomUUID().toString(); Session session = sessionManager.getSession(); Transaction transaction = null; try { transaction = session.beginTransaction(); SqlUserNotification notification = new SqlUserNotification(); notification.setId(id); notification.setUserId(userId); notification.setTitle(title); notification.setMessage(message); notification.setSentDate(now); notification.setExpirationAge(expirationAge); notification.setMarkedRead(false); if (actionEvent != null) { notification.setActionEvent(actionEvent); } if (actionPayload != null) { notification.setActionPayload(actionPayload); } session.save(notification); transaction.commit(); return notification; } catch (HibernateException e) { if (transaction != null) { transaction.rollback(); } throw new LumifyException("HibernateException while creating", e); } } @Override public UserNotification getNotification(String notificationId, User user) { String userId = user.getUserId(); Session session = sessionManager.getSession(); List<UserNotification> notifications = session.createCriteria(SqlUserNotification.class) .add(Restrictions.eq("id", notificationId)) .add(Restrictions.eq("userId", userId)) .list(); if (notificationId.length() != 1) { throw new LumifyException("failed to find a user notification with id = " + notificationId + " and user_id = " + userId); } return notifications.get(0); } @Override public void markRead(String[] notificationIds, User user) { for (String notificationId : notificationIds) { markRead(notificationId, user); } } private String dateFunction(Dialect dialect, ExpirationAgeUnit eau) { if (dialect.getClass() == org.hibernate.dialect.MySQL5InnoDBDialect.class) { return String.format("DATE_ADD(sent_date, INTERVAL expiration_age_amount %s)", eau.getMysqlInterval()); } else if (dialect.getClass() == org.hibernate.dialect.H2Dialect.class) { return String.format("DATEADD('%s', expiration_age_amount, sent_date)", eau.getH2unit()); } else { throw new LumifyException("unsupported Hibernate dialect: " + dialect.getClass().getName()); } } private StringBuilder appendCaseStatement(StringBuilder sql, Dialect dialect) { sql.append(" CASE expiration_age_unit"); for (ExpirationAgeUnit eau : ExpirationAgeUnit.values()) { sql.append(" WHEN '").append(eau.toString()).append("' THEN ").append(dateFunction(dialect, eau)).append(" >= :now"); } return sql.append(" END"); } @Override public List<UserNotification> getActiveNotifications(User user) { Session session = sessionManager.getSession(); Dialect dialect = ((SessionFactoryImplementor) session.getSessionFactory()).getDialect(); StringBuilder sql = new StringBuilder("SELECT * from user_notification WHERE user_id = :userId AND sent_date <= :now AND"); sql = appendCaseStatement(sql, dialect); SQLQuery query = session.createSQLQuery(sql.toString()); query.setString("userId", user.getUserId()); query.setDate("now", new Date()); List<UserNotification> activeNotifications = query.list(); LOGGER.debug("returning %d active user notifications", activeNotifications.size()); return activeNotifications; } public void markRead(String notificationId, User user) { Session session = sessionManager.getSession(); Transaction transaction = null; try { transaction = session.beginTransaction(); String userId = user.getUserId(); List<UserNotification> notifications = session.createCriteria(SqlUserNotification.class) .add(Restrictions.eq("id", notificationId)) .add(Restrictions.eq("userId", userId)) .list(); if (notificationId.length() != 1) { throw new LumifyException("failed to find a user notification with id = " + notificationId + " and user_id = " + userId); } UserNotification notification = notifications.get(0); notification.setMarkedRead(true); session.update(notification); transaction.commit(); } catch (HibernateException e) { if (transaction != null) { transaction.rollback(); } throw new LumifyException("HibernateException while marking read", e); } } }