private static TimelineEntity maskFields(TimelineEntity entity, EnumSet<Field> fields) {
   // Conceal the fields that are not going to be exposed
   TimelineEntity entityToReturn = new TimelineEntity();
   entityToReturn.setEntityId(entity.getEntityId());
   entityToReturn.setEntityType(entity.getEntityType());
   entityToReturn.setStartTime(entity.getStartTime());
   // Deep copy
   if (fields.contains(Field.EVENTS)) {
     entityToReturn.addEvents(entity.getEvents());
   } else if (fields.contains(Field.LAST_EVENT_ONLY)) {
     entityToReturn.addEvent(entity.getEvents().get(0));
   } else {
     entityToReturn.setEvents(null);
   }
   if (fields.contains(Field.RELATED_ENTITIES)) {
     entityToReturn.addRelatedEntities(entity.getRelatedEntities());
   } else {
     entityToReturn.setRelatedEntities(null);
   }
   if (fields.contains(Field.PRIMARY_FILTERS)) {
     entityToReturn.addPrimaryFilters(entity.getPrimaryFilters());
   } else {
     entityToReturn.setPrimaryFilters(null);
   }
   if (fields.contains(Field.OTHER_INFO)) {
     entityToReturn.addOtherInfo(entity.getOtherInfo());
   } else {
     entityToReturn.setOtherInfo(null);
   }
   return entityToReturn;
 }
 @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;
 }