You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2024/06/19 08:27:30 UTC
(causeway) branch 3779-select.by.id created (now 41b21443cb)
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a change to branch 3779-select.by.id
in repository https://gitbox.apache.org/repos/asf/causeway.git
at 41b21443cb CAUSEWAY-3779: initial draft
This branch includes the following new commits:
new 41b21443cb CAUSEWAY-3779: initial draft
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(causeway) 01/01: CAUSEWAY-3779: initial draft
Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch 3779-select.by.id
in repository https://gitbox.apache.org/repos/asf/causeway.git
commit 41b21443cbd3e5ff3471ea4f94deeb13ff788841
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Jun 17 14:53:26 2024 +0200
CAUSEWAY-3779: initial draft
---
.../org/apache/causeway/applib/query/Query.java | 19 +++++++++--
...ancesQueryDefault.java => SelectByIdQuery.java} | 30 ++++-------------
.../applib/query/_AllInstancesQueryDefault.java | 9 +++--
...ryDefault.java => _SelectByIdQueryDefault.java} | 27 +++++++++------
.../causeway/commons/internal/base/_Timing.java | 18 ++++++++--
.../tabular/interactive/DataTableInteractive.java | 39 ++++++++++++++++++----
.../core/metamodel/tabular/simple/DataTable.java | 18 ++++++++--
.../metamodel/facets/entity/JdoEntityFacet.java | 19 +++++++++++
.../jpa/integration/entity/JpaEntityFacet.java | 8 ++++-
.../CollectionContentsSortableDataProvider.java | 9 +++++
10 files changed, 140 insertions(+), 56 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/causeway/applib/query/Query.java b/api/applib/src/main/java/org/apache/causeway/applib/query/Query.java
index 7838036267..68f470a799 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/query/Query.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/query/Query.java
@@ -22,6 +22,7 @@ import java.io.Serializable;
import java.util.function.Predicate;
import org.apache.causeway.applib.services.repository.RepositoryService;
+import org.apache.causeway.commons.collections.Can;
import lombok.NonNull;
@@ -69,15 +70,15 @@ public interface Query<T> extends Serializable {
Query<T> withRange(@NonNull QueryRange range);
- default Query<T> withRange(long ...range) {
+ default Query<T> withRange(final long ...range) {
return withRange(QueryRange.of(range));
}
- default Query<T> withStart(long start) {
+ default Query<T> withStart(final long start) {
return withRange(start);
}
- default Query<T> withLimit(long limit) {
+ default Query<T> withLimit(final long limit) {
return withRange(0L, limit);
}
@@ -94,4 +95,16 @@ public interface Query<T> extends Serializable {
return new _NamedQueryDefault<>(resultType, queryName, QueryRange.unconstrained(), null);
}
+ static <T> SelectByIdQuery<T> selectByIdQuery(
+ final @NonNull Class<T> resultType,
+ final @NonNull String ... idsStringified) {
+ return selectByIdQuery(resultType, Can.ofArray(idsStringified));
+ }
+
+ static <T> SelectByIdQuery<T> selectByIdQuery(
+ final @NonNull Class<T> resultType,
+ final @NonNull Can<String> idsStringified) {
+ return new _SelectByIdQueryDefault<>(resultType, idsStringified, QueryRange.unconstrained());
+ }
+
}
diff --git a/api/applib/src/main/java/org/apache/causeway/applib/query/_AllInstancesQueryDefault.java b/api/applib/src/main/java/org/apache/causeway/applib/query/SelectByIdQuery.java
similarity index 56%
copy from api/applib/src/main/java/org/apache/causeway/applib/query/_AllInstancesQueryDefault.java
copy to api/applib/src/main/java/org/apache/causeway/applib/query/SelectByIdQuery.java
index 9f81a79427..d53fc557f5 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/query/_AllInstancesQueryDefault.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/query/SelectByIdQuery.java
@@ -18,31 +18,13 @@
*/
package org.apache.causeway.applib.query;
-import lombok.NonNull;
+import org.apache.causeway.commons.collections.Can;
-final class _AllInstancesQueryDefault<T>
-extends _QueryAbstract<T>
-implements AllInstancesQuery<T> {
-
- private static final long serialVersionUID = 1L;
-
- protected _AllInstancesQueryDefault(
- final @NonNull Class<T> type,
- final @NonNull QueryRange range) {
- super(type, range);
- }
-
- @Override
- public String getDescription() {
- return getResultType().getName() + " (all instances)";
- }
-
- // -- WITHERS
-
- @Override
- public _AllInstancesQueryDefault<T> withRange(final @NonNull QueryRange range) {
- return new _AllInstancesQueryDefault<>(getResultType(), range);
- }
+/**
+ * @since 2.1, 3.1 {@index}
+ */
+public interface SelectByIdQuery<T> extends Query<T> {
+ Can<String> getIdsStringified();
}
diff --git a/api/applib/src/main/java/org/apache/causeway/applib/query/_AllInstancesQueryDefault.java b/api/applib/src/main/java/org/apache/causeway/applib/query/_AllInstancesQueryDefault.java
index 9f81a79427..ed3ceee382 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/query/_AllInstancesQueryDefault.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/query/_AllInstancesQueryDefault.java
@@ -20,14 +20,14 @@ package org.apache.causeway.applib.query;
import lombok.NonNull;
-final class _AllInstancesQueryDefault<T>
-extends _QueryAbstract<T>
+final class _AllInstancesQueryDefault<T>
+extends _QueryAbstract<T>
implements AllInstancesQuery<T> {
private static final long serialVersionUID = 1L;
protected _AllInstancesQueryDefault(
- final @NonNull Class<T> type,
+ final @NonNull Class<T> type,
final @NonNull QueryRange range) {
super(type, range);
}
@@ -38,11 +38,10 @@ implements AllInstancesQuery<T> {
}
// -- WITHERS
-
+
@Override
public _AllInstancesQueryDefault<T> withRange(final @NonNull QueryRange range) {
return new _AllInstancesQueryDefault<>(getResultType(), range);
}
-
}
diff --git a/api/applib/src/main/java/org/apache/causeway/applib/query/_AllInstancesQueryDefault.java b/api/applib/src/main/java/org/apache/causeway/applib/query/_SelectByIdQueryDefault.java
similarity index 63%
copy from api/applib/src/main/java/org/apache/causeway/applib/query/_AllInstancesQueryDefault.java
copy to api/applib/src/main/java/org/apache/causeway/applib/query/_SelectByIdQueryDefault.java
index 9f81a79427..27dea7eb21 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/query/_AllInstancesQueryDefault.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/query/_SelectByIdQueryDefault.java
@@ -18,31 +18,38 @@
*/
package org.apache.causeway.applib.query;
+import org.apache.causeway.commons.collections.Can;
+
+import lombok.Getter;
import lombok.NonNull;
-final class _AllInstancesQueryDefault<T>
-extends _QueryAbstract<T>
-implements AllInstancesQuery<T> {
+final class _SelectByIdQueryDefault<T>
+extends _QueryAbstract<T>
+implements SelectByIdQuery<T> {
private static final long serialVersionUID = 1L;
- protected _AllInstancesQueryDefault(
- final @NonNull Class<T> type,
+ @Getter
+ private final @NonNull Can<String> idsStringified;
+
+ _SelectByIdQueryDefault(
+ final @NonNull Class<T> type,
+ final @NonNull Can<String> idsStringified,
final @NonNull QueryRange range) {
super(type, range);
+ this.idsStringified = idsStringified;
}
@Override
public String getDescription() {
- return getResultType().getName() + " (all instances)";
+ return getResultType().getName() + " (select by id)";
}
// -- WITHERS
-
+
@Override
- public _AllInstancesQueryDefault<T> withRange(final @NonNull QueryRange range) {
- return new _AllInstancesQueryDefault<>(getResultType(), range);
+ public _SelectByIdQueryDefault<T> withRange(final @NonNull QueryRange range) {
+ return new _SelectByIdQueryDefault<>(getResultType(), idsStringified, range);
}
-
}
diff --git a/commons/src/main/java/org/apache/causeway/commons/internal/base/_Timing.java b/commons/src/main/java/org/apache/causeway/commons/internal/base/_Timing.java
index d40f6abafa..0a8bd7798a 100644
--- a/commons/src/main/java/org/apache/causeway/commons/internal/base/_Timing.java
+++ b/commons/src/main/java/org/apache/causeway/commons/internal/base/_Timing.java
@@ -134,6 +134,21 @@ public final class _Timing {
return watch.stop();
}
+ public static void runVerbose(final String label, final Runnable runnable) {
+ System.out.println(String.format(Locale.US, "Entering call '%s'", label));
+ final StopWatch watch = run(runnable);
+ System.out.println(String.format(Locale.US, "Running '%s' took %d ms", label, watch.getMillis()));
+ }
+
+ public static <T> T callVerbose(final String label, final Supplier<T> callable) {
+ System.out.println(String.format(Locale.US, "Entering call '%s'", label));
+ final StopWatch watch = now();
+ T result = callable.get();
+ watch.stop();
+ System.out.println(String.format(Locale.US, "Calling '%s' took %d ms", label, watch.getMillis()));
+ return result;
+ }
+
public static void runVerbose(final Logger log, final String label, final Runnable runnable) {
final StopWatch watch = run(runnable);
log.info(String.format(Locale.US, "Running '%s' took %d ms", label, watch.getMillis()));
@@ -147,7 +162,4 @@ public final class _Timing {
return result;
}
-
-
-
}
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/interactive/DataTableInteractive.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/interactive/DataTableInteractive.java
index 5404162ed1..0b5c7fc1cf 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/interactive/DataTableInteractive.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/interactive/DataTableInteractive.java
@@ -20,6 +20,7 @@ package org.apache.causeway.core.metamodel.tabular.interactive;
import java.io.Serializable;
import java.util.Comparator;
+import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -35,6 +36,7 @@ import org.apache.causeway.applib.services.filter.CollectionFilterService;
import org.apache.causeway.commons.binding.Bindable;
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.functional.IndexedFunction;
+import org.apache.causeway.commons.internal.base._Timing;
import org.apache.causeway.commons.internal.binding._BindableAbstract;
import org.apache.causeway.commons.internal.binding._Bindables;
import org.apache.causeway.commons.internal.binding._Observables;
@@ -146,22 +148,22 @@ implements MultiselectChoices {
//.filter(this::ignoreHidden) // I believe is redundant, has major performance impact
);
- this.dataRows = _Observables.lazy(()->
+ this.dataRows = _Observables.lazy(()->_Timing.callVerbose("dataRows.get()", ()->
dataElements.getValue().stream()
.map(IndexedFunction.zeroBased((rowIndex, element)->new DataRow(rowIndex, this, element, tokens(element))))
- .collect(Can.toCan()));
+ .collect(Can.toCan())));
- this.dataRowsFilteredAndSorted = _Observables.lazy(()->
+ this.dataRowsFilteredAndSorted = _Observables.lazy(()->_Timing.callVerbose("dataRowsFilteredAndSorted.get()", ()->
dataRows.getValue().stream()
.filter(adaptSearchPredicate())
.sorted(sortingComparator()
.orElseGet(()->(a, b)->0)) // else don't sort (no-op comparator for streams)
- .collect(Can.toCan()));
+ .collect(Can.toCan())));
- this.dataRowsSelected = _Observables.lazy(()->
+ this.dataRowsSelected = _Observables.lazy(()->_Timing.callVerbose("dataRowsSelected.get()", ()->
dataRows.getValue().stream()
.filter(dataRow->dataRow.getSelectToggle().getValue().booleanValue())
- .collect(Can.toCan()));
+ .collect(Can.toCan())));
this.selectionChanges = _Bindables.forValue(Boolean.FALSE);
this.selectAllToggle = _Bindables.forValue(Boolean.FALSE);
@@ -374,6 +376,16 @@ implements MultiselectChoices {
.collect(Can.toCan()));
}
+ @NonNull
+ public Iterator<DataRow> getDataRowsFilteredAndSorted(final long skip, final long limit) {
+ var stopWatch = _Timing.now();
+ var iterator = dataRowsFilteredAndSorted.getValue()
+ .iterator(Math.toIntExact(skip), Math.toIntExact(limit));
+ System.err.printf("get iterator took %s%n", stopWatch);
+ stopWatch.stop();
+ return iterator;
+ }
+
// used internally for serialization
private DataTable exportAll() {
return new DataTable(
@@ -406,12 +418,19 @@ implements MultiselectChoices {
static Memento create(
final @NonNull DataTableInteractive tableInteractive) {
- return new Memento(
+ var stopWatch = _Timing.now();
+
+ var memento = new Memento(
tableInteractive.managedMember.getIdentifier(),
tableInteractive.where,
tableInteractive.exportAll(),
tableInteractive.searchArgument.getValue(),
tableInteractive.getSelectedRowIndexes());
+
+ stopWatch.stop();
+ System.err.printf("table memento created, took %s%n", stopWatch);
+
+ return memento;
}
private final @NonNull Identifier featureId;
@@ -432,6 +451,8 @@ implements MultiselectChoices {
throw _Exceptions.illegalArgument("cannot recreate from memento for deleted object");
}
+ var stopWatch = _Timing.now();
+
val memberId = featureId.getMemberLogicalName();
final ManagedMember managedMember = featureId.getType().isPropertyOrCollection()
@@ -456,6 +477,10 @@ implements MultiselectChoices {
.filter(dataRow->selectedRowIndexes.contains(dataRow.getRowIndex()))
.forEach(dataRow->dataRow.getSelectToggle().setValue(true));
});
+
+ stopWatch.stop();
+ System.err.printf("table restored from memento, took %s%n", stopWatch);
+
return dataTableInteractive;
}
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataTable.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataTable.java
index 0f8ace874c..168053129b 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataTable.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataTable.java
@@ -41,6 +41,7 @@ import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.causeway.core.metamodel.context.MetaModelContext;
import org.apache.causeway.core.metamodel.object.ManagedObject;
import org.apache.causeway.core.metamodel.objectmanager.ObjectBulkLoader;
+import org.apache.causeway.core.metamodel.objectmanager.ObjectBulkLoader.Request;
import org.apache.causeway.core.metamodel.objectmanager.ObjectManager;
import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
@@ -348,9 +349,20 @@ public class DataTable implements Serializable {
var elementType = MetaModelContext.instanceElseFail().specForTypeElseFail(elementTypeClass);
var dataTable = new DataTable(elementType, columnIds
.map(columnId->elementType.getAssociationElseFail(columnId, MixedIn.INCLUDED)));
- var rowElements = rowElementBookmarks.map(objectManager::loadObjectElseFail);
- dataTable.setDataElements(rowElements);
- dataTable.tableFriendlyName = tableFriendlyName;
+
+ if(elementType.isEntity()) {
+ //TODO[CAUSEWAY-3779] instead of using the common element type we need to use to actual types
+ //(use a multivalued map by type)
+ final Can<String> idsStringified = rowElementBookmarks.map(Bookmark::getIdentifier);
+ var rowElements = objectManager.getObjectBulkLoader()
+ .loadObject(Request.of(elementType,
+ Query.selectByIdQuery(elementType.getCorrespondingClass(), idsStringified)));
+ dataTable.setDataElements(rowElements);
+ } else {
+ var rowElements = rowElementBookmarks.map(objectManager::loadObjectElseFail);
+ dataTable.setDataElements(rowElements);
+ }
+ dataTable.tableFriendlyName = this.tableFriendlyName;
return dataTable;
}
}
diff --git a/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/metamodel/facets/entity/JdoEntityFacet.java b/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/metamodel/facets/entity/JdoEntityFacet.java
index c7bfdef422..1d8fc3417b 100644
--- a/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/metamodel/facets/entity/JdoEntityFacet.java
+++ b/persistence/jdo/datanucleus/src/main/java/org/apache/causeway/persistence/jdo/datanucleus/metamodel/facets/entity/JdoEntityFacet.java
@@ -40,6 +40,7 @@ import org.springframework.lang.Nullable;
import org.apache.causeway.applib.query.AllInstancesQuery;
import org.apache.causeway.applib.query.NamedQuery;
import org.apache.causeway.applib.query.Query;
+import org.apache.causeway.applib.query.SelectByIdQuery;
import org.apache.causeway.applib.services.bookmark.Bookmark;
import org.apache.causeway.applib.services.exceprecog.Category;
import org.apache.causeway.applib.services.exceprecog.ExceptionRecognizerService;
@@ -250,6 +251,24 @@ implements EntityFacet {
return resultList;
+ } else if(query instanceof SelectByIdQuery) {
+
+ //TODO[CAUSEWAY-3779] implement select by
+
+ val queryById = (SelectByIdQuery<?>) query;
+ val queryEntityType = queryById.getResultType();
+ val idsStringified = queryById.getIdsStringified();
+
+ // guard against misuse
+ _Assert.assertTypeIsInstanceOf(queryEntityType, entityClass);
+
+ val pm = getPersistenceManager();
+
+ val q = pm.newQuery(queryEntityType, ":p.contains(id)");
+
+ val resultList = fetchWithinTransaction(()->(List)q.execute(idsStringified.toList()));
+ return resultList;
+
} else if(query instanceof NamedQuery) {
val applibNamedQuery = (NamedQuery<?>) query;
diff --git a/persistence/jpa/integration/src/main/java/org/apache/causeway/persistence/jpa/integration/entity/JpaEntityFacet.java b/persistence/jpa/integration/src/main/java/org/apache/causeway/persistence/jpa/integration/entity/JpaEntityFacet.java
index bfd94780b3..03514c795e 100644
--- a/persistence/jpa/integration/src/main/java/org/apache/causeway/persistence/jpa/integration/entity/JpaEntityFacet.java
+++ b/persistence/jpa/integration/src/main/java/org/apache/causeway/persistence/jpa/integration/entity/JpaEntityFacet.java
@@ -31,6 +31,7 @@ import org.springframework.lang.Nullable;
import org.apache.causeway.applib.query.AllInstancesQuery;
import org.apache.causeway.applib.query.NamedQuery;
import org.apache.causeway.applib.query.Query;
+import org.apache.causeway.applib.query.SelectByIdQuery;
import org.apache.causeway.applib.services.bookmark.Bookmark;
import org.apache.causeway.applib.services.repository.EntityState;
import org.apache.causeway.commons.collections.Can;
@@ -154,7 +155,12 @@ public class JpaEntityFacet
typedQuery.getResultStream()
.map(entity -> ManagedObject.adaptSingular(entitySpec, entity)));
- } else if (query instanceof NamedQuery) {
+ } else if(query instanceof SelectByIdQuery) {
+
+ //TODO[CAUSEWAY-3779] implement select by
+
+ } else if(query instanceof NamedQuery) {
+
val applibNamedQuery = (NamedQuery<?>) query;
val queryResultType = applibNamedQuery.getResultType();
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsSortableDataProvider.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsSortableDataProvider.java
index 89a97ab3a7..b0538a05d8 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsSortableDataProvider.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsSortableDataProvider.java
@@ -86,6 +86,15 @@ extends SortableDataProvider<DataRow, String> {
.iterator(Math.toIntExact(skip), Math.toIntExact(limit));
}
+ //TODO[CAUSEWAY-3779] idea
+// @Override
+// public Iterator<DataRow> iterator(final long skip, final long limit) {
+// var dataTable = getDataTableModel();
+// // honor (single) column sort (if any)
+// dataTable.getColumnSort().setValue(columnSort().orElse(null));
+// return dataTable.getDataRowsFilteredAndSorted(Math.toIntExact(skip), Math.toIntExact(limit));
+// }
+
// -- HELPER
private Optional<DataTableInteractive.ColumnSort> columnSort() {