diff --git a/dao/src/main/java/org/thingsboard/server/dao/event/CassandraBaseEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/event/CassandraBaseEventDao.java index 3598d2a176..5d4b91cb8a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/event/CassandraBaseEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/event/CassandraBaseEventDao.java @@ -142,7 +142,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao { @Transient @@ -63,7 +63,7 @@ public class EventEntity implements BaseEntity { @ClusteringColumn(value = 1) @Column(name = EVENT_UID_PROPERTY) - private String eventUId; + private String eventUid; @Column(name = EVENT_BODY_PROPERTY, codec = JsonCodec.class) private JsonNode body; @@ -80,7 +80,7 @@ public class EventEntity implements BaseEntity { this.entityId = event.getEntityId().getId(); } this.eventType = event.getType(); - this.eventUId = event.getUid(); + this.eventUid = event.getUid(); this.body = event.getBody(); } @@ -118,7 +118,7 @@ public class EventEntity implements BaseEntity { } event.setBody(body); event.setType(eventType); - event.setUid(eventUId); + event.setUid(eventUid); return event; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java index 92808ba2b5..9bfa663213 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java @@ -22,46 +22,51 @@ import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Transient; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.Event; import org.thingsboard.server.common.data.id.*; import org.thingsboard.server.dao.model.BaseEntity; -import org.thingsboard.server.dao.model.ModelConstants; +import static org.thingsboard.server.dao.model.ModelConstants.*; + +import java.io.IOException; import java.util.UUID; @Data +@Slf4j @NoArgsConstructor -//@Entity -@Table(name = ModelConstants.DEVICE_COLUMN_FAMILY_NAME) +@Entity +@Table(name = EVENT_COLUMN_FAMILY_NAME) public class EventEntity implements BaseEntity { @Transient private static final long serialVersionUID = -5717830061727466727L; - @Column(name = ModelConstants.ID_PROPERTY) + @Id + @Column(name = ID_PROPERTY, columnDefinition = "BINARY(16)") private UUID id; - @Id - @Column(name = ModelConstants.EVENT_TENANT_ID_PROPERTY) + @Column(name = EVENT_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)") private UUID tenantId; - @Column(name = ModelConstants.EVENT_ENTITY_TYPE_PROPERTY) + @Column(name = EVENT_ENTITY_TYPE_PROPERTY) private EntityType entityType; - @Column(name = ModelConstants.EVENT_ENTITY_ID_PROPERTY) + @Column(name = EVENT_ENTITY_ID_PROPERTY, columnDefinition = "BINARY(16)") private UUID entityId; - @Column(name = ModelConstants.EVENT_TYPE_PROPERTY) + @Column(name = EVENT_TYPE_PROPERTY) private String eventType; - @Column(name = ModelConstants.EVENT_UID_PROPERTY) - private String eventUId; + @Column(name = EVENT_UID_PROPERTY) + private String eventUid; - @Column(name = ModelConstants.EVENT_BODY_PROPERTY) - private JsonNode body; + @Column(name = EVENT_BODY_PROPERTY) + private String body; public EventEntity(Event event) { if (event.getId() != null) { @@ -75,8 +80,10 @@ public class EventEntity implements BaseEntity { this.entityId = event.getEntityId().getId(); } this.eventType = event.getType(); - this.eventUId = event.getUid(); - this.body = event.getBody(); + this.eventUid = event.getUid(); + if (event.getBody() != null) { + this.body = event.getBody().toString(); + } } @Override @@ -111,9 +118,17 @@ public class EventEntity implements BaseEntity { event.setEntityId(new PluginId(entityId)); break; } - event.setBody(body); + ObjectMapper mapper = new ObjectMapper(); + if (body != null) { + try { + JsonNode jsonNode = mapper.readTree(body); + event.setBody(jsonNode); + } catch (IOException e) { + log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", body, e.getMessage()), e); + } + } event.setType(eventType); - event.setUid(eventUId); + event.setUid(eventUid); return event; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTextDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTextDao.java new file mode 100644 index 0000000000..02d0e07871 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTextDao.java @@ -0,0 +1,14 @@ +package org.thingsboard.server.dao.sql; + +import org.thingsboard.server.dao.model.BaseEntity; + +/** + * Created by Valerii Sosliuk on 5/6/2017. + */ +public abstract class JpaAbstractSearchTextDao , D> extends JpaAbstractDao { + + @Override + protected boolean isSearchTextDao() { + return true; + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTimeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTimeDao.java new file mode 100644 index 0000000000..f0e5cb2e65 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTimeDao.java @@ -0,0 +1,62 @@ +package org.thingsboard.server.dao.sql; + +import com.datastax.driver.core.utils.UUIDs; +import org.springframework.data.jpa.domain.Specification; +import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.dao.model.BaseEntity; +import static org.thingsboard.server.dao.model.ModelConstants.*; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Created by Valerii Sosliuk on 5/4/2017. + */ +public abstract class JpaAbstractSearchTimeDao, D> extends JpaAbstractDao { + + protected Specification getTimeSearchPageSpec(TimePageLink pageLink) { + return new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + Predicate lowerBound = null; + Predicate upperBound = null; + List predicates = new ArrayList<>(); + if (pageLink.isAscOrder()) { + if (pageLink.getIdOffset() != null) { + lowerBound = criteriaBuilder.greaterThan(root.get(ID_PROPERTY), pageLink.getIdOffset()); + predicates.add(lowerBound); + } else if (pageLink.getStartTime() != null) { + UUID startOf = UUIDs.startOf(pageLink.getStartTime()); + lowerBound = criteriaBuilder.greaterThanOrEqualTo(root.get(ID_PROPERTY), startOf); + predicates.add(lowerBound); + } + if (pageLink.getEndTime() != null) { + UUID endOf = UUIDs.endOf(pageLink.getEndTime()); + upperBound = criteriaBuilder.lessThanOrEqualTo(root.get(ID_PROPERTY), endOf); + predicates.add(upperBound); + } + } else { + if (pageLink.getIdOffset() != null) { + lowerBound = criteriaBuilder.lessThan(root.get(ID_PROPERTY), pageLink.getIdOffset()); + predicates.add(lowerBound); + } else if (pageLink.getEndTime() != null) { + UUID endOf = UUIDs.endOf(pageLink.getEndTime()); + lowerBound = criteriaBuilder.lessThanOrEqualTo(root.get(ID_PROPERTY), endOf); + predicates.add(lowerBound); + } + if (pageLink.getStartTime() != null) { + UUID startOf = UUIDs.startOf(pageLink.getStartTime()); + upperBound = criteriaBuilder.greaterThanOrEqualTo(root.get(ID_PROPERTY), startOf); + predicates.add(upperBound); + } + } + return criteriaBuilder.and(predicates.toArray(new Predicate[0])); + } + }; + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventRepository.java new file mode 100644 index 0000000000..32a5b3bad5 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventRepository.java @@ -0,0 +1,24 @@ +package org.thingsboard.server.dao.sql.event; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.Event; +import org.thingsboard.server.dao.model.sql.EventEntity; + +import java.util.List; +import java.util.UUID; + +/** + * Created by Valerii Sosliuk on 5/3/2017. + */ +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) +public interface EventRepository extends CrudRepository, JpaSpecificationExecutor { + + EventEntity findByTenantIdAndEntityTypeAndEntityIdAndEventTypeAndEventUid( + UUID tenantId, EntityType entityType, UUID id, String eventType, String eventUid); + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java new file mode 100644 index 0000000000..3972c8e4d6 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java @@ -0,0 +1,137 @@ +package org.thingsboard.server.dao.sql.event; + +import com.datastax.driver.core.utils.UUIDs; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.Event; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.event.EventDao; +import org.thingsboard.server.dao.model.sql.EventEntity; +import org.thingsboard.server.dao.sql.JpaAbstractSearchTimeDao; + +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.springframework.data.jpa.domain.Specifications.where; +import static org.thingsboard.server.dao.model.ModelConstants.EVENT_COLUMN_FAMILY_NAME; +import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; + +/** + * Created by Valerii Sosliuk on 5/3/2017. + */ +@Slf4j +@Component +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) +public class JpaBaseEventDao extends JpaAbstractSearchTimeDao implements EventDao { + + private final UUID systemTenantId = NULL_UUID; + + @Autowired + private EventRepository eventRepository; + + @Override + protected Class getEntityClass() { + return EventEntity.class; + } + + @Override + protected String getColumnFamilyName() { + return EVENT_COLUMN_FAMILY_NAME; + } + + @Override + protected CrudRepository getCrudRepository() { + return eventRepository; + } + + @Override + public Event save(Event event) { + if (StringUtils.isEmpty(event.getUid())) { + event.setUid(event.getId().toString()); + } + return save(new EventEntity(event), false).orElse(null); + } + + @Override + public Optional saveIfNotExists(Event event) { + return save(new EventEntity(event), true); + } + + @Override + public Event findEvent(UUID tenantId, EntityId entityId, String eventType, String eventUid) { + return DaoUtil.getData(eventRepository.findByTenantIdAndEntityTypeAndEntityIdAndEventTypeAndEventUid( + tenantId, entityId.getEntityType(), entityId.getId(), eventType, eventUid)); + } + + @Override + public List findEvents(UUID tenantId, EntityId entityId, TimePageLink pageLink) { + return findEvents(tenantId, entityId, null, pageLink); + } + @Override + public List findEvents(UUID tenantId, EntityId entityId, String eventType, TimePageLink pageLink) { + Specification timeSearchSpec = getTimeSearchPageSpec(pageLink); + Specification fieldsSpec = getEntityFieldsSpec(tenantId, entityId, eventType); + Sort.Direction sortDirection = pageLink.isAscOrder() ? Sort.Direction.ASC : Sort.Direction.DESC; + Pageable pageable = new PageRequest(0, pageLink.getLimit(), sortDirection, ID_PROPERTY); + return DaoUtil.convertDataList(eventRepository.findAll(where(timeSearchSpec).and(fieldsSpec), pageable).getContent()); + } + + public Optional save(EventEntity entity, boolean ifNotExists) { + log.debug("Save event [{}] ", entity); + if (entity.getTenantId() == null) { + log.trace("Save system event with predefined id {}", systemTenantId); + entity.setTenantId(systemTenantId); + } + if (entity.getId() == null) { + entity.setId(UUIDs.timeBased()); + } + if (StringUtils.isEmpty(entity.getEventUid())) { + entity.setEventUid(entity.getId().toString()); + } + if (ifNotExists && findById(entity.getId()) != null) { + return Optional.empty(); + } + return Optional.of(DaoUtil.getData(eventRepository.save(entity))); + } + + private Specification getEntityFieldsSpec(UUID tenantId, EntityId entityId, String eventType) { + return new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + List predicates = new ArrayList(); + if (tenantId != null) { + Predicate tenantIdPredicate = criteriaBuilder.equal(root.get("tenantId"), tenantId); + predicates.add(tenantIdPredicate); + } + if (entityId != null) { + Predicate entityTypePredicate = criteriaBuilder.equal(root.get("entityType"), entityId.getEntityType()); + Predicate entityIdPredicate = criteriaBuilder.equal(root.get("entityId"), entityId.getId()); + predicates.add(entityTypePredicate); + predicates.add(entityIdPredicate); + } + if (eventType != null) { + Predicate eventTypePredicate = criteriaBuilder.equal(root.get("eventType"), eventType); + predicates.add(eventTypePredicate); + } + return criteriaBuilder.and(predicates.toArray(new Predicate[0])); + } + }; + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java index 5134ae6994..44e43d5e03 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java @@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.sql.PluginMetaDataEntity; import org.thingsboard.server.dao.plugin.PluginDao; import org.thingsboard.server.dao.sql.JpaAbstractDao; +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; import java.util.Arrays; import java.util.List; @@ -40,7 +41,7 @@ import java.util.UUID; @Slf4j @Component @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) -public class JpaBasePluginDao extends JpaAbstractDao implements PluginDao { +public class JpaBasePluginDao extends JpaAbstractSearchTextDao implements PluginDao { @Autowired private PluginMetaDataRepository pluginMetaDataRepository; @@ -60,11 +61,6 @@ public class JpaBasePluginDao extends JpaAbstractDao implements RuleDao { +public class JpaBaseRuleDao extends JpaAbstractSearchTextDao implements RuleDao { @Autowired private RuleMetaDataRepository ruleMetaDataRepository; @@ -59,11 +60,6 @@ public class JpaBaseRuleDao extends JpaAbstractDao implements TenantDao { +public class JpaTenantDao extends JpaAbstractSearchTextDao implements TenantDao { @Autowired private TenantRepository tenantRepository; @@ -56,11 +57,6 @@ public class JpaTenantDao extends JpaAbstractDao implement return tenantRepository; } - @Override - protected boolean isSearchTextDao() { - return true; - } - @Override public List findTenantsByRegion(String region, TextPageLink pageLink) { if (pageLink.getIdOffset() == null) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java index ff40dd29af..4288e5ab74 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity; import org.thingsboard.server.dao.sql.JpaAbstractDao; +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; import org.thingsboard.server.dao.widget.WidgetsBundleDao; import java.util.List; @@ -36,7 +37,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.WIDGETS_BUNDLE_COL */ @Component @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) -public class JpaWidgetsBundleDao extends JpaAbstractDao implements WidgetsBundleDao { +public class JpaWidgetsBundleDao extends JpaAbstractSearchTextDao implements WidgetsBundleDao { @Autowired private WidgetsBundleRepository widgetsBundleRepository; @@ -61,10 +62,6 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao findSystemWidgetsBundles(TextPageLink pageLink) { diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java new file mode 100644 index 0000000000..cdebaddb51 --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java @@ -0,0 +1,145 @@ +package org.thingsboard.server.dao.sql.event; + +import ch.qos.logback.core.net.SyslogOutputStream; +import com.datastax.driver.core.utils.UUIDs; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.springtestdbunit.annotation.DatabaseSetup; +import lombok.extern.slf4j.Slf4j; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.thingsboard.server.common.data.Event; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EventId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.dao.AbstractJpaDaoTest; +import org.thingsboard.server.dao.event.EventDao; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.junit.Assert.*; +import static org.thingsboard.server.common.data.DataConstants.STATS; + +/** + * Created by Valerii Sosliuk on 5/5/2017. + */ +@Slf4j +public class JpaBaseEventDaoTest extends AbstractJpaDaoTest { + + public static final long HOUR_MILLISECONDS = (long) 3.6e+6; + @Autowired + private EventDao eventDao; + + @Test + @DatabaseSetup("classpath:dbunit/empty_dataset.xml") + public void testSaveIfNotExists() { + UUID eventId = UUIDs.timeBased(); + UUID tenantId = UUIDs.timeBased(); + UUID entityId = UUIDs.timeBased(); + Event event = getEvent(eventId, tenantId, entityId); + Optional optEvent1 = eventDao.saveIfNotExists(event); + assertTrue("Optional is expected to be non-empty", optEvent1.isPresent()); + assertEquals(optEvent1.get(), event); + Optional optEvent2 = eventDao.saveIfNotExists(event); + assertFalse("Optional is expected to be empty", optEvent2.isPresent()); + } + + @Test + @DatabaseSetup("classpath:dbunit/events.xml") + public void findEvent() { + UUID tenantId = UUID.fromString("be41c7a0-31f5-11e7-9cfd-2786e6aa2046"); + UUID entityId = UUID.fromString("be41c7a1-31f5-11e7-9cfd-2786e6aa2046"); + String eventType = STATS; + String eventUid = "be41c7a3-31f5-11e7-9cfd-2786e6aa2046"; + Event event = eventDao.findEvent(tenantId, new DeviceId(entityId), eventType, eventUid); + assertNotNull("Event expected to be not null", event); + assertEquals("be41c7a2-31f5-11e7-9cfd-2786e6aa2046", event.getId().getId().toString()); + } + + @Test + @DatabaseSetup("classpath:dbunit/empty_dataset.xml") + public void findEventsByEntityIdAndPageLink() { + UUID tenantId = UUIDs.timeBased(); + UUID entityId1 = UUIDs.timeBased(); + UUID entityId2 = UUIDs.timeBased(); + long startTime = System.currentTimeMillis(); + long endTime = createEventsTwoEntities(tenantId, entityId1, entityId2, startTime, 20); + List allEvents = eventDao.find(); + + assertEquals(20, allEvents.size()); + + TimePageLink pageLink1 = new TimePageLink(30, null, null, true); + List events1 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink1); + assertEquals(10, events1.size()); + + TimePageLink pageLink2 = new TimePageLink(30, startTime, null, true); + List events2 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink2); + assertEquals(10, events2.size()); + + TimePageLink pageLink3 = new TimePageLink(30, startTime, endTime, true); + List events3 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink3); + assertEquals(10, events3.size()); + + TimePageLink pageLink4 = new TimePageLink(5, startTime, endTime, true); + List events4 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink4); + assertEquals(5, events4.size()); + + UUID idOffset = events4.get(4).getId().getId(); + TimePageLink pageLink5 = new TimePageLink(10, startTime, endTime, true, idOffset); + List events5 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink5); + assertEquals(5, events5.size()); + + } + + private long createEventsTwoEntities(UUID tenantId, UUID entityId1, UUID entityId2, long startTime, int count) { + // Generate #count events for two entities with timestamps from an hour ago till now + + // Distribute events uniformly + long step = HOUR_MILLISECONDS / count; + long timestamp = startTime; + for (int i = 0; i < count / 2; i++) { + //UUID eventId1 = UUIDs.startOf(timestamp); + UUID eventId1 = UUIDs.timeBased(); + Event event1 = getEvent(eventId1, tenantId, entityId1); + eventDao.save(event1); + timestamp += step; + //UUID eventId2 = UUIDs.startOf(timestamp); + UUID eventId2 = UUIDs.timeBased(); + Event event2 = getEvent(eventId2, tenantId, entityId2); + eventDao.save(event2); + timestamp += step; + } + return System.currentTimeMillis(); + } + + @Test + @DatabaseSetup("classpath:dbunit/empty_dataset.xml") + public void findEventsByEntityIdAndEventTypeAndPageLink() { + + } + + private Event getEvent(UUID eventId, UUID tenantId, UUID entityId) { + Event event = new Event(); + event.setId(new EventId(eventId)); + event.setTenantId(new TenantId(tenantId)); + EntityId deviceId = new DeviceId(entityId); + event.setEntityId(deviceId); + event.setUid(entityId.toString()); + event.setType(STATS); + ObjectMapper mapper = new ObjectMapper(); + try { + JsonNode jsonNode = mapper.readTree("{\"key\":\"value\"}"); + event.setBody(jsonNode); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + return event; + } +} diff --git a/dao/src/test/resources/dbunit/events.xml b/dao/src/test/resources/dbunit/events.xml new file mode 100644 index 0000000000..8f8875882b --- /dev/null +++ b/dao/src/test/resources/dbunit/events.xml @@ -0,0 +1,18 @@ + + + + \ No newline at end of file