You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/04/23 06:13:47 UTC
[isis] 01/02: ISIS-2619: introduces new
DeriveMixinMembersPostProcessor
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch ISIS-2619
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 3026c349409c3663c7db7bb5edd4f8ebcc1953e2
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Apr 23 07:04:24 2021 +0100
ISIS-2619: introduces new DeriveMixinMembersPostProcessor
---
.../param/DeriveMixinMembersPostProcessor.java | 65 ++++++++++++++++++
.../dflt/ProgrammingModelFacetsJava8.java | 13 ++--
.../specloader/facetprocessor/FacetProcessor.java | 78 +++++++++++-----------
.../facets/TenantedAuthorizationFacetFactory.java | 14 ++--
4 files changed, 121 insertions(+), 49 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/param/DeriveMixinMembersPostProcessor.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/param/DeriveMixinMembersPostProcessor.java
new file mode 100644
index 0000000..8207049
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/param/DeriveMixinMembersPostProcessor.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.core.metamodel.postprocessors.param;
+
+import java.util.stream.Stream;
+
+import org.apache.isis.core.metamodel.context.MetaModelContext;
+import org.apache.isis.core.metamodel.context.MetaModelContextAware;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.progmodel.ObjectSpecificationPostProcessor;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.MixedIn;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.metamodel.specloader.specimpl.ObjectMemberAbstract;
+
+import lombok.Setter;
+import lombok.val;
+
+
+public class DeriveMixinMembersPostProcessor
+implements ObjectSpecificationPostProcessor, MetaModelContextAware {
+
+ @Setter(onMethod = @__(@Override))
+ private MetaModelContext metaModelContext;
+
+ @Override
+ public void postProcess(final ObjectSpecification objectSpecification) {
+
+ // all the actions of this type
+ val actionTypes = metaModelContext.getSystemEnvironment().isPrototyping()
+ ? ActionType.USER_AND_PROTOTYPE
+ : ActionType.USER_ONLY;
+ objectSpecification.streamActions(actionTypes, MixedIn.INCLUDED);
+
+ // and all the collections of this type
+ objectSpecification.streamCollections(MixedIn.INCLUDED);
+
+ // and all the properties of this type
+ objectSpecification.streamProperties(MixedIn.INCLUDED);
+
+ }
+
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
index 8f55ad8..23ce56c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
@@ -143,6 +143,7 @@ import org.apache.isis.core.metamodel.methods.MemberSupportAnnotationEnforcesSup
import org.apache.isis.core.metamodel.methods.MethodByClassMap;
import org.apache.isis.core.metamodel.methods.OrphanedSupportingMethodValidator;
import org.apache.isis.core.metamodel.postprocessors.param.DeriveFacetsPostProcessor;
+import org.apache.isis.core.metamodel.postprocessors.param.DeriveMixinMembersPostProcessor;
import org.apache.isis.core.metamodel.progmodel.ProgrammingModelAbstract;
import org.apache.isis.core.metamodel.services.title.TitlesAndTranslationsValidator;
@@ -236,7 +237,7 @@ public final class ProgrammingModelFacetsJava8 extends ProgrammingModelAbstract
addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, DisabledObjectFacetViaMethodFactory.class);
val postConstructMethodsCache = new MethodByClassMap();
-
+
addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new RecreatableObjectFacetFactory(postConstructMethodsCache));
addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, JaxbFacetFactory.class);
@@ -256,7 +257,7 @@ public final class ProgrammingModelFacetsJava8 extends ProgrammingModelAbstract
// must come after DomainObjectAnnotationFacetFactory & MixinFacetFactory
addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, ContributingFacetDerivedFromMixinFacetFactory.class);
-
+
addFactory(FacetProcessingOrder.F1_LAYOUT, GridFacetFactory.class);
// must come before DomainObjectLayoutFacetFactory
@@ -327,7 +328,7 @@ public final class ProgrammingModelFacetsJava8 extends ProgrammingModelAbstract
addFactory(FacetProcessingOrder.G1_VALUE_TYPES, OffsetDateTimeValueFacetUsingSemanticsProviderFactory.class);
addFactory(FacetProcessingOrder.G1_VALUE_TYPES, ZonedDateTimeValueFacetUsingSemanticsProviderFactory.class);
- addFactory(FacetProcessingOrder.Z0_BEFORE_FINALLY, AuthorizationFacetFactory.class);
+ addFactory(FacetProcessingOrder.Z0_BEFORE_FINALLY, AuthorizationFacetFactory.class); // TODO: reimplement as a PostProcessor
// written to not trample over TypeOf if already installed
addFactory(FacetProcessingOrder.Z1_FINALLY, CollectionFacetFactory.class);
@@ -346,12 +347,14 @@ public final class ProgrammingModelFacetsJava8 extends ProgrammingModelAbstract
addFactory(FacetProcessingOrder.Z1_FINALLY, FacetsFacetAnnotationFactory.class);
// must be after all named facets and description facets have been installed
- addFactory(FacetProcessingOrder.Z1_FINALLY, TranslationFacetFactory.class);
+ addFactory(FacetProcessingOrder.Z1_FINALLY, TranslationFacetFactory.class); // TODO: reimplement as a PostProcessor
+
addFactory(FacetProcessingOrder.Z1_FINALLY, ViewModelSemanticCheckingFacetFactory.class);
+ addPostProcessor(PostProcessingOrder.A0_BEFORE_BUILTIN, DeriveMixinMembersPostProcessor.class);
addPostProcessor(PostProcessingOrder.A1_BUILTIN, DeriveFacetsPostProcessor.class);
-
+
addValidator(new MemberSupportAnnotationEnforcesSupportingMethodValidator());
addValidator(new OrphanedSupportingMethodValidator());
addValidator(new TitlesAndTranslationsValidator());
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/facetprocessor/FacetProcessor.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/facetprocessor/FacetProcessor.java
index ab133f7..a038a92 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/facetprocessor/FacetProcessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/facetprocessor/FacetProcessor.java
@@ -80,7 +80,7 @@ public class FacetProcessor {
* {@link MethodPrefixBasedFacetFactory}.
*
*/
- private final _Lazy<Set<String>> methodPrefixes =
+ private final _Lazy<Set<String>> methodPrefixes =
_Lazy.threadSafe(this::init_methodPrefixes);
/**
@@ -111,13 +111,13 @@ public class FacetProcessor {
* Lazily initialized, then cached. The lists remain in the same order that
* the factories were {@link #registerFactory(FacetFactory) registered}.
*/
- private final _Lazy<ListMultimap<FeatureType, FacetFactory>> factoryListByFeatureType =
+ private final _Lazy<ListMultimap<FeatureType, FacetFactory>> factoryListByFeatureType =
_Lazy.threadSafe(this::init_factoriesByFeatureType);
-
+
// -- LIFECYCLE
-
+
public void init() {
- cleanUp();
+ cleanUp();
programmingModel.streamFactories()
.forEach(this::registerFactory);
}
@@ -131,7 +131,7 @@ public class FacetProcessor {
factories.clear();
factoryByFactoryType.clear();
}
-
+
private void registerFactory(FacetFactory factory) {
factoryByFactoryType.put(factory.getClass(), factory);
factories.add(factory);
@@ -155,11 +155,11 @@ public class FacetProcessor {
* {@link PropertyOrCollectionIdentifyingFacetFactory}s.
*/
public void findAssociationCandidateAccessors(
- Stream<Method> methods,
+ Stream<Method> methods,
Consumer<Method> onCandidate) {
-
+
val factories = propertyOrCollectionIdentifyingFactories.get();
-
+
methods.forEach(method->{
for (val facetFactory : factories) {
if (facetFactory.isPropertyOrCollectionAccessorCandidate(method)) {
@@ -178,9 +178,9 @@ public class FacetProcessor {
* Intended to be called after {@link #findAndRemovePropertyAccessors(MethodRemover, java.util.List)} once only reference properties remain.
*/
public void findAndRemovePropertyAccessors(
- MethodRemover methodRemover,
+ MethodRemover methodRemover,
List<Method> methodListToAppendTo) {
-
+
for (val facetFactory : propertyOrCollectionIdentifyingFactories.get()) {
facetFactory.findAndRemovePropertyAccessors(methodRemover, methodListToAppendTo);
}
@@ -195,9 +195,9 @@ public class FacetProcessor {
* List)
*/
public void findAndRemoveCollectionAccessors(
- MethodRemover methodRemover,
+ MethodRemover methodRemover,
List<Method> methodListToAppendTo) {
-
+
for (val facetFactory : propertyOrCollectionIdentifyingFactories.get()) {
facetFactory.findAndRemoveCollectionAccessors(methodRemover, methodListToAppendTo);
}
@@ -247,11 +247,11 @@ public class FacetProcessor {
private List<ObjectSpecIdFacetFactory> objectSpecIfFacetFactoryList = null;
-
+
private List<ObjectSpecIdFacetFactory> getObjectSpecIfFacetFactoryList() {
if(objectSpecIfFacetFactoryList == null) {
val facetFactories = _Lists.<ObjectSpecIdFacetFactory>newArrayList();
-
+
factoryListByFeatureType.get().getOrElseEmpty(FeatureType.OBJECT)
.forEach(facetFactory->{
if (facetFactory instanceof ObjectSpecIdFacetFactory) {
@@ -259,7 +259,7 @@ public class FacetProcessor {
facetFactories.add(objectSpecIdFacetFactory);
}
});
-
+
objectSpecIfFacetFactoryList = Collections.unmodifiableList(facetFactories);
}
return objectSpecIfFacetFactoryList;
@@ -284,12 +284,12 @@ public class FacetProcessor {
Class<?> cls,
MethodRemover methodRemover,
FacetHolder facetHolder) {
-
+
val ctx = new ProcessClassContext(
- cls,
- removerElseNoopRemover(methodRemover),
+ cls,
+ removerElseNoopRemover(methodRemover),
facetHolder);
-
+
factoryListByFeatureType.get().getOrElseEmpty(FeatureType.OBJECT)
.forEach(facetFactory->facetFactory.process(ctx));
}
@@ -315,7 +315,7 @@ public class FacetProcessor {
* - what type of feature the method represents (property,
* action, collection etc)
* @param isMixinMain
- * - Whether we are currently processing a mixin type AND this context's method
+ * - Whether we are currently processing a mixin type AND this context's method
* can be identified as the main method of the processed mixin class. (since 2.0)
*/
public void process(
@@ -323,24 +323,26 @@ public class FacetProcessor {
Method method,
MethodRemover methodRemover,
FacetedMethod facetedMethod,
- FeatureType featureType,
+ FeatureType featureType,
boolean isMixinMain) {
-
+
facetedMethod.setMetaModelContext(metaModelContext);
-
+
val processMethodContext =
new ProcessMethodContext(
- cls,
- featureType,
- method,
+ cls,
+ featureType,
+ method,
removerElseNoopRemover(methodRemover), facetedMethod, isMixinMain);
-
- factoryListByFeatureType.get().getOrElseEmpty(featureType)
- .forEach(facetFactory->facetFactory.process(processMethodContext));
+
+ for (FacetFactory facetFactory : factoryListByFeatureType.get().getOrElseEmpty(featureType)) {
+
+ facetFactory.process(processMethodContext);
+ }
}
public void processMemberOrder(ObjectMember facetHolder) {
-
+
}
/**
@@ -367,9 +369,9 @@ public class FacetProcessor {
int paramNum,
MethodRemover methodRemover,
FacetedMethodParameter facetedMethodParameter) {
-
+
facetedMethodParameter.setMetaModelContext(metaModelContext);
-
+
for (val featureType : FeatureType.PARAMETERS_ONLY) {
processParams(introspectedClass, method, paramNum, methodRemover, facetedMethodParameter, featureType);
}
@@ -382,12 +384,12 @@ public class FacetProcessor {
MethodRemover methodRemover,
FacetedMethodParameter facetedMethodParameter,
FeatureType featureType) {
-
+
facetedMethodParameter.setMetaModelContext(metaModelContext);
-
+
val processParameterContext =
new ProcessParameterContext(introspectedClass, method, paramNum, methodRemover, facetedMethodParameter);
-
+
factoryListByFeatureType.get().getOrElseEmpty(featureType)
.forEach(facetFactory->facetFactory.processParams(processParameterContext));
}
@@ -399,7 +401,7 @@ public class FacetProcessor {
methodFilteringFactories.clear();
propertyOrCollectionIdentifyingFactories.clear();
}
-
+
// -- INITIALIZERS
private ListMultimap<FeatureType, FacetFactory> init_factoriesByFeatureType() {
@@ -443,7 +445,7 @@ public class FacetProcessor {
}
return propertyOrCollectionIdentifyingFactories;
}
-
+
// -- HELPER
private static MethodRemover removerElseNoopRemover(MethodRemover methodRemover) {
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/facets/TenantedAuthorizationFacetFactory.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/facets/TenantedAuthorizationFacetFactory.java
index a60e300..d08b5ba 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/facets/TenantedAuthorizationFacetFactory.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/facets/TenantedAuthorizationFacetFactory.java
@@ -33,6 +33,7 @@ import org.apache.isis.core.metamodel.facetapi.FeatureType;
import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import org.apache.isis.extensions.secman.api.tenancy.ApplicationTenancyEvaluator;
import org.apache.isis.extensions.secman.api.user.ApplicationUserRepository;
@@ -78,35 +79,36 @@ public class TenantedAuthorizationFacetFactory extends FacetFactoryAbstract {
FacetUtil.addFacet(createFacet(cls, facetHolder));
}
-
+
public static class QueryResultsCacheProviderHolder {
@Inject @Getter private Provider<QueryResultsCache> queryResultsCacheProvider;
}
-
+
@SuppressWarnings({ "rawtypes", "unchecked" })
private TenantedAuthorizationFacetDefault createFacet(
- final Class<?> cls,
+ final Class<?> cls,
final FacetHolder holder) {
val serviceRegistry = super.getServiceRegistry();
+ final boolean mixinClass = serviceRegistry.lookupService(SpecificationLoader.class).map(x -> x.loadSpecification(cls)).map(x -> x.isMixin()).isPresent();
val evaluators = serviceRegistry
.select(ApplicationTenancyEvaluator.class)
.stream()
- .filter(applicationTenancyEvaluator->applicationTenancyEvaluator.handles(cls))
+ .filter(applicationTenancyEvaluator-> mixinClass || applicationTenancyEvaluator.handles(cls))
.collect(Collectors.<ApplicationTenancyEvaluator>toList());
if(evaluators.isEmpty()) {
return null;
}
-
+
val applicationUserRepository =
serviceRegistry.lookupService(ApplicationUserRepository.class).orElse(null);
val queryResultsCacheProvider =
super.getServiceInjector()
.injectServicesInto(new QueryResultsCacheProviderHolder())
.getQueryResultsCacheProvider();
- val userService =
+ val userService =
serviceRegistry.lookupService(UserService.class).orElse(null);
return new TenantedAuthorizationFacetDefault(