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 2020/01/21 15:15:23 UTC
[isis] 02/02: ISIS-2158: have @XmlRootElement win over any other
RecreatableObjectFacet providing strategy
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
commit fff71c540413525a8bc5a1d5fb0a6609ee38b51f
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Jan 21 16:15:10 2020 +0100
ISIS-2158: have @XmlRootElement win over any other
RecreatableObjectFacet providing strategy
---
.../org/apache/isis/applib/annotation/Nature.java | 6 +--
.../isis/core/metamodel/facetapi/FacetUtil.java | 21 ++++++++++
.../DomainObjectAnnotationFacetFactory.java | 4 +-
...atableObjectFacetForDomainObjectAnnotation.java | 7 ++--
.../RecreatableObjectFacetAbstract.java | 4 +-
.../recreatable/RecreatableObjectFacetFactory.java | 45 ++++++++++++++--------
...ableObjectFacetForXmlRootElementAnnotation.java | 3 +-
.../demoapp/dom/events/DemoEventSubscriber.java | 2 +-
8 files changed, 64 insertions(+), 28 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/annotation/Nature.java b/api/applib/src/main/java/org/apache/isis/applib/annotation/Nature.java
index 4ffa704..fcb6fc1 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/annotation/Nature.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/annotation/Nature.java
@@ -70,8 +70,8 @@ public enum Nature {
* constructed from some sort of internal memory data structure.
*
* <p>
- * As for a {@link #EXTERNAL_ENTITY}, the identity of a synthetic entity is determined solely by the state of
- * object's properties (that have not been set to be ignored using
+ * As for a {@link #EXTERNAL_ENTITY}, the identity of a synthetic entity is determined solely by the
+ * state of object's properties (that have not been set to be ignored using
* {@link org.apache.isis.applib.annotation.Property#notPersisted()}).
* </p>
*
@@ -82,7 +82,7 @@ public enum Nature {
*/
INMEMORY_ENTITY,
/**
- * An object that is conceptually part of the application layer, and which surfaces behaviour and/or state that
+ * An object that is conceptually part of the application layer, and which surfaces behavior and/or state that
* is aggregate of one or more domain entity.
*
* <p>
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetUtil.java
index 3a1bd13..db73476 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetUtil.java
@@ -31,6 +31,27 @@ import lombok.val;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class FacetUtil {
+ public static void addIfNotAlreadyPresent(final Facet facet) {
+ if (facet == null) {
+ return;
+ }
+ val facetHolder = facet.getFacetHolder();
+ if(!facetHolder.containsFacet(facet.facetType())) {
+ facetHolder.addFacet(facet);
+ }
+ }
+
+ public static void replaceIfAlreadyPresent(final Facet facet) {
+ if (facet == null) {
+ return;
+ }
+ val facetHolder = facet.getFacetHolder();
+ facetHolder.addOrReplaceFacet(facet);
+ // second call sets the underlying facet as well to this type
+ // hacky, to pass validation
+ facetHolder.addOrReplaceFacet(facet);
+ }
+
public static void addOrReplaceFacet(final Facet facet) {
if (facet == null) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
index 940e69b..dd5c9d8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
@@ -41,6 +41,7 @@ import org.apache.isis.applib.services.HasUniqueId;
import org.apache.isis.core.commons.internal.collections._Maps;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
import org.apache.isis.core.metamodel.facetapi.FeatureType;
import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
@@ -300,7 +301,8 @@ implements MetaModelRefiner, PostConstructMethodCache, ObjectSpecIdFacetFactory
postConstructMethodCache);
if(recreatableObjectFacet != null) {
- super.addFacet(recreatableObjectFacet);
+ // handle with least priority
+ FacetUtil.addIfNotAlreadyPresent(recreatableObjectFacet);
} else {
val mixinDomainObjectIfAny =
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java
index d978af1..d51408c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/recreatable/RecreatableObjectFacetForDomainObjectAnnotation.java
@@ -28,8 +28,8 @@ import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
import org.apache.isis.core.metamodel.facets.object.recreatable.RecreatableObjectFacetDeclarativeInitializingAbstract;
import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
-public class RecreatableObjectFacetForDomainObjectAnnotation extends
-RecreatableObjectFacetDeclarativeInitializingAbstract {
+public class RecreatableObjectFacetForDomainObjectAnnotation
+extends RecreatableObjectFacetDeclarativeInitializingAbstract {
public static ViewModelFacet create(
final Optional<DomainObject> domainObjectIfAny,
@@ -49,8 +49,7 @@ RecreatableObjectFacetDeclarativeInitializingAbstract {
case VIEW_MODEL:
case EXTERNAL_ENTITY:
case INMEMORY_ENTITY:
- final ViewModelFacet existingFacet = holder.getFacet(ViewModelFacet.class);
- if (existingFacet != null) {
+ if (!holder.containsFacet(ViewModelFacet.class)) {
return null;
}
return new RecreatableObjectFacetForDomainObjectAnnotation(
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
index 70f9758..56b747b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetAbstract.java
@@ -35,7 +35,9 @@ import org.apache.isis.core.metamodel.specloader.specimpl.dflt.ObjectSpecificati
import lombok.val;
-public abstract class RecreatableObjectFacetAbstract extends FacetAbstract implements ViewModelFacet {
+public abstract class RecreatableObjectFacetAbstract
+extends FacetAbstract
+implements ViewModelFacet {
private final PostConstructMethodCache postConstructMethodCache;
private final ViewModelFacet.RecreationMechanism recreationMechanism;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetFactory.java
index 718af72..f5b48d5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetFactory.java
@@ -30,7 +30,6 @@ import org.apache.isis.applib.RecreatableDomainObject;
import org.apache.isis.applib.ViewModel;
import org.apache.isis.core.commons.internal.collections._Maps;
import org.apache.isis.core.config.IsisConfiguration;
-import org.apache.isis.core.metamodel.facetapi.Facet;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
import org.apache.isis.core.metamodel.facetapi.FacetUtil;
import org.apache.isis.core.metamodel.facetapi.FeatureType;
@@ -42,6 +41,8 @@ import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
+import lombok.val;
+
public class RecreatableObjectFacetFactory extends FacetFactoryAbstract
implements MetaModelRefiner, PostConstructMethodCache {
@@ -56,34 +57,41 @@ implements MetaModelRefiner, PostConstructMethodCache {
@Override
public void process(final ProcessClassContext processClassContext) {
+ val facetHolder = processClassContext.getFacetHolder();
+ val type = processClassContext.getCls();
+
// ViewModel interface
if (ViewModel.class.isAssignableFrom(processClassContext.getCls())) {
final PostConstructMethodCache postConstructMethodCache = this;
FacetUtil.addFacet(new RecreatableObjectFacetForRecreatableObjectInterface(
- processClassContext.getFacetHolder(), postConstructMethodCache));
+ facetHolder, postConstructMethodCache));
}
// ViewModel annotation
- final org.apache.isis.applib.annotation.ViewModel annotation = Annotations.getAnnotation(processClassContext.getCls(), org.apache.isis.applib.annotation.ViewModel.class);
- FacetUtil.addFacet(create(annotation, processClassContext.getFacetHolder()));
-
- // XmlRootElement annotation
- final XmlRootElement xmlRootElement = Annotations.getAnnotation(processClassContext.getCls(), XmlRootElement.class);
- FacetUtil.addFacet(create(xmlRootElement, processClassContext.getFacetHolder()));
-
+ final org.apache.isis.applib.annotation.ViewModel annotation =
+ Annotations.getAnnotation(type, org.apache.isis.applib.annotation.ViewModel.class);
+ FacetUtil.addFacet(create(annotation, facetHolder));
+
// RecreatableDomainObject interface
- if (RecreatableDomainObject.class.isAssignableFrom(processClassContext.getCls())) {
+ if (RecreatableDomainObject.class.isAssignableFrom(type)) {
final PostConstructMethodCache postConstructMethodCache = this;
FacetUtil.addFacet(new RecreatableObjectFacetForRecreatableDomainObjectInterface(
- processClassContext.getFacetHolder(), postConstructMethodCache));
+ facetHolder, postConstructMethodCache));
}
+
+ // XmlRootElement annotation
+ final XmlRootElement xmlRootElement = Annotations.getAnnotation(type, XmlRootElement.class);
+ // handle with highest precedence
+ FacetUtil.replaceIfAlreadyPresent(create(xmlRootElement, facetHolder));
- // DomainObject(nature=VIEW_MODEL) is managed by the DomainObjectFacetFactory
+ // DomainObject(nature=VIEW_MODEL) is managed by the DomainObjectAnnotationFacetFactory
}
private ViewModelFacet create(final org.apache.isis.applib.annotation.ViewModel annotation, final FacetHolder holder) {
final PostConstructMethodCache postConstructMethodCache = this;
- return annotation != null ? new RecreatableObjectFacetForViewModelAnnotation(holder, postConstructMethodCache) : null;
+ return annotation != null
+ ? new RecreatableObjectFacetForViewModelAnnotation(holder, postConstructMethodCache)
+ : null;
}
private ViewModelFacet create(final XmlRootElement annotation, final FacetHolder holder) {
@@ -100,16 +108,19 @@ implements MetaModelRefiner, PostConstructMethodCache {
programmingModel.addValidator((objectSpec, validate) -> {
- final ViewModelFacet facet = objectSpec.getFacet(ViewModelFacet.class);
- final Facet underlyingFacet = facet != null ? facet.getUnderlyingFacet() : null;
- if(underlyingFacet != null && underlyingFacet.getClass() != facet.getClass()) {
+ val viewModelFacet = objectSpec.getFacet(ViewModelFacet.class);
+ val underlyingFacet = viewModelFacet != null ? viewModelFacet.getUnderlyingFacet() : null;
+ if(underlyingFacet == null) {
+ return true;
+ }
+ if(underlyingFacet.getClass() != viewModelFacet.getClass()) {
validate.onFailure(
objectSpec,
objectSpec.getIdentifier(),
"%s: has multiple incompatible annotations/interfaces indicating that " +
"it is a recreatable object of some sort (%s and %s)",
objectSpec.getFullIdentifier(),
- facet.getClass().getSimpleName(),
+ viewModelFacet.getClass().getSimpleName(),
underlyingFacet.getClass().getSimpleName());
}
return true;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java
index 390dc9f..315be60 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetForXmlRootElementAnnotation.java
@@ -24,7 +24,8 @@ import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
import org.apache.isis.core.metamodel.facets.PostConstructMethodCache;
-public class RecreatableObjectFacetForXmlRootElementAnnotation extends RecreatableObjectFacetAbstract {
+public class RecreatableObjectFacetForXmlRootElementAnnotation
+extends RecreatableObjectFacetAbstract {
public RecreatableObjectFacetForXmlRootElementAnnotation(
diff --git a/examples/demo/src/main/java/demoapp/dom/events/DemoEventSubscriber.java b/examples/demo/src/main/java/demoapp/dom/events/DemoEventSubscriber.java
index 039cad9..d16c0a9 100644
--- a/examples/demo/src/main/java/demoapp/dom/events/DemoEventSubscriber.java
+++ b/examples/demo/src/main/java/demoapp/dom/events/DemoEventSubscriber.java
@@ -52,7 +52,7 @@ public class DemoEventSubscriber {
log.info(emphasize("UiButtonEvent")); // <-- log to the console
- val eventLogWriter = factoryService.instantiate(EventLogWriter.class); // <-- get a new writer
+ val eventLogWriter = factoryService.get(EventLogWriter.class); // <-- get a new writer
wrapper.async(eventLogWriter)
.run(EventLogWriter::storeEvent, event);