@Test
  public void testTimelinePutErrors() throws Exception {
    TimelinePutResponse TimelinePutErrors = new TimelinePutResponse();
    TimelinePutError error1 = new TimelinePutError();
    error1.setEntityId("entity id 1");
    error1.setEntityId("entity type 1");
    error1.setErrorCode(TimelinePutError.NO_START_TIME);
    TimelinePutErrors.addError(error1);
    List<TimelinePutError> response = new ArrayList<TimelinePutError>();
    response.add(error1);
    TimelinePutError error2 = new TimelinePutError();
    error2.setEntityId("entity id 2");
    error2.setEntityId("entity type 2");
    error2.setErrorCode(TimelinePutError.IO_EXCEPTION);
    response.add(error2);
    TimelinePutErrors.addErrors(response);
    LOG.info("Errors in JSON:");
    LOG.info(TimelineUtils.dumpTimelineRecordtoJSON(TimelinePutErrors, true));

    Assert.assertEquals(3, TimelinePutErrors.getErrors().size());
    TimelinePutError e = TimelinePutErrors.getErrors().get(0);
    Assert.assertEquals(error1.getEntityId(), e.getEntityId());
    Assert.assertEquals(error1.getEntityType(), e.getEntityType());
    Assert.assertEquals(error1.getErrorCode(), e.getErrorCode());
    e = TimelinePutErrors.getErrors().get(1);
    Assert.assertEquals(error1.getEntityId(), e.getEntityId());
    Assert.assertEquals(error1.getEntityType(), e.getEntityType());
    Assert.assertEquals(error1.getErrorCode(), e.getErrorCode());
    e = TimelinePutErrors.getErrors().get(2);
    Assert.assertEquals(error2.getEntityId(), e.getEntityId());
    Assert.assertEquals(error2.getEntityType(), e.getEntityType());
    Assert.assertEquals(error2.getErrorCode(), e.getErrorCode());
  }
 @Override
 public TimelinePutResponse put(TimelineEntities data) {
   TimelinePutResponse response = new TimelinePutResponse();
   for (TimelineEntity entity : data.getEntities()) {
     EntityIdentifier entityId =
         new EntityIdentifier(entity.getEntityId(), entity.getEntityType());
     // store entity info in memory
     TimelineEntity existingEntity = entities.get(entityId);
     if (existingEntity == null) {
       existingEntity = new TimelineEntity();
       existingEntity.setEntityId(entity.getEntityId());
       existingEntity.setEntityType(entity.getEntityType());
       existingEntity.setStartTime(entity.getStartTime());
       entities.put(entityId, existingEntity);
       entityInsertTimes.put(entityId, System.currentTimeMillis());
     }
     if (entity.getEvents() != null) {
       if (existingEntity.getEvents() == null) {
         existingEntity.setEvents(entity.getEvents());
       } else {
         existingEntity.addEvents(entity.getEvents());
       }
       Collections.sort(existingEntity.getEvents());
     }
     // check startTime
     if (existingEntity.getStartTime() == null) {
       if (existingEntity.getEvents() == null || existingEntity.getEvents().isEmpty()) {
         TimelinePutError error = new TimelinePutError();
         error.setEntityId(entityId.getId());
         error.setEntityType(entityId.getType());
         error.setErrorCode(TimelinePutError.NO_START_TIME);
         response.addError(error);
         entities.remove(entityId);
         entityInsertTimes.remove(entityId);
         continue;
       } else {
         Long min = Long.MAX_VALUE;
         for (TimelineEvent e : entity.getEvents()) {
           if (min > e.getTimestamp()) {
             min = e.getTimestamp();
           }
         }
         existingEntity.setStartTime(min);
       }
     }
     if (entity.getPrimaryFilters() != null) {
       if (existingEntity.getPrimaryFilters() == null) {
         existingEntity.setPrimaryFilters(new HashMap<String, Set<Object>>());
       }
       for (Entry<String, Set<Object>> pf : entity.getPrimaryFilters().entrySet()) {
         for (Object pfo : pf.getValue()) {
           existingEntity.addPrimaryFilter(pf.getKey(), maybeConvert(pfo));
         }
       }
     }
     if (entity.getOtherInfo() != null) {
       if (existingEntity.getOtherInfo() == null) {
         existingEntity.setOtherInfo(new HashMap<String, Object>());
       }
       for (Entry<String, Object> info : entity.getOtherInfo().entrySet()) {
         existingEntity.addOtherInfo(info.getKey(), maybeConvert(info.getValue()));
       }
     }
     // relate it to other entities
     if (entity.getRelatedEntities() == null) {
       continue;
     }
     for (Map.Entry<String, Set<String>> partRelatedEntities :
         entity.getRelatedEntities().entrySet()) {
       if (partRelatedEntities == null) {
         continue;
       }
       for (String idStr : partRelatedEntities.getValue()) {
         EntityIdentifier relatedEntityId =
             new EntityIdentifier(idStr, partRelatedEntities.getKey());
         TimelineEntity relatedEntity = entities.get(relatedEntityId);
         if (relatedEntity != null) {
           relatedEntity.addRelatedEntity(
               existingEntity.getEntityType(), existingEntity.getEntityId());
         } else {
           relatedEntity = new TimelineEntity();
           relatedEntity.setEntityId(relatedEntityId.getId());
           relatedEntity.setEntityType(relatedEntityId.getType());
           relatedEntity.setStartTime(existingEntity.getStartTime());
           relatedEntity.addRelatedEntity(
               existingEntity.getEntityType(), existingEntity.getEntityId());
           entities.put(relatedEntityId, relatedEntity);
           entityInsertTimes.put(relatedEntityId, System.currentTimeMillis());
         }
       }
     }
   }
   return response;
 }