From 8f181a0d88951ce976d1798bc4aaf8d6d3f467d7 Mon Sep 17 00:00:00 2001 From: Robert von Burg Date: Thu, 26 Mar 2020 14:37:37 +0100 Subject: [PATCH] [New] Extended OrderDao to allow a DateRange on queries --- .../li/strolch/persistence/api/OrderDao.java | 94 ++++++++- .../postgresql/PostgreSqlOrderDao.java | 191 ++++++++++++++++++ .../strolch/persistence/xml/AbstractDao.java | 18 +- .../strolch/persistence/xml/XmlAuditDao.java | 67 ++---- .../persistence/xml/XmlLogMessageDao.java | 2 +- .../strolch/persistence/xml/XmlOrderDao.java | 98 +++++++++ .../runtime/OrderModelTestRunner.java | 69 +++++++ 7 files changed, 473 insertions(+), 66 deletions(-) diff --git a/li.strolch.agent/src/main/java/li/strolch/persistence/api/OrderDao.java b/li.strolch.agent/src/main/java/li/strolch/persistence/api/OrderDao.java index c33938fd7..5c57f8972 100644 --- a/li.strolch.agent/src/main/java/li/strolch/persistence/api/OrderDao.java +++ b/li.strolch.agent/src/main/java/li/strolch/persistence/api/OrderDao.java @@ -1,12 +1,12 @@ /* * Copyright 2013 Robert von Burg - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,12 +15,98 @@ */ package li.strolch.persistence.api; +import java.util.List; + import li.strolch.model.Order; +import li.strolch.utils.collections.DateRange; /** * @author Robert von Burg */ public interface OrderDao extends StrolchDao { - // marker interface + /** + * Returns the number of elements in the underlying persistence layer, regardless of type + * + * @return the number of elements in the underlying persistence layer + */ + long querySize(DateRange dateRange); + + /** + * Returns the number of elements in the underlying persistence layer for the given type(s) + * + * @param dateRange + * the date range filter + * @param types + * the type(s) to query the size for + * + * @return the number of elements in the underlying persistence layer for the given type(s) + */ + long querySize(DateRange dateRange, String... types); + + /** + * Queries and returns all elements regardless of type + * + * @param dateRange + * the date range filter + * + * @return all elements regardless of type + * + * @throws StrolchPersistenceException + * if something goes wrong + */ + List queryAll(DateRange dateRange) throws StrolchPersistenceException; + + /** + * Queries and returns all elements regardless of type + * + * @param dateRange + * the date range filter + * @param limit + * the max amount, or @{@link Integer#MAX_VALUE} for all + * @param offset + * if max amount defined, then the offset to start from + * + * @return all elements regardless of type + * + * @throws StrolchPersistenceException + * if something goes wrong + */ + List queryAll(DateRange dateRange, long limit, long offset) throws StrolchPersistenceException; + + /** + * Queries and returns all elements of the given type + * + * @param dateRange + * the date range filter + * @param types + * the type(s) of element(s) to return + * + * @return all elements of the given type + * + * @throws StrolchPersistenceException + * if something goes wrong + */ + List queryAll(DateRange dateRange, String... types) throws StrolchPersistenceException; + + /** + * Queries and returns all elements of the given type + * + * @param dateRange + * the date range filter + * @param limit + * the max amount, or @{@link Integer#MAX_VALUE} for all + * @param offset + * if max amount defined, then the offset to start from + * @param types + * the type(s) of element(s) to return + * + * @return all elements of the given type + * + * @throws StrolchPersistenceException + * if something goes wrong + */ + List queryAll(DateRange dateRange, long limit, long offset, String... types) + throws StrolchPersistenceException; + } diff --git a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlOrderDao.java b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlOrderDao.java index fbc8a8212..33b1ef21e 100644 --- a/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlOrderDao.java +++ b/li.strolch.persistence.postgresql/src/main/java/li/strolch/persistence/postgresql/PostgreSqlOrderDao.java @@ -22,7 +22,9 @@ import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.text.MessageFormat; +import java.util.ArrayList; import java.util.Calendar; +import java.util.List; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -34,6 +36,8 @@ import li.strolch.model.xml.XmlModelSaxReader; import li.strolch.persistence.api.OrderDao; import li.strolch.persistence.api.StrolchPersistenceException; import li.strolch.persistence.api.TransactionResult; +import li.strolch.utils.collections.DateRange; +import li.strolch.utils.iso8601.ISO8601; import org.xml.sax.SAXException; @SuppressWarnings("nls") @@ -41,6 +45,19 @@ public class PostgreSqlOrderDao extends PostgresqlDao implements OrderDao public static final String ORDERS = "orders"; + private static final String querySizeDrSqlS = "select count(*) from {0} where latest = true {1}"; + private static final String querySizeOfTypeDrSqlS = "select count(*) from {0} where type = ANY(?) and latest = true {1}"; + + private static final String queryAllDrAsXmlSqlS = "select id, type, asxml from {0} where latest = true {1}"; + private static final String queryAllDrAsXmlLimitSqlS = "select id, type, asxml from {0} where latest = true {1} order by id limit {2} offset {3}"; + private static final String queryAllDrAsJsonSqlS = "select id, type, asjson from {0} where latest = true {1}"; + private static final String queryAllDrAsJsonLimitSqlS = "select id, type, asjson from {0} where latest = true {1} order by id limit {2} offset {3}"; + + private static final String queryAllByTypeDrAsXmlSqlS = "select id, type, asxml from {0} where type = ANY(?) and latest = true {1}"; + private static final String queryAllByTypeDrAsXmlLimitSqlS = "select id, type, asxml from {0} where type = ANY(?) and latest = true {1} order by id limit {2,number,#} offset {3,number,#}"; + private static final String queryAllByTypeDrAsJsonSqlS = "select id, type, asjson from {0} where type = ANY(?) and latest = true {1}"; + private static final String queryAllByTypeDrAsJsonLimitSqlS = "select id, type, asjson from {0} where type = ANY(?) and latest = true {1} order by id limit {2,number,#} offset {3,number,#}"; + private static final String insertAsXmlSqlS = "insert into {0} (id, version, created_by, created_at, updated_at, deleted, latest, name, type, state, date, asxml) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::order_state, ?, ?)"; private static final String insertAsJsonSqlS = "insert into {0} (id, version, created_by, created_at, updated_at, deleted, latest, name, type, state, date, asjson) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?::order_state, ?, ?)"; @@ -230,4 +247,178 @@ public class PostgreSqlOrderDao extends PostgresqlDao implements OrderDao .format("Failed to update Order {0} due to {1}", order.getLocator(), e.getLocalizedMessage()), e); } } + + @Override + public long querySize(DateRange dateRange) { + String sql = MessageFormat.format(querySizeDrSqlS, getTableName(), buildDateRangeClaus(dateRange)); + try (PreparedStatement statement = this.connection.prepareStatement(sql)) { + + try (ResultSet result = statement.executeQuery()) { + result.next(); + return result.getLong(1); + } + + } catch (SQLException e) { + throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e); + } + } + + @Override + public long querySize(DateRange dateRange, String... types) { + if (types.length == 0) + return querySize(); + + String sql = MessageFormat.format(querySizeOfTypeDrSqlS, getTableName(), buildDateRangeClaus(dateRange)); + + try (PreparedStatement statement = this.connection.prepareStatement(sql)) { + + Array typesArray = statement.getConnection().createArrayOf("varchar", types); + statement.setArray(1, typesArray); + + try (ResultSet result = statement.executeQuery()) { + result.next(); + return result.getLong(1); + } + + } catch (SQLException e) { + throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e); + } + } + + @Override + public List queryAll(DateRange dateRange) throws StrolchPersistenceException { + return queryAll(dateRange, Integer.MAX_VALUE, 0); + } + + @Override + public List queryAll(DateRange dateRange, long limit, long offset) throws StrolchPersistenceException { + + List list = new ArrayList<>(); + + String sql = getLimitSql(dateRange, limit, offset, queryAllDrAsXmlSqlS, queryAllDrAsJsonSqlS, + queryAllDrAsXmlLimitSqlS, queryAllDrAsJsonLimitSqlS); + + try (PreparedStatement statement = this.connection.prepareStatement(sql)) { + + try (ResultSet result = statement.executeQuery()) { + while (result.next()) { + String id = result.getString("id"); + String type = result.getString("type"); + list.add(parseDbObject(result, id, type)); + } + + return list; + } + + } catch (SQLException e) { + throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e); + } + } + + @Override + public List queryAll(DateRange dateRange, String... types) throws StrolchPersistenceException { + return queryAll(dateRange, Integer.MAX_VALUE, 0, types); + } + + @Override + public List queryAll(DateRange dateRange, long limit, long offset, String... types) + throws StrolchPersistenceException { + if (types.length == 0) + return queryAll(limit, offset); + + List list = new ArrayList<>(); + + String sql = getLimitSql(dateRange, limit, offset, queryAllByTypeDrAsXmlSqlS, queryAllByTypeDrAsJsonSqlS, + queryAllByTypeDrAsXmlLimitSqlS, queryAllByTypeDrAsJsonLimitSqlS); + + try (PreparedStatement statement = this.connection.prepareStatement(sql)) { + + Array typesArray = statement.getConnection().createArrayOf("varchar", types); + statement.setArray(1, typesArray); + + try (ResultSet result = statement.executeQuery()) { + while (result.next()) { + String id = result.getString("id"); + String type = result.getString("type"); + list.add(parseDbObject(result, id, type)); + } + + return list; + } + + } catch (SQLException e) { + throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e); + } + } + + protected String getLimitSql(DateRange dateRange, long limit, long offset, String xmlSql, String jsonSql, + String xmlLimitSql, String jsonLimitSql) { + + String sql; + if (limit == Integer.MAX_VALUE) { + return getSql(dateRange, xmlSql, jsonSql); + } + + if (this.dataType == DataType.xml) + sql = xmlLimitSql; + else if (this.dataType == DataType.json) + sql = jsonLimitSql; + else + throw new IllegalStateException("Unhandled DataType " + this.dataType); + + String dateRangeClause = buildDateRangeClaus(dateRange); + return MessageFormat.format(sql, getTableName(), dateRangeClause, limit, offset); + } + + protected String getSql(DateRange dateRange, String xmlSql, String jsonSql) { + + String sql; + if (this.dataType == DataType.xml) + sql = xmlSql; + else if (this.dataType == DataType.json) + sql = jsonSql; + else + throw new IllegalStateException("Unhandled DataType " + this.dataType); + + String dateRangeClause = buildDateRangeClaus(dateRange); + return MessageFormat.format(sql, getTableName(), dateRangeClause); + } + + private String buildDateRangeClaus(DateRange dateRange) { + + if (dateRange.isFromBounded() && dateRange.isToBounded()) { + + String from = ISO8601.toString(dateRange.getFromDate()); + String to = ISO8601.toString(dateRange.getToDate()); + + if (dateRange.isFromInclusive() && dateRange.isToInclusive()) + return "and date >= '" + from + "' and date <= '" + to + "'"; + + if (dateRange.isFromInclusive()) + return "and date >= '" + from + "' and date < '" + to + "'"; + + if (dateRange.isToInclusive()) + return "and date > '" + from + "' and date <= '" + to + "'"; + + return "and date > '" + from + "' and date < '" + to + "'"; + + } else if (dateRange.isFromBounded()) { + + String from = ISO8601.toString(dateRange.getFromDate()); + + if (dateRange.isFromInclusive()) + return "and date >= '" + from + "'"; + + return "and date > '" + from + "'"; + + } else { + + String to = ISO8601.toString(dateRange.getToDate()); + + if (dateRange.isToInclusive()) + return "and date <= '" + to + "'"; + + return "and date < '" + to + "'"; + } + } } diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/AbstractDao.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/AbstractDao.java index 47fab3290..b8ea4e11d 100644 --- a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/AbstractDao.java +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/AbstractDao.java @@ -48,7 +48,7 @@ public abstract class AbstractDao implements Strol return this.tx.getManager().getObjectRefCache().getIdOfSubTypeRef(getClassType(), type, id); } - private SubTypeRef getTypeRef(String type) { + protected SubTypeRef getTypeRef(String type) { return this.tx.getManager().getObjectRefCache().getSubTypeRef(getClassType(), type); } @@ -58,7 +58,7 @@ public abstract class AbstractDao implements Strol Set types = queryTypes(); for (String type : types) { SubTypeRef subTypeRef = getTypeRef(type); - size += this.tx.getMetadataDao().querySize(subTypeRef); + size += this.tx.getMetadataDao().querySize(subTypeRef, file -> true); } return size; } @@ -71,13 +71,13 @@ public abstract class AbstractDao implements Strol if (types.length == 1) { SubTypeRef subTypeRef = getTypeRef(types[0]); - return this.tx.getMetadataDao().querySize(subTypeRef); + return this.tx.getMetadataDao().querySize(subTypeRef, file -> true); } int size = 0; for (String type : types) { SubTypeRef subTypeRef = getTypeRef(type); - size += this.tx.getMetadataDao().querySize(subTypeRef); + size += this.tx.getMetadataDao().querySize(subTypeRef, file -> true); } return size; @@ -94,7 +94,7 @@ public abstract class AbstractDao implements Strol List objects = new ArrayList<>(); Set types = queryTypes(); for (String type : types) { - List objectsByType = this.tx.getObjectDao().queryAll(getTypeRef(type)); + List objectsByType = this.tx.getObjectDao().queryAll(getTypeRef(type), file -> true); objects.addAll(objectsByType); } @@ -107,12 +107,12 @@ public abstract class AbstractDao implements Strol return queryAll(); if (types.length == 1) { - return this.tx.getObjectDao().queryAll(getTypeRef(types[0])); + return this.tx.getObjectDao().queryAll(getTypeRef(types[0]), file -> true); } List objects = new ArrayList<>(); for (String type : types) { - objects.addAll(this.tx.getObjectDao().queryAll(getTypeRef(type))); + objects.addAll(this.tx.getObjectDao().queryAll(getTypeRef(type), file -> true)); } return objects; @@ -151,13 +151,13 @@ public abstract class AbstractDao implements Strol @Override public long removeAll() { TypeRef typeRef = this.tx.getManager().getObjectRefCache().getTypeRef(getClassType()); - return this.tx.getObjectDao().removeAllBy(typeRef); + return this.tx.getObjectDao().removeAllBy(typeRef, file -> true); } @Override public long removeAllBy(String type) { SubTypeRef typeRef = getTypeRef(type); - return this.tx.getObjectDao().removeAllBy(typeRef); + return this.tx.getObjectDao().removeAllBy(typeRef, file -> true); } @Override diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlAuditDao.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlAuditDao.java index 4455076b0..6a72b6e53 100644 --- a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlAuditDao.java +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlAuditDao.java @@ -15,9 +15,11 @@ */ package li.strolch.persistence.xml; -import java.util.ArrayList; +import java.io.File; +import java.util.Date; import java.util.List; import java.util.Set; +import java.util.function.Predicate; import li.strolch.model.Tags; import li.strolch.model.audit.Audit; @@ -28,7 +30,6 @@ import li.strolch.utils.collections.DateRange; import li.strolch.xmlpers.api.PersistenceContext; import li.strolch.xmlpers.api.PersistenceTransaction; import li.strolch.xmlpers.objref.IdOfSubTypeRef; -import li.strolch.xmlpers.objref.ObjectRef; import li.strolch.xmlpers.objref.SubTypeRef; import li.strolch.xmlpers.objref.TypeRef; @@ -77,20 +78,8 @@ public class XmlAuditDao implements AuditDao { @Override public long querySize(String type, DateRange dateRange) { - long size = 0; - - // TODO re-think this nonsense... this might have a huge performance penalty - SubTypeRef subTypeRef = getTypeRef(type); - Set keySet = this.tx.getMetadataDao().queryKeySet(subTypeRef); - for (String key : keySet) { - ObjectRef objectRef = subTypeRef.getChildIdRef(this.tx, key); - Audit audit = this.tx.getObjectDao().queryById(objectRef); - if (dateRange.contains(audit.getDate())) - size++; - } - - // return this.tx.getMetadataDao().querySize(subTypeRef); - return size; + Predicate predicate = file -> dateRange.contains(new Date(file.lastModified())); + return this.tx.getMetadataDao().querySize(getTypeRef(type), predicate); } @Override @@ -106,82 +95,56 @@ public class XmlAuditDao implements AuditDao { @Override public List queryAll(String type, DateRange dateRange) { - - List audits = new ArrayList<>(); - - SubTypeRef subTypeRef = getTypeRef(type); - Set keySet = this.tx.getMetadataDao().queryKeySet(subTypeRef); - for (String key : keySet) { - ObjectRef objectRef = subTypeRef.getChildIdRef(this.tx, key); - Audit audit = this.tx.getObjectDao().queryById(objectRef); - if (dateRange.contains(audit.getDate())) - audits.add(audit); - } - - // this.tx.getObjectDao().queryAll(getTypeRef(type)); - return audits; + Predicate predicate = file -> dateRange.contains(new Date(file.lastModified())); + return this.tx.getObjectDao().queryAll(getTypeRef(type), predicate); } @Override public void save(Audit audit) { - PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit); + PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit, -1L); this.tx.getFileDao().performCreate(ctx); } @Override public void saveAll(List audits) { for (Audit audit : audits) { - PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit); + PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit, -1L); this.tx.getFileDao().performCreate(ctx); } } @Override public void update(Audit audit) { - PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit); + PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit, -1L); this.tx.getFileDao().performUpdate(ctx); } @Override public void updateAll(List audits) { for (Audit audit : audits) { - PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit); + PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit, -1L); this.tx.getFileDao().performUpdate(ctx); } } @Override public void remove(Audit audit) { - PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit); + PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit, -1L); this.tx.getFileDao().performDelete(ctx); } @Override public void removeAll(List audits) { for (Audit audit : audits) { - PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit); + PersistenceContext ctx = this.tx.getObjectDao().createCtx(audit, -1L); this.tx.getFileDao().performDelete(ctx); } } @Override public long removeAll(String type, DateRange dateRange) { - - long removed = 0L; - - SubTypeRef subTypeRef = getTypeRef(type); - Set keySet = this.tx.getMetadataDao().queryKeySet(subTypeRef); - for (String key : keySet) { - ObjectRef objectRef = subTypeRef.getChildIdRef(this.tx, key); - Audit audit = this.tx.getObjectDao().queryById(objectRef); - if (dateRange.contains(audit.getDate())) { - PersistenceContext ctx = this.tx.getObjectDao().createCtx(objectRef); - this.tx.getFileDao().performDelete(ctx); - removed++; - } - } - - return removed; + Predicate predicate = file -> dateRange.contains(new Date(file.lastModified())); + return this.tx.getObjectDao().removeAllBy(getTypeRef(type), predicate); } @Override diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlLogMessageDao.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlLogMessageDao.java index 3378de6a6..2c068c725 100644 --- a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlLogMessageDao.java +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlLogMessageDao.java @@ -25,7 +25,7 @@ public class XmlLogMessageDao implements LogMessageDao { @Override public List queryLatest(String realm, int maxNr) { SubTypeRef subTypeRef = this.tx.getManager().getObjectRefCache().getSubTypeRef(getClassType(), realm); - return this.tx.getObjectDao().queryAll(subTypeRef, maxNr, true); + return this.tx.getObjectDao().queryAll(subTypeRef, true, file -> true, maxNr); } @Override diff --git a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlOrderDao.java b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlOrderDao.java index 75735ff5a..dd0fb96d4 100644 --- a/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlOrderDao.java +++ b/li.strolch.persistence.xml/src/main/java/li/strolch/persistence/xml/XmlOrderDao.java @@ -15,10 +15,20 @@ */ package li.strolch.persistence.xml; +import java.io.File; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; + import li.strolch.model.Order; import li.strolch.model.Tags; import li.strolch.persistence.api.OrderDao; +import li.strolch.persistence.api.StrolchPersistenceException; import li.strolch.persistence.api.StrolchTransaction; +import li.strolch.utils.collections.DateRange; +import li.strolch.xmlpers.objref.SubTypeRef; public class XmlOrderDao extends AbstractDao implements OrderDao { @@ -30,4 +40,92 @@ public class XmlOrderDao extends AbstractDao implements OrderDao { protected String getClassType() { return Tags.ORDER; } + + @Override + public void save(Order object) { + this.tx.getObjectDao().add(object, object.getDate().getTime()); + } + + @Override + public void saveAll(List objects) { + for (Order object : objects) { + save(object); + } + } + + @Override + public void update(Order object) { + this.tx.getObjectDao().update(object, object.getDate().getTime()); + } + + @Override + public void updateAll(List objects) { + for (Order object : objects) { + update(object); + } + } + + private Predicate getDateRangePredicate(DateRange dateRange) { + return file -> dateRange.contains(new Date(file.lastModified())); + } + + @Override + public long querySize(DateRange dateRange) { + long size = 0; + Set types = queryTypes(); + for (String type : types) { + SubTypeRef subTypeRef = getTypeRef(type); + size += this.tx.getMetadataDao().querySize(subTypeRef, getDateRangePredicate(dateRange)); + } + return size; + } + + @Override + public long querySize(DateRange dateRange, String... types) { + + if (types.length == 0) + return querySize(); + + if (types.length == 1) { + SubTypeRef subTypeRef = getTypeRef(types[0]); + return this.tx.getMetadataDao().querySize(subTypeRef, getDateRangePredicate(dateRange)); + } + + int size = 0; + for (String type : types) { + SubTypeRef subTypeRef = getTypeRef(type); + size += this.tx.getMetadataDao().querySize(subTypeRef, getDateRangePredicate(dateRange)); + } + + return size; + } + + @Override + public List queryAll(DateRange dateRange) throws StrolchPersistenceException { + List objects = new ArrayList<>(); + Set types = queryTypes(); + for (String type : types) { + List objectsByType = this.tx.getObjectDao() + .queryAll(getTypeRef(type), getDateRangePredicate(dateRange)); + objects.addAll(objectsByType); + } + + return objects; + } + + @Override + public List queryAll(DateRange dateRange, long limit, long offset) throws StrolchPersistenceException { + throw new UnsupportedOperationException("Paging not supported! Check first with supportsPaging()"); + } + + @Override + public List queryAll(DateRange dateRange, String... types) throws StrolchPersistenceException { + throw new UnsupportedOperationException("Paging not supported! Check first with supportsPaging()"); + } + + @Override + public List queryAll(DateRange dateRange, long limit, long offset, String... types) + throws StrolchPersistenceException { + throw new UnsupportedOperationException("Paging not supported! Check first with supportsPaging()"); + } } diff --git a/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/OrderModelTestRunner.java b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/OrderModelTestRunner.java index dd13e968f..54f8b0f51 100644 --- a/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/OrderModelTestRunner.java +++ b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/OrderModelTestRunner.java @@ -18,6 +18,7 @@ package li.strolch.testbase.runtime; import static li.strolch.model.ModelGenerator.*; import static org.junit.Assert.*; +import java.time.LocalDate; import java.util.*; import li.strolch.agent.api.OrderMap; @@ -25,9 +26,12 @@ import li.strolch.agent.impl.DataStoreMode; import li.strolch.model.Order; import li.strolch.model.StrolchElement; import li.strolch.model.parameter.StringParameter; +import li.strolch.persistence.api.OrderDao; +import li.strolch.persistence.api.PersistenceHandler; import li.strolch.persistence.api.StrolchTransaction; import li.strolch.privilege.model.Certificate; import li.strolch.runtime.privilege.PrivilegeHandler; +import li.strolch.utils.collections.DateRange; @SuppressWarnings("nls") public class OrderModelTestRunner { @@ -76,6 +80,11 @@ public class OrderModelTestRunner { Order order1 = createOrder("myTestOrder1", "Test Name", "QTestType1"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ Order order2 = createOrder("myTestOrder2", "Test Name", "QTestType2"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ Order order3 = createOrder("myTestOrder3", "Test Name", "QTestType3"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + + order1.setDate(LocalDate.of(2018, 3, 1)); + order2.setDate(LocalDate.of(2019, 4, 1)); + order3.setDate(LocalDate.of(2019, 5, 1)); + try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName) .openTx(this.certificate, "test", false)) { tx.add(order1); @@ -101,6 +110,66 @@ public class OrderModelTestRunner { size = tx.getOrderMap().querySize(tx, "NonExistingType"); assertEquals("Should have zero objects of type 'NonExistingType'", 0, size); } + + try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test", true)) { + PersistenceHandler persistenceHandler = this.runtimeMock.getComponent(PersistenceHandler.class); + OrderDao dao = persistenceHandler.getOrderDao(tx); + + LocalDate _2017 = LocalDate.of(2017, 1, 1); + LocalDate _2018 = LocalDate.of(2018, 1, 1); + LocalDate _20180301 = LocalDate.of(2018, 3, 1); + LocalDate _20190401 = LocalDate.of(2019, 4, 1); + LocalDate _20190501 = LocalDate.of(2019, 5, 1); + LocalDate _2020 = LocalDate.of(2020, 1, 1); + + long size; + + size = dao.querySize(new DateRange().to(_2017, true)); + assertEquals("Expect 0 Orders before 2017 inc", 0, size); + + size = dao.querySize(new DateRange().from(_2017, true).to(_2018, true)); + assertEquals("Expect 0 Orders between _2017 inc and _2018 inc", 0, size); + + size = dao.querySize(new DateRange().from(_2018, true).to(_20180301, false)); + assertEquals("Expect 0 Orders between _2018 inc and _20180301 exc", 0, size); + + size = dao.querySize(new DateRange().from(_2018, true).to(_20180301, true)); + assertEquals("Expect 1 Orders between 2018 inc and _20180301 inc", 1, size); + + size = dao.querySize(new DateRange().from(_20180301, false).to(_20190401, false)); + assertEquals("Expect 0 Orders between _20180301 exc and _20190401 exc", 0, size); + + size = dao.querySize(new DateRange().from(_2017, true)); + assertEquals("Expect 3 Orders from _2017 inc", 3, size); + + size = dao.querySize(new DateRange().from(_2020, true)); + assertEquals("Expect 0 Orders from _2020 inc", 0, size); + + size = dao.querySize(new DateRange().from(_20190501, true).to(_2020, true)); + assertEquals("Expect 1 Orders from _20190501 inc to _2020 inc", 1, size); + + DateRange dateRange = new DateRange().from(_2017, true).to(_20190401, true); + String[] types = { "QTestType1", "QTestType2", "QTestType3" }; + + size = dao.querySize(dateRange, types); + assertEquals("Expect 2 Orders from _2017 inc to _20190401 inc by types", 2, size); + + List orders; + + orders = dao.queryAll(dateRange); + assertEquals("Expect 2 Orders from _2017 inc to _20190401 inc", 2, orders.size()); + + if (dao.supportsPaging()) { + orders = dao.queryAll(dateRange, 2, 1); + assertEquals("Expect 1 Orders from _2017 inc to _20190401 inc offset 1 limit 2", 1, orders.size()); + assertEquals("Expect order myTestOrder2", "myTestOrder2", orders.get(0).getId()); + + orders = dao.queryAll(new DateRange().from(_2017, true).to(_2020, true), 2, 1); + assertEquals("Expect 2 Orders from _2017 inc to _2020 inc offset 1 limit 2", 2, orders.size()); + assertEquals("Expect order myTestOrder2", "myTestOrder2", orders.get(0).getId()); + assertEquals("Expect order myTestOrder3", "myTestOrder3", orders.get(1).getId()); + } + } } public void runCrudTests() {