You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/12/20 09:16:55 UTC
[isis] branch master updated: ISIS-2882: allow bindable values to install a guard against invalid values
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new 2d5138f ISIS-2882: allow bindable values to install a guard against invalid values
2d5138f is described below
commit 2d5138f9f63f0cf8ed7d3f37a36cd583896b7168
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Dec 20 10:16:48 2021 +0100
ISIS-2882: allow bindable values to install a guard against invalid
values
---
.../internal/binding/_BindableAbstract.java | 10 ++++++++-
.../interactions/managed/ManagedProperty.java | 4 ++--
.../interactions/managed/ManagedValue.java | 8 +++++--
.../managed/ParameterNegotiationModel.java | 2 ++
.../managed/PropertyNegotiationModel.java | 1 +
.../isis/core/metamodel/spec/ManagedObjects.java | 26 +++++++++++++++++++---
.../core/metamodel/spec/feature/ObjectFeature.java | 3 ++-
.../core/runtime/context/IsisAppCommonContext.java | 4 ----
.../actionresponse/ActionResultResponseType.java | 2 +-
.../ui/components/scalars/TextFieldValueModel.java | 2 +-
.../blobclob/IsisBlobOrClobPanelAbstract.java | 2 +-
.../components/scalars/primitive/BooleanPanel.java | 4 ++--
12 files changed, 50 insertions(+), 18 deletions(-)
diff --git a/commons/src/main/java/org/apache/isis/commons/internal/binding/_BindableAbstract.java b/commons/src/main/java/org/apache/isis/commons/internal/binding/_BindableAbstract.java
index 29271ca..4533496 100644
--- a/commons/src/main/java/org/apache/isis/commons/internal/binding/_BindableAbstract.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/binding/_BindableAbstract.java
@@ -59,6 +59,13 @@ public abstract class _BindableAbstract<T> implements Bindable<T> {
*/
@Setter private @NonNull UnaryOperator<T> valueRefiner = UnaryOperator.identity();
+ /**
+ * Called within {@link #setValue()} to guard against invalid new values.
+ * <p>
+ * use-case: guard against incompatible types
+ */
+ @Setter private @NonNull UnaryOperator<T> valueGuard = UnaryOperator.identity();
+
public _BindableAbstract() {
}
@@ -106,10 +113,11 @@ public abstract class _BindableAbstract<T> implements Bindable<T> {
}
@Override
- public void setValue(final T newValue) {
+ public void setValue(final T proposedNewValue) {
if (isBound()) {
throw _Exceptions.unrecoverable("Cannot set value on a bound bindable.");
}
+ val newValue = valueGuard.apply(proposedNewValue);
if (value != newValue) {
value = newValue;
markInvalid();
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedProperty.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedProperty.java
index a454931..90566e9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedProperty.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedProperty.java
@@ -124,8 +124,8 @@ extends ManagedMember {
return interactionVeto;
}
- ManagedObject managedObject = property.set(getOwner(), proposedNewValue, InteractionInitiatedBy.USER);
- setOwner(managedObject);
+ val updatedOwner = property.set(getOwner(), proposedNewValue, InteractionInitiatedBy.USER);
+ setOwner(updatedOwner);
observablePropValue.invalidate();
return Optional.empty();
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedValue.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedValue.java
index d261c01..ae5cf21 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedValue.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedValue.java
@@ -43,13 +43,17 @@ public interface ManagedValue {
Observable<Can<ManagedObject>> getChoices();
default void update(final UnaryOperator<ManagedObject> updater) {
- val value = getValue();
- value.setValue(updater.apply(value.getValue()));
+ val valueHolder = getValue();
+ val oldValue = valueHolder.getValue();
+ val newValue = updater.apply(oldValue);
+ valueHolder.setValue(newValue);
}
/**
* Requires specified objects, that is ManagedObjects require an ObjectSpecification.
+ * @deprecated does not preserve memoized bookmarks; use for testing only!
*/
+ @Deprecated
default void updatePojo(final UnaryOperator<Object> updater) {
update(v->ManagedObject.of(v.getSpecification(), updater.apply(v.getPojo())));
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ParameterNegotiationModel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ParameterNegotiationModel.java
index e9617d9..95b3756 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ParameterNegotiationModel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ParameterNegotiationModel.java
@@ -38,6 +38,7 @@ import org.apache.isis.core.metamodel.consent.Consent;
import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.isis.core.metamodel.consent.InteractionResult;
import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.ManagedObjects;
import org.apache.isis.core.metamodel.spec.ManagedObjects.EntityUtil;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
@@ -277,6 +278,7 @@ public class ParameterNegotiationModel {
bindableParamValue = _Bindables.forValue(initialValue);
bindableParamValue.setValueRefiner(EntityUtil::refetch);
+ bindableParamValue.setValueGuard(ManagedObjects.assertInstanceOf(metaModel.getElementType()));
bindableParamValue.addListener((e,o,n)->{
if(n==null) {
// lift null to empty ...
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/PropertyNegotiationModel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/PropertyNegotiationModel.java
index bba953d..8e775f6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/PropertyNegotiationModel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/PropertyNegotiationModel.java
@@ -63,6 +63,7 @@ public class PropertyNegotiationModel implements ManagedValue {
proposedValue = _Bindables.forValue(defaultValue);
proposedValue.setValueRefiner(EntityUtil::refetch);
+ proposedValue.setValueGuard(ManagedObjects.assertInstanceOf(propMeta.getElementType()));
proposedValue.addListener((e,o,n)->{
invalidateChoicesAndValidation();
});
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java
index b312869..fd05830 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java
@@ -123,6 +123,29 @@ public final class ManagedObjects {
.map(ObjectSpecification::getLogicalTypeName);
}
+ // -- INSTANCE-OF CHECKS
+
+ /**
+ * guard against incompatible type
+ */
+ public static @NonNull UnaryOperator<ManagedObject> assertInstanceOf(final ObjectSpecification elementType) {
+ val upperBound = elementType.getCorrespondingClass();
+ return newValue -> {
+ if(ManagedObjects.isNullOrUnspecifiedOrEmpty(newValue)) {
+ return newValue;
+ }
+ val newValueActualType = newValue.getSpecification().getCorrespondingClass();
+ if(!upperBound.isAssignableFrom(newValueActualType)) {
+ throw _Exceptions.illegalArgument("Proposed new value has incompatible type %s,"
+ + "must be an instance of %s.",
+ newValueActualType.getName(),
+ upperBound.getName());
+ }
+ return newValue;
+ };
+ }
+
+
// -- IDENTIFICATION
public static Optional<ObjectSpecification> spec(final @Nullable ManagedObject managedObject) {
@@ -1063,7 +1086,4 @@ public final class ManagedObjects {
}
-
-
-
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectFeature.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectFeature.java
index 70d797b..956694a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectFeature.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectFeature.java
@@ -155,8 +155,9 @@ public interface ObjectFeature extends Specification {
* element the collection holds (not the type of collection).
* <li>for an {@link ObjectAction action} will return {@link ObjectAction#getReturnType()}.
* <li>for an {@link ObjectActionParameter action parameter}, will return the type of
- * the parameter}.
+ * the parameter.
* </ul>
+ * @since 2.0
*/
ObjectSpecification getElementType();
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/context/IsisAppCommonContext.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/context/IsisAppCommonContext.java
index bc4bead..ddf57ca 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/context/IsisAppCommonContext.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/context/IsisAppCommonContext.java
@@ -19,7 +19,6 @@
package org.apache.isis.core.runtime.context;
import java.util.Optional;
-import java.util.function.Function;
import java.util.function.Supplier;
import org.springframework.lang.Nullable;
@@ -76,9 +75,6 @@ public class IsisAppCommonContext implements HasMetaModelContext {
@Getter(lazy = true, value = AccessLevel.PRIVATE)
private final ObjectMementoService mementoService = lookupServiceElseFail(ObjectMementoService.class);
- @Getter(lazy = true)
- private final Function<Object, ManagedObject> pojoToAdapter = metaModelContext.getObjectManager()::adapt;
-
public Optional<MessageBroker> getMessageBroker() {
return getMetaModelContext().getServiceRegistry().lookupService(MessageBroker.class);
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java
index cbe0018..fc8bf04 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/actionresponse/ActionResultResponseType.java
@@ -251,7 +251,7 @@ public enum ActionResultResponseType {
.findFirst()
.orElseThrow(_Exceptions::noSuchElement);
- final var scalarAdapter = commonContext.getPojoToAdapter().apply(pojo);
+ final var scalarAdapter = commonContext.getObjectManager().adapt(pojo);
return scalarAdapter;
}
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/TextFieldValueModel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/TextFieldValueModel.java
index 340b7c6..15e9836 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/TextFieldValueModel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/TextFieldValueModel.java
@@ -66,7 +66,7 @@ public class TextFieldValueModel<T extends Serializable> extends Model<T> {
if (object == null) {
scalarModel.setObject(null);
} else {
- val objectAdapter = scalarModel.getCommonContext().getPojoToAdapter().apply(object);
+ val objectAdapter = scalarModel.getCommonContext().getObjectManager().adapt(object);
scalarModel.setObject(objectAdapter);
}
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/blobclob/IsisBlobOrClobPanelAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/blobclob/IsisBlobOrClobPanelAbstract.java
index 8ad5463..9210858 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/blobclob/IsisBlobOrClobPanelAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/blobclob/IsisBlobOrClobPanelAbstract.java
@@ -186,7 +186,7 @@ extends ScalarPanelAbstract {
}
val blob = getBlobOrClobFrom(fileUploads);
- val objectAdapter = scalarModel.getCommonContext().getPojoToAdapter().apply(blob);
+ val objectAdapter = scalarModel.getCommonContext().getObjectManager().adapt(blob);
getModel().setObject(objectAdapter);
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/primitive/BooleanPanel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/primitive/BooleanPanel.java
index 9f0e2e7..047639d 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/primitive/BooleanPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/primitive/BooleanPanel.java
@@ -139,7 +139,7 @@ public class BooleanPanel extends ScalarPanelAbstract {
@Override
public void setObject(final Boolean object) {
- val objectAdapter = scalarModel.getCommonContext().getPojoToAdapter().apply(object);
+ val objectAdapter = scalarModel.getCommonContext().getObjectManager().adapt(object);
getModel().setObject(objectAdapter);
}
}) {
@@ -178,7 +178,7 @@ public class BooleanPanel extends ScalarPanelAbstract {
final ObjectSpecification objectSpecification = getModel().getScalarTypeSpec();
if(objectSpecification.getFullIdentifier().equals("boolean")) {
if(getModel().getObject() == null) {
- val objectAdapter = scalarModel.getCommonContext().getPojoToAdapter().apply(Boolean.FALSE);
+ val objectAdapter = scalarModel.getCommonContext().getObjectManager().adapt(Boolean.FALSE);
getModel().setObject(objectAdapter);
}
}