@Override
 @SuppressWarnings("unchecked")
 public Conversation create(Conversation conv) {
   final Long id = getId(conv);
   if (template
           .opsForValue()
           .get(
               KeyUtils.conversationProductIdAndVisitorToken(
                   conv.getTopic().getProductId(), conv.getVisitor()))
       != null) {
     return findBy(id);
   }
   conv.setId(id);
   template.opsForHash().put(getIdKey(id), "id", id.toString());
   template.opsForHash().put(getIdKey(id), "topic", conv.getTopic().getId().toString());
   template.opsForHash().put(getIdKey(id), "visitor", conv.getVisitor());
   template.opsForHash().put(getIdKey(id), "visitorName", conv.getVisitorName());
   template
       .opsForHash()
       .put(getIdKey(id), "customerServiceUser", conv.getCustomerServiceUsername());
   template.opsForHash().put(getIdKey(id), "status", conv.getStatus().toString());
   template
       .opsForHash()
       .put(getIdKey(id), "createDate", String.valueOf(conv.getCreateDate().getTime()));
   template
       .opsForValue()
       .set(
           KeyUtils.conversationProductIdAndVisitorToken(
               conv.getTopic().getProductId(), conv.getVisitor()),
           id.toString());
   return conv;
 }
 public Conversation findByWithMessage(final Long convId) {
   Conversation result = findBy(convId);
   String messageQueue = KeyUtils.conversationMessage(convId);
   for (String msgId : template.opsForList().range(messageQueue, 0, 0)) {
     result.addMessage(messageDao.findBy(msgId));
   }
   return result;
 }
 private ConversationTopic createConversationTopic(String topicId) {
   ConversationTopic result = new ConversationTopic();
   result.setId(Long.valueOf(topicId));
   final String k = KeyUtils.conversationTopic(topicId);
   result.setProductId(template.opsForHash().get(k, "productId").toString());
   result.setDescription(template.opsForHash().get(k, "description").toString());
   result.setProductName(template.opsForHash().get(k, "productName").toString());
   result.setPicture(template.opsForHash().get(k, "picture").toString());
   return result;
 }
 protected Long getId(Conversation conv) {
   String id =
       template
           .opsForValue()
           .get(
               KeyUtils.conversationProductIdAndVisitorToken(
                   conv.getTopic().getProductId(), conv.getVisitor()));
   if (id != null) return Long.valueOf(id);
   if (conv.getId() == null) {
     return idCounter.incrementAndGet();
   }
   return conv.getId();
 }
 public List<Conversation> findByVisitor(String visitor, int pageFrom, int pageSize) {
   List<Conversation> result = new ArrayList<Conversation>();
   template.delete(KeyUtils.conversationVisitor(visitor));
   for (String k : template.keys(KeyUtils.conversationProductIdAndVisitorKey(visitor))) {
     template
         .opsForSet()
         .add(KeyUtils.conversationVisitor(visitor), template.opsForValue().get(k));
   }
   template.delete(KeyUtils.conversationWithMessageKey());
   for (String k : template.keys("conversation:*:messages")) {
     template
         .opsForSet()
         .add(KeyUtils.conversationWithMessageKey(), StringUtils.substringBetween(k, ":"));
   }
   template
       .opsForSet()
       .intersectAndStore(
           KeyUtils.conversationVisitor(visitor),
           KeyUtils.conversationWithMessageKey(),
           KeyUtils.conversationVisitor(visitor));
   List<String> sort =
       template.sort(
           SortQueryBuilder.sort(KeyUtils.conversationVisitor(visitor))
               .order(SortParameters.Order.DESC)
               .limit(pageFrom, pageSize)
               .build());
   for (String covId : sort) {
     Conversation c = findBy(Long.valueOf(covId));
     String messageQueue = KeyUtils.conversationMessage(Long.valueOf(covId));
     for (String msgId : template.opsForList().range(messageQueue, 0, 0)) {
       c.addMessage(messageDao.findBy(msgId));
       result.add(c);
     }
   }
   return result;
 }
 public List<Conversation> findBy(
     final String queueName, final int pageFrom, final int pageSize, String order) {
   List<Conversation> result = new ArrayList<Conversation>();
   List<String> sort =
       template.sort(
           SortQueryBuilder.sort(queueName)
               .order(SortParameters.Order.valueOf(StringUtils.upperCase(order)))
               .limit(pageFrom, pageSize)
               .build());
   for (String covId : sort) {
     Conversation c = findBy(Long.valueOf(covId));
     String messageQueue = KeyUtils.conversationMessage(Long.valueOf(covId));
     for (String msgId : template.opsForList().range(messageQueue, 0, 0)) {
       c.addMessage(messageDao.findBy(msgId));
     }
     result.add(c);
   }
   return result;
 }