diff --git a/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryAuditQuery.java b/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryAuditQuery.java index 366564ac0..74f7a67d1 100644 --- a/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryAuditQuery.java +++ b/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryAuditQuery.java @@ -32,17 +32,15 @@ public class InMemoryAuditQuery { private AuditTypeNavigator navigator; private List selectors; private AuditVisitor auditVisitor; + private long limit; - /** - * @param navigator - * @param selectors - * @param auditVisitor - */ - public InMemoryAuditQuery(AuditTypeNavigator navigator, List selectors, AuditVisitor auditVisitor) { + public InMemoryAuditQuery(AuditTypeNavigator navigator, long limit, List selectors, + AuditVisitor auditVisitor) { DBC.PRE.assertNotNull("Navigator must be set!", navigator); //$NON-NLS-1$ DBC.PRE.assertNotNull("selectors must be set!", selectors); //$NON-NLS-1$ DBC.PRE.assertNotNull("auditVisitor must be set!", auditVisitor); //$NON-NLS-1$ this.navigator = navigator; + this.limit = limit; this.selectors = selectors; this.auditVisitor = auditVisitor; } @@ -51,6 +49,9 @@ public class InMemoryAuditQuery { List result = new ArrayList<>(); List elements = this.navigator.navigate(dao); + + elements.sort((a1, a2) -> a2.getDate().compareTo(a1.getDate())); + for (Audit audit : elements) { if (!this.selectors.isEmpty()) { @@ -69,6 +70,9 @@ public class InMemoryAuditQuery { U returnValue = this.auditVisitor.visitAudit(audit); DBC.INTERIM.assertNotNull("Visitor may not return null in query!", returnValue); //$NON-NLS-1$ result.add(returnValue); + + if (this.limit > 0 && result.size() >= this.limit) + break; } return result; diff --git a/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryAuditQueryVisitor.java b/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryAuditQueryVisitor.java index 5484aa068..a5e5876a0 100644 --- a/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryAuditQueryVisitor.java +++ b/li.strolch.agent/src/main/java/li/strolch/runtime/query/inmemory/InMemoryAuditQueryVisitor.java @@ -44,8 +44,10 @@ public class InMemoryAuditQueryVisitor implements AuditQueryVisitor { String msg = "Query is missing a navigation!"; //$NON-NLS-1$ throw new QueryException(msg); } + + long limit = auditQuery.getLimit(); - return new InMemoryAuditQuery(this.navigator, this.selectors, auditVisitor); + return new InMemoryAuditQuery(this.navigator, limit, this.selectors, auditVisitor); } @Override diff --git a/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/AuditQueryTest.java b/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/AuditQueryTest.java index 3990aa583..c267051bc 100644 --- a/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/AuditQueryTest.java +++ b/li.strolch.agent/src/test/java/li/strolch/runtime/query/inmemory/AuditQueryTest.java @@ -143,6 +143,18 @@ public class AuditQueryTest { query.identity().firstnames(StringMatchMode.CONTAINS_CASE_INSENSITIVE, "enn") .lastnames(StringMatchMode.CONTAINS_CASE_INSENSITIVE, "kennedy"); performQuery(query, Arrays.asList(0L, 1L, 2L, 3L, 4L)); + + query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true)); + query.element().elementSubTypes(StringMatchMode.EQUALS_CASE_SENSITIVE, "Foo"); + performQuery(query, Arrays.asList(0L, 1L, 2L, 3L, 4L)); + + query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true)); + query.element().elementSubTypes(StringMatchMode.EQUALS_CASE_SENSITIVE, "Bar"); + performQuery(query, Arrays.asList()); + + query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true)); + query.limit(1).element().elementSubTypes(StringMatchMode.EQUALS_CASE_SENSITIVE, "Foo"); + performQuery(query, Arrays.asList(2L)); } private void performQuery(AuditQuery query, List expected) throws SQLException { diff --git a/li.strolch.model/src/main/java/li/strolch/model/audit/AuditQuery.java b/li.strolch.model/src/main/java/li/strolch/model/audit/AuditQuery.java index 19c37d52e..9970c2039 100644 --- a/li.strolch.model/src/main/java/li/strolch/model/audit/AuditQuery.java +++ b/li.strolch.model/src/main/java/li/strolch/model/audit/AuditQuery.java @@ -30,6 +30,7 @@ public class AuditQuery implements StrolchQuery { private String elementTypeSelection; private List selections; private DateRange dateRange; + private long limit; public AuditQuery(String elementTypeSelection, DateRange dateRange) { DBC.PRE.assertNotEmpty("No elementTypeSelection (navigation) set!", elementTypeSelection); //$NON-NLS-1$ @@ -47,6 +48,15 @@ public class AuditQuery implements StrolchQuery { return this.dateRange; } + public long getLimit() { + return limit; + } + + public AuditQuery limit(long limit) { + this.limit = limit; + return this; + } + public ActionSelection action() { ActionSelection selection = new ActionSelection(this); this.selections.add(selection); diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlAuditQueryVisitor.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlAuditQueryVisitor.java index e3e90f071..56c1d31dc 100644 --- a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlAuditQueryVisitor.java +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlAuditQueryVisitor.java @@ -37,6 +37,9 @@ public class PostgreSqlAuditQueryVisitor implements AuditQueryVisitor { protected StringBuilder sql; protected StringBuilder sb; protected List values; + + protected long limit; + protected String indent; private String sqlAsString; @@ -63,6 +66,12 @@ public class PostgreSqlAuditQueryVisitor implements AuditQueryVisitor { this.sql.append("\nwhere\n"); this.sql.append(this.sb.toString()); + + this.sql.append("ORDER BY date DESC\n"); + + if (limit != 0) + this.sql.append("LIMIT " + limit + "\n"); + this.sqlAsString = this.sql.toString(); return this.sqlAsString; } @@ -73,6 +82,7 @@ public class PostgreSqlAuditQueryVisitor implements AuditQueryVisitor { this.sb.append(this.indent); this.sb.append(PostgreSqlAuditDao.ELEMENT_TYPE); this.sb.append(" = ?\n"); + this.limit = auditQuery.getLimit(); ensureAnd(); this.values.add(auditQuery.getElementTypeSelection()); PostgreSqlHelper.toSql(this.indent, this.sb, this.values, PostgreSqlAuditDao.DATE, auditQuery.getDateRange()); diff --git a/li.strolch.persistence.postgresql/src/test/java/li/strolch/persistence/postgresql/dao/test/AuditQueryTest.java b/li.strolch.persistence.postgresql/src/test/java/li/strolch/persistence/postgresql/dao/test/AuditQueryTest.java index bfb72cc82..d5fdfb1fd 100644 --- a/li.strolch.persistence.postgresql/src/test/java/li/strolch/persistence/postgresql/dao/test/AuditQueryTest.java +++ b/li.strolch.persistence.postgresql/src/test/java/li/strolch/persistence/postgresql/dao/test/AuditQueryTest.java @@ -251,6 +251,10 @@ public class AuditQueryTest { query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true)); query.element().elementSubTypes(StringMatchMode.EQUALS_CASE_SENSITIVE, "Bar"); performQuery(query, Arrays.asList()); + + query = new AuditQuery(Tags.AUDIT, new DateRange().from(past, true).to(future, true)); + query.limit(1).element().elementSubTypes(StringMatchMode.EQUALS_CASE_SENSITIVE, "Foo"); + performQuery(query, Arrays.asList("2")); } private void performQuery(AuditQuery query, List expected) throws SQLException { diff --git a/li.strolch.rest/src/main/java/li/strolch/rest/model/AuditQuery.java b/li.strolch.rest/src/main/java/li/strolch/rest/model/AuditQuery.java index 8b9be3b52..1f3a38f3b 100644 --- a/li.strolch.rest/src/main/java/li/strolch/rest/model/AuditQuery.java +++ b/li.strolch.rest/src/main/java/li/strolch/rest/model/AuditQuery.java @@ -46,6 +46,9 @@ public class AuditQuery { @XmlElement(name = "dateRange") private DateRange dateRange; + @XmlElement(name = "limit") + private long limit; + public String getElementType() { return elementType; } @@ -93,4 +96,12 @@ public class AuditQuery { public void setDateRange(DateRange dateRange) { this.dateRange = dateRange; } + + public long getLimit() { + return limit; + } + + public void setLimit(long limit) { + this.limit = limit; + } } diff --git a/li.strolch.rest/src/main/java/li/strolch/rest/model/visitor/ToAuditQueryVisitor.java b/li.strolch.rest/src/main/java/li/strolch/rest/model/visitor/ToAuditQueryVisitor.java index ac16979c2..eebe3920e 100644 --- a/li.strolch.rest/src/main/java/li/strolch/rest/model/visitor/ToAuditQueryVisitor.java +++ b/li.strolch.rest/src/main/java/li/strolch/rest/model/visitor/ToAuditQueryVisitor.java @@ -32,6 +32,9 @@ public class ToAuditQueryVisitor { // create query li.strolch.model.audit.AuditQuery auditQuery = new li.strolch.model.audit.AuditQuery(elementType, dr); + // limit + auditQuery.limit(query.getLimit()); + // element String elementSubType = query.getElementSubType(); if (StringHelper.isNotEmpty(elementSubType)) {