public List<NotificationEntry> getNotifications(String username, String startId) {
   try {
     byte[] timeUUIDAsBytes = EMPTY_BYTE_ARRAY;
     if (startId != null && startId.length() > 0) {
       UUID uuid = UUIDUtil.fromString(startId);
       final byte[] idAsBytes = UUIDUtil.toBytes(uuid);
       timeUUIDAsBytes = getTimeUUIDFromID(username, idAsBytes);
       if (timeUUIDAsBytes == null) {
         timeUUIDAsBytes = EMPTY_BYTE_ARRAY;
       }
     }
     Selector selector = Pelops.createSelector(TRENDOCEAN_POOL, TRENDOCEAN_KEYSPACE);
     SlicePredicate columnPredicate =
         Selector.newColumnsPredicate(timeUUIDAsBytes, EMPTY_BYTE_ARRAY, true, PAGE_SIZE);
     List<SuperColumn> columns =
         selector.getSuperColumnsFromRow(username, WALL_CF, columnPredicate, ConsistencyLevel.ONE);
     List<NotificationEntry> notificationList = new ArrayList<NotificationEntry>(columns.size());
     for (SuperColumn superColumn : columns) {
       List<Column> wallEntryColumns = superColumn.getColumns();
       String notificationId = null;
       NotificationType notificationType = null;
       String questionId = null;
       String relatedUser = null;
       long answerCount = -1L;
       long time = 0;
       for (Column notificationColumn : wallEntryColumns) {
         String notificationColumnName = toString(notificationColumn.getName());
         if (notificationColumnName.equals("_id")) {
           notificationId = UUIDUtil.toUUID(notificationColumn.getValue()).toString();
           long timeInMicroSeconds = notificationColumn.getTimestamp();
           time = timeInMicroSeconds / 1000L;
         } else if (notificationColumnName.equals("_type")) {
           notificationType = NotificationType.fromId(toByte(notificationColumn));
         } else if (notificationColumnName.equals("questionId")) {
           questionId = toString(notificationColumn);
         } else if (notificationColumnName.equals("relatedUser")) {
           relatedUser = toString(notificationColumn);
         } else if (notificationColumnName.equals("answerCount")) {
           answerCount = toLong(notificationColumn);
         } else {
           logger.warn("Invalid notification column:{}", notificationColumnName);
         }
       }
       NotificationEntry notificationEntry = new NotificationEntry();
       notificationEntry.setId(notificationId);
       notificationEntry.setTime(time);
       notificationEntry.setNotificationType(notificationType);
       notificationEntry.setQuestionId(questionId);
       notificationList.add(notificationEntry);
       notificationEntry.setUsername(relatedUser);
       notificationEntry.setAnswerCount(answerCount);
     }
     return notificationList;
   } catch (NotFoundException ex) {
     return Collections.EMPTY_LIST;
   } catch (Exception ex) {
     logger.error("Can not get time uuid", ex);
     throw new TrendOceanException(ex);
   }
 }
  /** Add a new comment entry for a user. */
  public void addNotification(
      String username,
      String relatedUser,
      String questionId,
      long answerCount,
      NotificationType notificationType) {
    try {
      Mutator mutator = Pelops.createMutator(TRENDOCEAN_POOL, TRENDOCEAN_KEYSPACE);
      byte[] timeUUIDBytes = UUIDUtil.toBytes(UUIDUtil.getTimeUUID());
      UUID id = UUIDUtil.getRandomUUID();
      byte[] idAsBytes = UUIDUtil.toBytes(id);

      // add new notification
      if (notificationType == NotificationType.COMMENT
          || notificationType == NotificationType.LIKE
          || notificationType == NotificationType.MENTION) {
        mutator.writeSubColumns(
            username,
            WALL_CF,
            timeUUIDBytes,
            mutator.newColumnList(
                mutator.newColumn("_id", idAsBytes),
                mutator.newColumn("_type", toBytes(notificationType.getId())),
                mutator.newColumn("questionId", toBytes(questionId)),
                mutator.newColumn("relatedUser", relatedUser)));
      } else if (notificationType == NotificationType.NEW_FOLLOWER
          || notificationType == NotificationType.FOLLOW_REQUEST_ACCEPT) {
        mutator.writeSubColumns(
            username,
            WALL_CF,
            timeUUIDBytes,
            mutator.newColumnList(
                mutator.newColumn("_id", idAsBytes),
                mutator.newColumn("_type", toBytes(notificationType.getId())),
                mutator.newColumn("relatedUser", relatedUser)));
      } else if (notificationType == NotificationType.ANSWER_COUNT) {
        mutator.writeSubColumns(
            username,
            WALL_CF,
            timeUUIDBytes,
            mutator.newColumnList(
                mutator.newColumn("_id", idAsBytes),
                mutator.newColumn("_type", toBytes(notificationType.getId())),
                mutator.newColumn("questionId", toBytes(questionId)),
                mutator.newColumn("answerCount", toBytes(answerCount))));
      }

      // write reverse mapping for delete
      mutator.writeColumn(username, ID_TO_TIMEUUID_CF, mutator.newColumn(idAsBytes, timeUUIDBytes));
      mutator.execute(ConsistencyLevel.QUORUM);
    } catch (Exception ex) {
      logger.error("Can not add follow entry", username + ":" + questionId, ex);
      throw new TrendOceanException(ex);
    }
  }
 private byte[] getTimeUUIDFromID(String username, byte[] idAsBytes) {
   try {
     Selector selector = Pelops.createSelector(TRENDOCEAN_POOL, TRENDOCEAN_KEYSPACE);
     Column column =
         selector.getColumnFromRow(username, ID_TO_TIMEUUID_CF, idAsBytes, ConsistencyLevel.ONE);
     byte[] timeUUIDAsBytes = column.getValue();
     return timeUUIDAsBytes;
   } catch (NotFoundException ex) {
     return null;
   } catch (Exception ex) {
     logger.error("Can not get time uuid", ex);
     throw new TrendOceanException(ex);
   }
 }
  /**
   * Delete the entry from wall.
   *
   * @param followEntry
   */
  public void deleteEntry(String username, String id) {
    try {
      // find name of super column using reverse mapping from id to time
      UUID uuid = UUIDUtil.fromString(id);
      final byte[] idAsBytes = UUIDUtil.toBytes(uuid);
      byte[] timeUUIDAsBytes = getTimeUUIDFromID(username, idAsBytes);
      if (timeUUIDAsBytes == null) {
        throw new TrendOceanException("Can not find time uuid " + username + ":" + id);
      }

      // delete super column from wall cf
      Mutator mutator = Pelops.createMutator(TRENDOCEAN_POOL, TRENDOCEAN_KEYSPACE);
      mutator.deleteColumn(username, WALL_CF, timeUUIDAsBytes);

      // also delete from reverse mapping from id to time
      mutator.deleteColumn(username, ID_TO_TIMEUUID_CF, idAsBytes);

      mutator.execute(ConsistencyLevel.QUORUM);
    } catch (Exception ex) {
      logger.error("Can not delete follow entry", username + ":" + id, ex);
      throw new TrendOceanException(ex);
    }
  }