This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch 3051.validate.memberId.clash in repository https://gitbox.apache.org/repos/asf/causeway.git
commit 51d6f916911c95a58b8882305932a95e9645d722 Author: Andi Huber <[email protected]> AuthorDate: Wed May 3 09:48:16 2023 +0200 CAUSEWAY-3051: simplify MM validator type hierarchy --- .../progmodel/ProgrammingModelConstants.java | 2 + ...reteTypeToBeIncludedWithMetamodelValidator.java | 7 +- .../actions/action/ActionOverloadingValidator.java | 6 +- .../annotation/HomePageFacetAnnotationFactory.java | 8 +- .../DomainObjectAnnotationFacetFactory.java | 8 +- ...tionEnforcesMetamodelContributionValidator.java | 6 +- .../MethodPrefixBasedFacetFactoryAbstract.java | 6 +- ...tProcessor.java => MetaModelPostProcessor.java} | 21 ++- ...ct.java => MetaModelPostProcessorAbstract.java} | 6 +- ...ssOnActionFromConfiguredRegexPostProcessor.java | 4 +- .../all/DescribedAsFromTypePostProcessor.java | 4 +- ...stProcessor.java => SanityChecksValidator.java} | 71 ++++++- .../i18n/SynthesizeObjectNamingPostProcessor.java | 4 +- .../all/i18n/TranslationPostProcessor.java | 4 +- .../authorization/AuthorizationPostProcessor.java | 4 +- ...ynthesizeDomainEventsForMixinPostProcessor.java | 4 +- ...NavigationFacetFromHiddenTypePostProcessor.java | 4 +- .../object/ProjectionFacetsPostProcessor.java | 4 +- .../param/ChoicesAndDefaultsPostProcessor.java | 4 +- .../param/TypicalLengthFromTypePostProcessor.java | 4 +- .../DisabledFromImmutablePostProcessor.java | 4 +- .../core/metamodel/progmodel/ProgrammingModel.java | 16 +- .../progmodel/ProgrammingModelAbstract.java | 14 +- .../progmodel/ProgrammingModelInitFilter.java | 4 +- .../ProgrammingModelInitFilterDefault.java | 4 +- .../dflt/ProgrammingModelFacetsJava11.java | 4 +- .../title/TitlesAndTranslationsValidator.java | 22 +-- .../specloader/SpecificationLoaderDefault.java | 28 +-- .../specloader/{_Util.java => _LogUtil.java} | 2 +- .../core/metamodel/specloader/_ValidateUtil.java | 88 +++++++++ .../specloader/postprocessor/PostProcessor.java | 69 ++----- .../specloader/validator/MetaModelValidator.java | 34 +++- .../validator/MetaModelVisitingValidator.java | 4 +- .../MetaModelVisitingValidatorAbstract.java | 45 ----- .../facets/TenantedAuthorizationPostProcessor.java | 4 +- ...etaModelVisitingValidatorForClauseAbstract.java | 6 +- .../DomainModelTest_usingBadDomain.java | 12 ++ .../bad/Configuration_usingInvalidDomain.java | 1 + .../testdomain/model/bad/InvalidMemberIdClash.java | 208 +++++++++++++++++++++ 39 files changed, 526 insertions(+), 224 deletions(-) diff --git a/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java b/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java index 53a7713ff1..dc6413ef21 100644 --- a/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java +++ b/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java @@ -533,6 +533,8 @@ public final class ProgrammingModelConstants { + "Tuple type ${patType} referenced by @ParameterTuple annotated parameter has no or more than one public constructor."), VETOED_OR_MANAGED_TYPE_NOT_ALLOWED_TO_ENTER_METAMODEL("${type}: has a member with either vetoed or managed " + "element-type ${elementType}, which is not allowed"), + MEMBER_ID_CLASH("${type}: has members using the same member-id " + + "'${memberId}', which is not allowed; clashes:\n\t[1]${member1}\n\t[2]${member2}"), ; private final String template; diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java index 2697ca2081..502ea2829a 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java @@ -29,14 +29,13 @@ import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.MixedIn; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; -import org.apache.causeway.core.metamodel.specloader.validator.MetaModelVisitingValidatorAbstract; +import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidatorAbstract; import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure; -import lombok.NonNull; import lombok.val; public class ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator -extends MetaModelVisitingValidatorAbstract { +extends MetaModelValidatorAbstract { @Inject public ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator(final MetaModelContext mmc) { @@ -44,7 +43,7 @@ extends MetaModelVisitingValidatorAbstract { } @Override - public void validate(final @NonNull ObjectSpecification spec) { + public void validateObjectEnter(final ObjectSpecification spec) { if(spec.getBeanSort()==BeanSort.UNKNOWN && !spec.isAbstract()) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionOverloadingValidator.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionOverloadingValidator.java index 409da3cd88..e678d93cb0 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionOverloadingValidator.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionOverloadingValidator.java @@ -28,7 +28,7 @@ import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.spec.ActionScope; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.MixedIn; -import org.apache.causeway.core.metamodel.specloader.validator.MetaModelVisitingValidatorAbstract; +import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidatorAbstract; import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure; import lombok.NonNull; @@ -43,7 +43,7 @@ import lombok.val; * @see <a href="https://issues.apache.org/jira/browse/CAUSEWAY-2493">CAUSEWAY-2493</a> */ public class ActionOverloadingValidator -extends MetaModelVisitingValidatorAbstract { +extends MetaModelValidatorAbstract { @Inject public ActionOverloadingValidator(final MetaModelContext mmc) { @@ -51,7 +51,7 @@ extends MetaModelVisitingValidatorAbstract { } @Override - public void validate(final @NonNull ObjectSpecification spec) { + public void validateObjectEnter(final @NonNull ObjectSpecification spec) { if(spec.getBeanSort()!=BeanSort.UNKNOWN && !spec.isAbstract()) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/homepage/annotation/HomePageFacetAnnotationFactory.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/homepage/annotation/HomePageFacetAnnotationFactory.java index 50c0942a23..13901dbb23 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/homepage/annotation/HomePageFacetAnnotationFactory.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/homepage/annotation/HomePageFacetAnnotationFactory.java @@ -40,7 +40,7 @@ import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.MixedIn; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidator; -import org.apache.causeway.core.metamodel.specloader.validator.MetaModelVisitingValidatorAbstract; +import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidatorAbstract; import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure; import static org.apache.causeway.commons.internal.functions._Predicates.not; @@ -78,12 +78,12 @@ implements MetaModelRefiner { } private MetaModelValidator newValidatorVisitor(final MetaModelContext mmc) { - return new MetaModelVisitingValidatorAbstract(mmc) { + return new MetaModelValidatorAbstract(mmc) { private final Map<String, ObjectAction> actionsHavingHomePageFacet = _Maps.newHashMap(); @Override - public void validate(final @NonNull ObjectSpecification spec) { + public void validateObjectEnter(final @NonNull ObjectSpecification spec) { if(spec.isInjectable()) { return; } @@ -106,7 +106,7 @@ implements MetaModelRefiner { } @Override - public void summarize() { + public void validateExit() { if(actionsHavingHomePageFacet.size()>1) { final Set<String> homepageActionIdSet = actionsHavingHomePageFacet.values().stream() diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java index b26736980a..f3003b478e 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java @@ -73,7 +73,7 @@ import org.apache.causeway.core.metamodel.facets.object.viewmodel.ViewModelFacet import org.apache.causeway.core.metamodel.object.MmEventUtils; import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; -import org.apache.causeway.core.metamodel.specloader.validator.MetaModelVisitingValidatorAbstract; +import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidatorAbstract; import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure; import static org.apache.causeway.commons.internal.base._NullSafe.stream; @@ -562,13 +562,13 @@ implements programmingModel .addValidator( - new MetaModelVisitingValidatorAbstract(programmingModel.getMetaModelContext()){ + new MetaModelValidatorAbstract(programmingModel.getMetaModelContext()){ final _Multimaps.ListMultimap<String, ObjectSpecification> specsByLogicalTypeName = _Multimaps.newConcurrentListMultimap(); @Override - public void validate(final ObjectSpecification objSpec) { + public void validateObjectEnter(final ObjectSpecification objSpec) { // @DomainObject(logicalTypeName=...) must be unique among non-abstract types // Eg. having an ApplicationUser interface and a concrete ApplicationUser (JDO) @@ -590,7 +590,7 @@ implements } @Override - public void summarize() { + public void validateExit() { specsByLogicalTypeName.forEach((logicalTypeName, collidingSpecs)->{ if(isObjectTypeCollision(collidingSpecs)) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/methods/DomainIncludeAnnotationEnforcesMetamodelContributionValidator.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/methods/DomainIncludeAnnotationEnforcesMetamodelContributionValidator.java index 615817439b..226cb60859 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/methods/DomainIncludeAnnotationEnforcesMetamodelContributionValidator.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/methods/DomainIncludeAnnotationEnforcesMetamodelContributionValidator.java @@ -46,7 +46,7 @@ import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.MixedIn; import org.apache.causeway.core.metamodel.specloader.specimpl.ObjectMemberAbstract; import org.apache.causeway.core.metamodel.specloader.specimpl.ObjectSpecificationAbstract; -import org.apache.causeway.core.metamodel.specloader.validator.MetaModelVisitingValidatorAbstract; +import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidatorAbstract; import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure; import lombok.val; @@ -56,7 +56,7 @@ import lombok.val; * @see org.apache.causeway.applib.annotation.Domain.Include */ public class DomainIncludeAnnotationEnforcesMetamodelContributionValidator -extends MetaModelVisitingValidatorAbstract { +extends MetaModelValidatorAbstract { private final _ClassCache classCache; @@ -67,7 +67,7 @@ extends MetaModelVisitingValidatorAbstract { } @Override - public void validate(final ObjectSpecification spec) { + public void validateObjectEnter(final ObjectSpecification spec) { if(!(spec instanceof ObjectSpecificationAbstract) || spec.isAbstract() diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/methods/MethodPrefixBasedFacetFactoryAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/methods/MethodPrefixBasedFacetFactoryAbstract.java index ddab2f6ea8..57c3b2a87e 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/methods/MethodPrefixBasedFacetFactoryAbstract.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/methods/MethodPrefixBasedFacetFactoryAbstract.java @@ -29,7 +29,7 @@ import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.MixedIn; import org.apache.causeway.core.metamodel.specloader.specimpl.ObjectMemberAbstract; import org.apache.causeway.core.metamodel.specloader.specimpl.ObjectSpecificationAbstract; -import org.apache.causeway.core.metamodel.specloader.validator.MetaModelVisitingValidatorAbstract; +import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidatorAbstract; import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure; import lombok.Getter; @@ -71,7 +71,7 @@ implements MethodPrefixBasedFacetFactory { } programmingModel - .addValidator(new MetaModelVisitingValidatorAbstract(programmingModel.getMetaModelContext()) { + .addValidator(new MetaModelValidatorAbstract(programmingModel.getMetaModelContext()) { @Override public String toString() { @@ -80,7 +80,7 @@ implements MethodPrefixBasedFacetFactory { } @Override - public void validate(final ObjectSpecification spec) { + public void validateObjectEnter(final ObjectSpecification spec) { if(spec.isInjectable()) { return; diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/ObjectSpecificationPostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/MetaModelPostProcessor.java similarity index 79% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/ObjectSpecificationPostProcessor.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/MetaModelPostProcessor.java index 07ee364144..724af6155b 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/ObjectSpecificationPostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/MetaModelPostProcessor.java @@ -25,17 +25,26 @@ import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter; import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; -public interface ObjectSpecificationPostProcessor +public interface MetaModelPostProcessor extends HasMetaModelContext { default boolean isEnabled() { return true; } - default void postProcessObject(final ObjectSpecification objSpec) {}; - default void postProcessAction(final ObjectSpecification objSpec, final ObjectAction act) {}; - default void postProcessParameter(final ObjectSpecification objSpec, final ObjectAction act, final ObjectActionParameter param) {}; - default void postProcessProperty(final ObjectSpecification objSpec, final OneToOneAssociation prop) {}; - default void postProcessCollection(final ObjectSpecification objSpec, final OneToManyAssociation coll) {}; + /** entry to post-processing of specified {@code objSpec} */ + default void postProcessObject(final ObjectSpecification objSpec) {} + + /** post process action - mixed-in included */ + default void postProcessAction(final ObjectSpecification objSpec, final ObjectAction act) {} + + /** post process action-parameter - mixed-in included */ + default void postProcessParameter(final ObjectSpecification objSpec, final ObjectAction act, final ObjectActionParameter param) {} + + /** post process property - mixed-in included */ + default void postProcessProperty(final ObjectSpecification objSpec, final OneToOneAssociation prop) {} + + /** post process collection - mixed-in included */ + default void postProcessCollection(final ObjectSpecification objSpec, final OneToManyAssociation coll) {} } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/ObjectSpecificationPostProcessorAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/MetaModelPostProcessorAbstract.java similarity index 90% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/ObjectSpecificationPostProcessorAbstract.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/MetaModelPostProcessorAbstract.java index 367f7b1d4e..809e54a105 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/ObjectSpecificationPostProcessorAbstract.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/MetaModelPostProcessorAbstract.java @@ -28,13 +28,13 @@ import lombok.Getter; import lombok.NonNull; import lombok.val; -public abstract class ObjectSpecificationPostProcessorAbstract -implements ObjectSpecificationPostProcessor { +public abstract class MetaModelPostProcessorAbstract +implements MetaModelPostProcessor { @Getter(onMethod_ = {@Override}) private final @NonNull MetaModelContext metaModelContext; - protected ObjectSpecificationPostProcessorAbstract(final MetaModelContext metaModelContext) { + protected MetaModelPostProcessorAbstract(final MetaModelContext metaModelContext) { super(); this.metaModelContext = metaModelContext; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/CssOnActionFromConfiguredRegexPostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/CssOnActionFromConfiguredRegexPostProcessor.java index afb5fde78e..43609da4e7 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/CssOnActionFromConfiguredRegexPostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/CssOnActionFromConfiguredRegexPostProcessor.java @@ -26,12 +26,12 @@ import org.apache.causeway.core.metamodel.facets.members.cssclass.CssClassFacet; import org.apache.causeway.core.metamodel.facets.members.cssclass.annotprop.CssClassFacetOnActionFromConfiguredRegex; import org.apache.causeway.core.metamodel.facets.members.cssclassfa.CssClassFaFacet; import org.apache.causeway.core.metamodel.facets.members.cssclassfa.annotprop.CssClassFaFacetOnMemberFromConfiguredRegex; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; public class CssOnActionFromConfiguredRegexPostProcessor -extends ObjectSpecificationPostProcessorAbstract { +extends MetaModelPostProcessorAbstract { @Inject public CssOnActionFromConfiguredRegexPostProcessor(final MetaModelContext mmc) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/DescribedAsFromTypePostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/DescribedAsFromTypePostProcessor.java index 2f6d42efdf..2551e2a807 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/DescribedAsFromTypePostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/DescribedAsFromTypePostProcessor.java @@ -27,7 +27,7 @@ import org.apache.causeway.core.metamodel.facets.all.described.ObjectDescribedFa import org.apache.causeway.core.metamodel.facets.all.described.ParamDescribedFacet; import org.apache.causeway.core.metamodel.facets.members.described.annotprop.MemberDescribedFacetFromType; import org.apache.causeway.core.metamodel.facets.param.described.annotderived.ParamDescribedFacetFromType; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter; @@ -36,7 +36,7 @@ import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; public class DescribedAsFromTypePostProcessor -extends ObjectSpecificationPostProcessorAbstract { +extends MetaModelPostProcessorAbstract { @Inject public DescribedAsFromTypePostProcessor(final MetaModelContext mmc) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/SanityChecksPostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/SanityChecksValidator.java similarity index 50% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/SanityChecksPostProcessor.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/SanityChecksValidator.java index ebdee2e640..87f83fac99 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/SanityChecksPostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/SanityChecksValidator.java @@ -18,56 +18,111 @@ */ package org.apache.causeway.core.metamodel.postprocessors.all; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + import javax.inject.Inject; +import org.apache.causeway.commons.internal.assertions._Assert; import org.apache.causeway.core.config.progmodel.ProgrammingModelConstants; import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter; +import org.apache.causeway.core.metamodel.spec.feature.ObjectMember; import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; +import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidatorAbstract; import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure; +import lombok.val; + /** * Checks various preconditions for a sane meta-model. * <ul> + * <li>Guard against members and mixed-in members that share the same member-id.</li> * <li>Guard against members that contribute vetoed or managed types. * Those are not allowed as member/return/param.</li> * </ul> */ -public class SanityChecksPostProcessor -extends ObjectSpecificationPostProcessorAbstract { +public class SanityChecksValidator +extends MetaModelValidatorAbstract { @Inject - public SanityChecksPostProcessor(final MetaModelContext mmc) { + public SanityChecksValidator(final MetaModelContext mmc) { super(mmc); } @Override - public void postProcessParameter(final ObjectSpecification objectSpecification, final ObjectAction objectAction, final ObjectActionParameter parameter) { + public void validateParameter(final ObjectSpecification objectSpecification, final ObjectAction objectAction, final ObjectActionParameter parameter) { checkElementType(parameter, objectSpecification, parameter.getElementType()); } @Override - public void postProcessAction(final ObjectSpecification objectSpecification, final ObjectAction objectAction) { + public void validateAction(final ObjectSpecification objectSpecification, final ObjectAction objectAction) { + checkMemberId(objectAction, objectSpecification); checkElementType(objectAction, objectSpecification, objectAction.getElementType()); } @Override - public void postProcessProperty(final ObjectSpecification objectSpecification, final OneToOneAssociation prop) { + public void validateProperty(final ObjectSpecification objectSpecification, final OneToOneAssociation prop) { + checkMemberId(prop, objectSpecification); checkElementType(prop, objectSpecification, prop.getElementType()); } @Override - public void postProcessCollection(final ObjectSpecification objectSpecification, final OneToManyAssociation coll) { + public void validateCollection(final ObjectSpecification objectSpecification, final OneToManyAssociation coll) { + checkMemberId(coll, objectSpecification); checkElementType(coll, objectSpecification, coll.getElementType()); } + @Override + public void validateObjectEnter(final ObjectSpecification objSpec) { + + _Assert.assertTrue(processingStack.isEmpty()); //TODO[CAUSEWAY-3051] simplify + + processingStack.push(memberIds = new HashMap<>()); + //System.err.printf("START %s %s%n", this.getClass().getSimpleName(), ""+this.hashCode()); + } + + @Override + public void validateObjectExit(final ObjectSpecification objSpec) { + memberIds = processingStack.isEmpty() + ? null + : processingStack.pop(); // garbage collect + } + // -- HELPER + private Map<String, ObjectMember> memberIds; + private final Stack<Map<String, ObjectMember>> processingStack = new Stack<>(); + + private void checkMemberId( + final ObjectMember objectMember, + final ObjectSpecification declaringType) { + + if(declaringType.isAbstract()) return; + + //TODO[CAUSEWAY-3051] debugging tests + if(objectMember.getDeclaringType().toString().contains("InvalidMemberIdClash")) { + System.err.printf("member-id: %s (%s)%n", objectMember.getId(), objectMember.getDeclaringType()); + } + + val previous = memberIds.put(objectMember.getId(), objectMember); + if(previous!=null) { + ValidationFailure.raiseFormatted(objectMember, + ProgrammingModelConstants.Violation.MEMBER_ID_CLASH + .builder() + .addVariable("type", declaringType.fqcn()) + .addVariable("memberId", ""+objectMember.getId()) + .addVariable("member1", previous.getFeatureIdentifier().getFullIdentityString()) + .addVariable("member2", objectMember.getFeatureIdentifier().getFullIdentityString()) + .buildMessage()); + } + } + private void checkElementType( final FacetHolder facetHolder, final ObjectSpecification declaringType, diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/i18n/SynthesizeObjectNamingPostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/i18n/SynthesizeObjectNamingPostProcessor.java index e1e562ce58..79cd799c07 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/i18n/SynthesizeObjectNamingPostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/i18n/SynthesizeObjectNamingPostProcessor.java @@ -28,13 +28,13 @@ import org.apache.causeway.core.metamodel.facets.all.i8n.noun.NounForm; import org.apache.causeway.core.metamodel.facets.all.i8n.noun.NounForms; import org.apache.causeway.core.metamodel.facets.all.named.ObjectNamedFacet; import org.apache.causeway.core.metamodel.facets.all.named.ObjectNamedFacetSynthesized; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import lombok.val; public class SynthesizeObjectNamingPostProcessor -extends ObjectSpecificationPostProcessorAbstract { +extends MetaModelPostProcessorAbstract { @Inject public SynthesizeObjectNamingPostProcessor(final MetaModelContext metaModelContext) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/i18n/TranslationPostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/i18n/TranslationPostProcessor.java index c14c99c0d2..25b160dd73 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/i18n/TranslationPostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/all/i18n/TranslationPostProcessor.java @@ -32,7 +32,7 @@ import org.apache.causeway.core.metamodel.facets.all.i8n.HasMemoizableTranslatio import org.apache.causeway.core.metamodel.facets.all.named.MemberNamedFacet; import org.apache.causeway.core.metamodel.facets.all.named.ObjectNamedFacet; import org.apache.causeway.core.metamodel.facets.all.named.ParamNamedFacet; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter; @@ -40,7 +40,7 @@ import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; public class TranslationPostProcessor -extends ObjectSpecificationPostProcessorAbstract { +extends MetaModelPostProcessorAbstract { @Inject public TranslationPostProcessor(final MetaModelContext metaModelContext) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationPostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationPostProcessor.java index c77b54fdc5..f3b4bb1c65 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationPostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationPostProcessor.java @@ -22,14 +22,14 @@ import javax.inject.Inject; import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; public class AuthorizationPostProcessor - extends ObjectSpecificationPostProcessorAbstract { + extends MetaModelPostProcessorAbstract { @Inject public AuthorizationPostProcessor(final MetaModelContext metaModelContext) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/SynthesizeDomainEventsForMixinPostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/SynthesizeDomainEventsForMixinPostProcessor.java index 32d14e9f09..3123813c9f 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/SynthesizeDomainEventsForMixinPostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/SynthesizeDomainEventsForMixinPostProcessor.java @@ -24,7 +24,7 @@ import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facets.actions.action.invocation.ActionDomainEventFacet; import org.apache.causeway.core.metamodel.facets.collections.collection.modify.CollectionDomainEventFacet; import org.apache.causeway.core.metamodel.facets.properties.property.modify.PropertyDomainEventFacet; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation; @@ -37,7 +37,7 @@ import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure * unless overwritten by the mixin type. */ public class SynthesizeDomainEventsForMixinPostProcessor -extends ObjectSpecificationPostProcessorAbstract { +extends MetaModelPostProcessorAbstract { @Inject public SynthesizeDomainEventsForMixinPostProcessor(final MetaModelContext metaModelContext) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenTypePostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenTypePostProcessor.java index 8fcce81eb6..61c7a8e7d6 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenTypePostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenTypePostProcessor.java @@ -24,7 +24,7 @@ import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facetapi.FacetUtil; import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenTypeFacet; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.ObjectMember; @@ -35,7 +35,7 @@ import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; * Installs the {@link NavigationFacetFromHiddenType} on all of the * {@link ObjectMember}s of the {@link ObjectSpecification}. */ -public class NavigationFacetFromHiddenTypePostProcessor extends ObjectSpecificationPostProcessorAbstract { +public class NavigationFacetFromHiddenTypePostProcessor extends MetaModelPostProcessorAbstract { @Inject public NavigationFacetFromHiddenTypePostProcessor(final MetaModelContext metaModelContext) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/object/ProjectionFacetsPostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/object/ProjectionFacetsPostProcessor.java index dec1600115..ceb448fc05 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/object/ProjectionFacetsPostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/object/ProjectionFacetsPostProcessor.java @@ -32,13 +32,13 @@ import org.apache.causeway.core.metamodel.facets.object.projection.ident.CssClas import org.apache.causeway.core.metamodel.facets.object.projection.ident.IconFacetFromProjectionFacet; import org.apache.causeway.core.metamodel.facets.object.projection.ident.TitleFacetFromProjectionFacet; import org.apache.causeway.core.metamodel.facets.object.title.TitleFacet; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import lombok.val; public class ProjectionFacetsPostProcessor -extends ObjectSpecificationPostProcessorAbstract { +extends MetaModelPostProcessorAbstract { @Inject public ProjectionFacetsPostProcessor(final MetaModelContext metaModelContext) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/param/ChoicesAndDefaultsPostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/param/ChoicesAndDefaultsPostProcessor.java index a6a07b29d2..1178cd5c97 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/param/ChoicesAndDefaultsPostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/param/ChoicesAndDefaultsPostProcessor.java @@ -35,7 +35,7 @@ import org.apache.causeway.core.metamodel.facets.properties.choices.PropertyChoi import org.apache.causeway.core.metamodel.facets.properties.choices.enums.PropertyChoicesFacetFromChoicesFacet; import org.apache.causeway.core.metamodel.facets.properties.defaults.PropertyDefaultFacet; import org.apache.causeway.core.metamodel.facets.properties.defaults.fromtype.PropertyDefaultFacetFromDefaultedFacet; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.MixedIn; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; @@ -53,7 +53,7 @@ import lombok.val; * */ public class ChoicesAndDefaultsPostProcessor -extends ObjectSpecificationPostProcessorAbstract { +extends MetaModelPostProcessorAbstract { @Inject public ChoicesAndDefaultsPostProcessor(final MetaModelContext metaModelContext) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/param/TypicalLengthFromTypePostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/param/TypicalLengthFromTypePostProcessor.java index ae16377fda..de4a46e80e 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/param/TypicalLengthFromTypePostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/param/TypicalLengthFromTypePostProcessor.java @@ -25,14 +25,14 @@ import org.apache.causeway.core.metamodel.facetapi.FacetUtil; import org.apache.causeway.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet; import org.apache.causeway.core.metamodel.facets.param.typicallen.fromtype.TypicalLengthFacetOnParameterFromType; import org.apache.causeway.core.metamodel.facets.properties.typicallen.fromtype.TypicalLengthFacetOnPropertyFromType; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; public class TypicalLengthFromTypePostProcessor -extends ObjectSpecificationPostProcessorAbstract { +extends MetaModelPostProcessorAbstract { @Inject public TypicalLengthFromTypePostProcessor(final MetaModelContext metaModelContext) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/properties/DisabledFromImmutablePostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/properties/DisabledFromImmutablePostProcessor.java index 06f2d211b9..2335b7e8ff 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/properties/DisabledFromImmutablePostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/properties/DisabledFromImmutablePostProcessor.java @@ -28,7 +28,7 @@ import org.apache.causeway.core.metamodel.facets.object.immutable.EditingEnabled import org.apache.causeway.core.metamodel.facets.object.immutable.ImmutableFacet; import org.apache.causeway.core.metamodel.facets.properties.disabled.fromimmutable.DisabledFacetOnPropertyFromImmutable; import org.apache.causeway.core.metamodel.facets.properties.disabled.fromimmutable.DisabledFacetOnPropertyFromImmutableFactory; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; @@ -40,7 +40,7 @@ import lombok.val; * Replaces {@link DisabledFacetOnPropertyFromImmutableFactory} */ public class DisabledFromImmutablePostProcessor -extends ObjectSpecificationPostProcessorAbstract { +extends MetaModelPostProcessorAbstract { @Inject public DisabledFromImmutablePostProcessor(final MetaModelContext metaModelContext) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModel.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModel.java index 5ab71fc8cf..95e27f764a 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModel.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModel.java @@ -23,10 +23,10 @@ import java.util.stream.Stream; import org.apache.causeway.core.metamodel.context.HasMetaModelContext; import org.apache.causeway.core.metamodel.facets.FacetFactory; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessor; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessor; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidator; -import org.apache.causeway.core.metamodel.specloader.validator.MetaModelVisitingValidatorAbstract; +import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidatorAbstract; import lombok.NonNull; @@ -123,7 +123,7 @@ extends HasMetaModelContext { T instance, Marker ... markers); - <T extends ObjectSpecificationPostProcessor> void addPostProcessor( + <T extends MetaModelPostProcessor> void addPostProcessor( PostProcessingOrder order, T instance, Marker ... markers); @@ -131,7 +131,7 @@ extends HasMetaModelContext { Stream<FacetFactory> streamFactories(); Stream<MetaModelValidator> streamValidators(); - Stream<ObjectSpecificationPostProcessor> streamPostProcessors(); + Stream<MetaModelPostProcessor> streamPostProcessors(); // -- SHORTCUTS @@ -147,9 +147,9 @@ extends HasMetaModelContext { final @NonNull Consumer<ObjectSpecification> validator, final Marker ... markers) { - addValidator(new MetaModelVisitingValidatorAbstract(getMetaModelContext()) { + addValidator(new MetaModelValidatorAbstract(getMetaModelContext()) { @Override - public void validate(final @NonNull ObjectSpecification spec) { + public void validateObjectEnter(final @NonNull ObjectSpecification spec) { validator.accept(spec); } }); @@ -159,9 +159,9 @@ extends HasMetaModelContext { final @NonNull Consumer<ObjectSpecification> validator, final Marker ... markers) { - addValidator(new MetaModelVisitingValidatorAbstract(getMetaModelContext()) { + addValidator(new MetaModelValidatorAbstract(getMetaModelContext()) { @Override - public void validate(final @NonNull ObjectSpecification spec) { + public void validateObjectEnter(final @NonNull ObjectSpecification spec) { if(spec.isInjectable()) { return; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelAbstract.java index 6f1db4990a..87f0312f7c 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelAbstract.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelAbstract.java @@ -31,7 +31,7 @@ import org.apache.causeway.core.metamodel.context.HasMetaModelContext; import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner; import org.apache.causeway.core.metamodel.facets.FacetFactory; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessor; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessor; import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidator; import lombok.EqualsAndHashCode; @@ -49,7 +49,7 @@ implements private List<FacetFactory> unmodifiableFactories; private List<MetaModelValidator> unmodifiableValidators; - private List<ObjectSpecificationPostProcessor> unmodifiablePostProcessors; + private List<MetaModelPostProcessor> unmodifiablePostProcessors; protected ProgrammingModelAbstract(final MetaModelContext metaModelContext) { this.metaModelContext = metaModelContext; @@ -109,7 +109,7 @@ implements } @Override - public <T extends ObjectSpecificationPostProcessor> void addPostProcessor( + public <T extends MetaModelPostProcessor> void addPostProcessor( final PostProcessingOrder order, final T instance, final Marker... markers) { @@ -135,7 +135,7 @@ implements } @Override - public Stream<ObjectSpecificationPostProcessor> streamPostProcessors() { + public Stream<MetaModelPostProcessor> streamPostProcessors() { assertInitialized(); return unmodifiablePostProcessors.stream(); } @@ -194,14 +194,14 @@ implements return validators; } - private final SetMultimap<PostProcessingOrder, ProgrammingModelEntry<? extends ObjectSpecificationPostProcessor>> + private final SetMultimap<PostProcessingOrder, ProgrammingModelEntry<? extends MetaModelPostProcessor>> postProcessorEntriesByOrder = _Multimaps.newSetMultimap(LinkedHashSet::new); - private List<ObjectSpecificationPostProcessor> snapshotPostProcessors( + private List<MetaModelPostProcessor> snapshotPostProcessors( final ProgrammingModelInitFilter filter, final MetaModelContext metaModelContext) { - val postProcessors = _Lists.<ObjectSpecificationPostProcessor>newArrayList(); + val postProcessors = _Lists.<MetaModelPostProcessor>newArrayList(); for(val order : PostProcessingOrder.values()) { val postProcessorEntrySet = postProcessorEntriesByOrder.get(order); if(postProcessorEntrySet==null) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelInitFilter.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelInitFilter.java index 89412621b4..36c77e2909 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelInitFilter.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelInitFilter.java @@ -25,7 +25,7 @@ import org.springframework.lang.Nullable; import org.apache.causeway.commons.internal.functions._Predicates; import org.apache.causeway.core.metamodel.facets.FacetFactory; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessor; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessor; import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidator; import static org.apache.causeway.commons.internal.base._NullSafe.isEmpty; @@ -48,7 +48,7 @@ public interface ProgrammingModelInitFilter { ProgrammingModel.Marker[] markersIfAny); boolean acceptPostProcessor( - Class<? extends ObjectSpecificationPostProcessor> postProcessorType, + Class<? extends MetaModelPostProcessor> postProcessorType, ProgrammingModel.Marker[] markersIfAny); // -- PREDEFINED PREDICATES diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelInitFilterDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelInitFilterDefault.java index 6110da8ac9..a3ebd4b8b8 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelInitFilterDefault.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodel/ProgrammingModelInitFilterDefault.java @@ -30,7 +30,7 @@ import org.springframework.stereotype.Component; import org.apache.causeway.core.config.CausewayConfiguration; import org.apache.causeway.core.metamodel.CausewayModuleCoreMetamodel; import org.apache.causeway.core.metamodel.facets.FacetFactory; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessor; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessor; import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidator; import static org.apache.causeway.core.metamodel.progmodel.ProgrammingModelInitFilter.excluding; @@ -79,7 +79,7 @@ public class ProgrammingModelInitFilterDefault implements ProgrammingModelInitFi @Override public boolean acceptPostProcessor( - Class<? extends ObjectSpecificationPostProcessor> postProcessorType, + Class<? extends MetaModelPostProcessor> postProcessorType, ProgrammingModel.Marker[] markersIfAny) { return filterOnMarker.test(markersIfAny); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava11.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava11.java index 39eb78ed14..a2bbacdc4f 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava11.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava11.java @@ -84,7 +84,7 @@ import org.apache.causeway.core.metamodel.facets.value.semantics.ValueSemanticsA import org.apache.causeway.core.metamodel.methods.DomainIncludeAnnotationEnforcesMetamodelContributionValidator; import org.apache.causeway.core.metamodel.postprocessors.all.CssOnActionFromConfiguredRegexPostProcessor; import org.apache.causeway.core.metamodel.postprocessors.all.DescribedAsFromTypePostProcessor; -import org.apache.causeway.core.metamodel.postprocessors.all.SanityChecksPostProcessor; +import org.apache.causeway.core.metamodel.postprocessors.all.SanityChecksValidator; import org.apache.causeway.core.metamodel.postprocessors.all.i18n.SynthesizeObjectNamingPostProcessor; import org.apache.causeway.core.metamodel.postprocessors.all.i18n.TranslationPostProcessor; import org.apache.causeway.core.metamodel.postprocessors.allbutparam.authorization.AuthorizationPostProcessor; @@ -239,7 +239,6 @@ extends ProgrammingModelAbstract { private void addPostProcessors() { val mmc = getMetaModelContext(); - addPostProcessor(PostProcessingOrder.A1_BUILTIN, new SanityChecksPostProcessor(mmc)); // must run before Object nouns are used addPostProcessor(PostProcessingOrder.A1_BUILTIN, new SynthesizeObjectNamingPostProcessor(mmc)); @@ -265,6 +264,7 @@ extends ProgrammingModelAbstract { val mmc = getMetaModelContext(); + addValidator(new SanityChecksValidator(mmc)); addValidator(new DomainIncludeAnnotationEnforcesMetamodelContributionValidator(mmc)); addValidator(new TitlesAndTranslationsValidator(mmc)); // should this instead be a post processor, alongside TranslationPostProcessor ? addValidator(new ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator(mmc)); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitlesAndTranslationsValidator.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitlesAndTranslationsValidator.java index 1e2f0c0c0f..541646924e 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitlesAndTranslationsValidator.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/title/TitlesAndTranslationsValidator.java @@ -23,7 +23,6 @@ import javax.inject.Inject; import org.apache.causeway.applib.Identifier; import org.apache.causeway.applib.id.LogicalType; import org.apache.causeway.applib.services.i18n.TranslationContext; -import org.apache.causeway.applib.services.title.TitleService; import org.apache.causeway.commons.internal.base._Blackhole; import org.apache.causeway.core.config.messages.MessageRegistry; import org.apache.causeway.core.metamodel.context.MetaModelContext; @@ -46,7 +45,7 @@ extends MetaModelValidatorAbstract { } @Override - public void validate() { + public void validateEnter() { validateServiceTitles(); validateEnumTitles(); validateRegisteredMessageTranslation(); @@ -54,10 +53,9 @@ extends MetaModelValidatorAbstract { private void validateServiceTitles() { - val serviceRegistry = super.getMetaModelContext().getServiceRegistry(); - val specificationLoader = super.getMetaModelContext().getSpecificationLoader(); - val titleService = serviceRegistry.lookupServiceElseFail(TitleService.class); - + val serviceRegistry = getServiceRegistry(); + val specificationLoader = getSpecificationLoader(); + val titleService = getTitleService(); serviceRegistry.streamRegisteredBeans() .forEach(managedBeanAdapter->{ @@ -109,9 +107,8 @@ extends MetaModelValidatorAbstract { private void validateEnumTitles() { - val serviceRegistry = super.getMetaModelContext().getServiceRegistry(); - val specificationLoader = super.getMetaModelContext().getSpecificationLoader(); - val titleService = serviceRegistry.lookupServiceElseFail(TitleService.class); + val specificationLoader = getSpecificationLoader(); + val titleService = getTitleService(); // (previously we took a protective copy to avoid a concurrent modification exception, // but this is now done by SpecificationLoader itself) @@ -147,11 +144,8 @@ extends MetaModelValidatorAbstract { private void validateRegisteredMessageTranslation() { - val specificationLoader = super.getMetaModelContext().getSpecificationLoader(); - val translationService = super.getMetaModelContext().getTranslationService(); - - // as used by the Wicket UI? - // final TranslationContext context = "org.apache.causeway...InteractionService"; + val specificationLoader = getSpecificationLoader(); + val translationService = getTranslationService(); // see @ConfirmUiModel#translate() val translationContext = TranslationContext.forClassName(MessageRegistry.class); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java index e40e3c6fde..a7228357a4 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/SpecificationLoaderDefault.java @@ -80,7 +80,6 @@ import org.apache.causeway.core.metamodel.specloader.facetprocessor.FacetProcess import org.apache.causeway.core.metamodel.specloader.postprocessor.PostProcessor; import org.apache.causeway.core.metamodel.specloader.specimpl.IntrospectionState; import org.apache.causeway.core.metamodel.specloader.specimpl.dflt.ObjectSpecificationDefault; -import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidatorAbstract; import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure; import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailures; import org.apache.causeway.core.metamodel.valuetypes.ValueSemanticsResolverDefault; @@ -288,7 +287,7 @@ implements //XXX[CAUSEWAY-2382] when parallel introspecting, make sure we have the mixins before their holders // (observation by experiment, no real understanding as to why) - _Util.logBefore(log, cache, knownSpecs); + _LogUtil.logBefore(log, cache, knownSpecs); log.info(" - introspecting {} type hierarchies", knownSpecs.size()); introspect(Can.ofCollection(knownSpecs), IntrospectionState.TYPE_INTROSPECTED); @@ -312,7 +311,7 @@ implements introspect(Can.ofCollection(domainObjectSpecs), IntrospectionState.FULLY_INTROSPECTED); - _Util.logAfter(log, cache, knownSpecs); + _LogUtil.logAfter(log, cache, knownSpecs); if(isFullIntrospect()) { val snapshot = cache.snapshotSpecs(); @@ -370,7 +369,7 @@ implements log.debug("shutting down {}", this); disposeMetaModel(); facetProcessor.shutdown(); - postProcessor.shutdown(); + postProcessor.close(); facetProcessor = null; } @@ -511,29 +510,14 @@ implements } private _Lazy<ValidationFailures> validationResult = - _Lazy.threadSafe(this::collectFailuresFromMetaModel); + _Lazy.threadSafe(this::runMetaModelValidators); private final AtomicBoolean validationInProgress = new AtomicBoolean(false); private final BlockingQueue<ObjectSpecification> validationQueue = new LinkedBlockingQueue<>(); - private ValidationFailures collectFailuresFromMetaModel() { + private ValidationFailures runMetaModelValidators() { validationInProgress.set(true); - - programmingModel.streamValidators() - .map(MetaModelValidatorAbstract.class::cast) - .forEach(validator -> { - log.debug("Running validator: {}", validator); - try { - validator.validate(); - } catch (Throwable t) { - log.error(t); - throw t; - } finally { - log.debug("Done validator: {}", validator); - } - }); - - log.debug("Done"); + _ValidateUtil.runValidators(programmingModel, this); validationInProgress.set(false); return validationFailures; diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_Util.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_LogUtil.java similarity index 99% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_Util.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_LogUtil.java index df9f7fb8f1..642fe881cd 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_Util.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_LogUtil.java @@ -30,7 +30,7 @@ import lombok.val; import lombok.experimental.UtilityClass; @UtilityClass -final class _Util { +final class _LogUtil { void logBefore( final Logger log, diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_ValidateUtil.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_ValidateUtil.java new file mode 100644 index 0000000000..7a1c7c4a88 --- /dev/null +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/_ValidateUtil.java @@ -0,0 +1,88 @@ +/* + * 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.causeway.core.metamodel.specloader; + +import org.apache.causeway.commons.collections.Can; +import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel; +import org.apache.causeway.core.metamodel.spec.ObjectSpecification; +import org.apache.causeway.core.metamodel.spec.feature.MixedIn; +import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidator; + +import lombok.val; +import lombok.experimental.UtilityClass; +import lombok.extern.log4j.Log4j2; + +@UtilityClass +@Log4j2 +class _ValidateUtil{ + + void runValidators( + final ProgrammingModel programmingModel, + final SpecificationLoader specLoader) { + + log.debug("Running MetaModelValidators ..."); + + val snapshot = specLoader.snapshotSpecifications(); + + programmingModel.streamValidators() + .filter(MetaModelValidator::isEnabled) + .forEach(validator -> { + log.debug("Running validator: {}", validator); + try { + runValidator(validator, snapshot); + } catch (Throwable t) { + log.error(t); + throw t; + } finally { + log.debug("Done validator: {}", validator); + } + }); + + log.debug("Done running MetaModelValidators."); + } + + + // -- HELPER + + private void runValidator(final MetaModelValidator validator, final Can<ObjectSpecification> snapshot) { + validator.validateEnter(); + snapshot.forEach(objSpec->runValidator(validator, objSpec)); + validator.validateExit(); + } + + private void runValidator(final MetaModelValidator validator, final ObjectSpecification objSpec) { + validator.validateObjectEnter(objSpec); + + objSpec.streamRuntimeActions(MixedIn.INCLUDED) + .forEach(act->{ + act.streamParameters().forEach(param -> + validator.validateParameter(objSpec, act, param)); + validator.validateAction(objSpec, act); + }); + + objSpec.streamProperties(MixedIn.INCLUDED) + .forEach(prop->validator.validateProperty(objSpec, prop)); + + objSpec.streamCollections(MixedIn.INCLUDED) + .forEach(coll->validator.validateCollection(objSpec, coll)); + + validator.validateObjectExit(objSpec); + } + +} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/postprocessor/PostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/postprocessor/PostProcessor.java index c461b9ff4f..2c70cb7d36 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/postprocessor/PostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/postprocessor/PostProcessor.java @@ -19,84 +19,49 @@ package org.apache.causeway.core.metamodel.specloader.postprocessor; import org.apache.causeway.commons.collections.Can; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessor; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessor; import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.MixedIn; -import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; -import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation; -import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; import lombok.RequiredArgsConstructor; import lombok.val; @RequiredArgsConstructor -public class PostProcessor { +public class PostProcessor implements AutoCloseable { private final ProgrammingModel programmingModel; - private Can<ObjectSpecificationPostProcessor> enabledPostProcessors = Can.empty(); // populated at #init + private Can<MetaModelPostProcessor> enabledPostProcessors = Can.empty(); // populated at #init public void init() { enabledPostProcessors = programmingModel.streamPostProcessors() - .filter(ObjectSpecificationPostProcessor::isEnabled) + .filter(MetaModelPostProcessor::isEnabled) .collect(Can.toCan()); } - public void shutdown() { + @Override + public void close() { enabledPostProcessors = Can.empty(); } public void postProcess(final ObjectSpecification objectSpecification) { - // calling count on these 3 streams so these are actually consumed, - // as a side-effect the meta-model potentially gets further populated -// objectSpecification.streamRuntimeActions(MixedIn.INCLUDED).count(); -// objectSpecification.streamCollections(MixedIn.INCLUDED).count(); -// objectSpecification.streamProperties(MixedIn.INCLUDED).count(); - postProcessObject(objectSpecification); - - objectSpecification.streamRuntimeActions(MixedIn.INCLUDED) - .forEach(act->postProcessAction(objectSpecification, act)); - - objectSpecification.streamProperties(MixedIn.INCLUDED) - .forEach(prop->postProcessProperty(objectSpecification, prop)); - - objectSpecification.streamCollections(MixedIn.INCLUDED) - .forEach(coll->postProcessCollection(objectSpecification, coll)); - } - - // -- HELPER - - private void postProcessObject( - final ObjectSpecification objectSpecification) { for (val postProcessor : enabledPostProcessors) { postProcessor.postProcessObject(objectSpecification); - } - } - private void postProcessAction( - final ObjectSpecification objectSpecification, - final ObjectAction act) { - for (val postProcessor : enabledPostProcessors) { - act.streamParameters().forEach(param -> - postProcessor.postProcessParameter(objectSpecification, act, param)); - postProcessor.postProcessAction(objectSpecification, act); - } - } + objectSpecification.streamRuntimeActions(MixedIn.INCLUDED) + .forEach(act->{ + act.streamParameters().forEach(param -> + postProcessor.postProcessParameter(objectSpecification, act, param)); + postProcessor.postProcessAction(objectSpecification, act); + }); - private void postProcessProperty( - final ObjectSpecification objectSpecification, - final OneToOneAssociation prop) { - for (val postProcessor : enabledPostProcessors) { - postProcessor.postProcessProperty(objectSpecification, prop); - } - } + objectSpecification.streamProperties(MixedIn.INCLUDED) + .forEach(prop->postProcessor.postProcessProperty(objectSpecification, prop)); + + objectSpecification.streamCollections(MixedIn.INCLUDED) + .forEach(coll->postProcessor.postProcessCollection(objectSpecification, coll)); - private void postProcessCollection( - final ObjectSpecification objectSpecification, - final OneToManyAssociation coll) { - for (val postProcessor : enabledPostProcessors) { - postProcessor.postProcessCollection(objectSpecification, coll); } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelValidator.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelValidator.java index 2fd357115d..4f0047e3d6 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelValidator.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelValidator.java @@ -18,8 +18,40 @@ */ package org.apache.causeway.core.metamodel.specloader.validator; +import org.apache.causeway.core.metamodel.spec.ObjectSpecification; +import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; +import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter; +import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation; +import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; + public interface MetaModelValidator { - void validate(); + default boolean isEnabled() { + return true; + } + + /** entry to meta-model validation */ + default void validateEnter() {} + + /** exit from meta-model validation */ + default void validateExit() {} + + /** entry to validation of specified {@code objSpec} */ + default void validateObjectEnter(final ObjectSpecification objSpec) {} + + /** exit from validation of specified {@code objSpec} */ + default void validateObjectExit(final ObjectSpecification objSpec) {} + + /** validate action - mixed-in included */ + default void validateAction(final ObjectSpecification objSpec, final ObjectAction act) {} + + /** validate action-parameter - mixed-in included */ + default void validateParameter(final ObjectSpecification objSpec, final ObjectAction act, final ObjectActionParameter param) {} + + /** validate property - mixed-in included */ + default void validateProperty(final ObjectSpecification objSpec, final OneToOneAssociation prop) {} + + /** validate collection - mixed-in included */ + default void validateCollection(final ObjectSpecification objSpec, final OneToManyAssociation coll) {} } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelVisitingValidator.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelVisitingValidator.java index 92127059d2..99b10588f7 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelVisitingValidator.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelVisitingValidator.java @@ -31,8 +31,6 @@ public interface MetaModelVisitingValidator { void validate(@NonNull ObjectSpecification spec); - default void summarize() { - - } + default void summarize() {} } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelVisitingValidatorAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelVisitingValidatorAbstract.java deleted file mode 100644 index 41e4045202..0000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/validator/MetaModelVisitingValidatorAbstract.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.causeway.core.metamodel.specloader.validator; - -import org.apache.causeway.core.metamodel.context.MetaModelContext; - -public abstract class MetaModelVisitingValidatorAbstract -extends MetaModelValidatorAbstract -implements MetaModelVisitingValidator { - - protected MetaModelVisitingValidatorAbstract(final MetaModelContext metaModelContext) { - super(metaModelContext); - } - - @Override - public final void validate() { - - if(!isEnabled()){ - return; - } - - getMetaModelContext().getSpecificationLoader() - .forEach(this::validate); - - summarize(); - - } - -} diff --git a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationPostProcessor.java b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationPostProcessor.java index 6f4a383dad..114b979f93 100644 --- a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationPostProcessor.java +++ b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationPostProcessor.java @@ -37,7 +37,7 @@ import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facetapi.FacetUtil; import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner; -import org.apache.causeway.core.metamodel.postprocessors.ObjectSpecificationPostProcessorAbstract; +import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; @@ -50,7 +50,7 @@ import org.apache.causeway.extensions.secman.applib.user.dom.ApplicationUserRepo import lombok.val; public class TenantedAuthorizationPostProcessor -extends ObjectSpecificationPostProcessorAbstract { +extends MetaModelPostProcessorAbstract { @Component public static class Register implements MetaModelRefiner { diff --git a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/object/query/MetaModelVisitingValidatorForClauseAbstract.java b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/object/query/MetaModelVisitingValidatorForClauseAbstract.java index b595850dc8..f7308e6506 100644 --- a/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/object/query/MetaModelVisitingValidatorForClauseAbstract.java +++ b/persistence/jdo/metamodel/src/main/java/org/apache/causeway/persistence/jdo/metamodel/facets/object/query/MetaModelVisitingValidatorForClauseAbstract.java @@ -25,14 +25,14 @@ import org.apache.causeway.commons.internal.base._Strings; import org.apache.causeway.commons.internal.context._Context; import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; -import org.apache.causeway.core.metamodel.specloader.validator.MetaModelVisitingValidatorAbstract; +import org.apache.causeway.core.metamodel.specloader.validator.MetaModelValidatorAbstract; import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure; import org.apache.causeway.persistence.jdo.provider.metamodel.facets.object.query.JdoQueryFacet; import lombok.val; abstract class MetaModelVisitingValidatorForClauseAbstract -extends MetaModelVisitingValidatorAbstract { +extends MetaModelValidatorAbstract { final String clause; @@ -44,7 +44,7 @@ extends MetaModelVisitingValidatorAbstract { } @Override - public void validate(final ObjectSpecification objectSpec) { + public void validateObjectEnter(final ObjectSpecification objectSpec) { if(objectSpec.isInjectable()) { return; diff --git a/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingBadDomain.java b/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingBadDomain.java index 35fdf35293..3bb59a8e0c 100644 --- a/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingBadDomain.java +++ b/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingBadDomain.java @@ -363,6 +363,18 @@ class DomainModelTest_usingBadDomain { } + @Test + void memberIdClash() { + + //TODO[CAUSEWAY-3051] WIP + System.err.println("------------------------------------------------"); + + validator.streamFailures(id->id.getFullIdentityString().contains("InvalidMemberIdClash")) + .forEach(failure->System.err.printf("!!!%s%n", failure)); + + System.err.println("------------------------------------------------"); + } + // -- ELEMENT-TYPE @ParameterizedTest diff --git a/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/bad/Configuration_usingInvalidDomain.java b/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/bad/Configuration_usingInvalidDomain.java index 6eb232ba78..aaafe8dcae 100644 --- a/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/bad/Configuration_usingInvalidDomain.java +++ b/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/bad/Configuration_usingInvalidDomain.java @@ -25,6 +25,7 @@ import org.springframework.context.annotation.Import; @Configuration @Import({ InvalidDomainObjectOnInterface.class, // explicitly import interface + InvalidMemberIdClash.class, }) @ComponentScan( basePackageClasses= { diff --git a/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/bad/InvalidMemberIdClash.java b/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/bad/InvalidMemberIdClash.java new file mode 100644 index 0000000000..04b327636c --- /dev/null +++ b/regressiontests/stable/src/main/java/org/apache/causeway/testdomain/model/bad/InvalidMemberIdClash.java @@ -0,0 +1,208 @@ +/* + * 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.causeway.testdomain.model.bad; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import javax.inject.Named; + +import org.apache.causeway.applib.annotation.Action; +import org.apache.causeway.applib.annotation.ActionLayout; +import org.apache.causeway.applib.annotation.Collection; +import org.apache.causeway.applib.annotation.CollectionLayout; +import org.apache.causeway.applib.annotation.DomainObject; +import org.apache.causeway.applib.annotation.MemberSupport; +import org.apache.causeway.applib.annotation.Nature; +import org.apache.causeway.applib.annotation.Property; +import org.apache.causeway.applib.annotation.PropertyLayout; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Collisions between: + * <ul> + * <li>act<->act1,prop1,coll1</li> + * <li>prop<->act2,prop2,coll2</li> + * <li>coll<->act3,prop3,coll3</li> + * <li>act4<->prop4</li> + * <li>act5<->coll4</li> + * <li>prop5<->coll5</li> + * </ul> + */ +@DomainObject(nature = Nature.VIEW_MODEL) +@Named("testdomain.InvalidMemberIdClash") +public class InvalidMemberIdClash { + + // member-id clash (act) + @Action + public boolean someAction() { + return false; + } + + // member-id clash (prop) + @Property + @Getter + private int someProperty = 0; + + // member-id clash (coll) + @Collection + @Getter + private List<Integer> someCollection = Collections.emptyList(); + + // -- MIXINS + + @Action + @ActionLayout(named = "someAction") // member-id clash + @RequiredArgsConstructor + public static class ActionMixin1 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public String act() { return ""; } + } + + @Action + @ActionLayout(named = "someProperty") // member-id clash + @RequiredArgsConstructor + public static class ActionMixin2 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public String act() { return ""; } + } + + @Action + @ActionLayout(named = "someCollection") // member-id clash + @RequiredArgsConstructor + public static class ActionMixin3 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public String act() { return ""; } + } + + @Action + @ActionLayout(named = "mixinA") // member-id clash + @RequiredArgsConstructor + public static class ActionMixin4 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public String act() { return ""; } + } + + @Action + @ActionLayout(named = "mixinB") // member-id clash + @RequiredArgsConstructor + public static class ActionMixin5 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public String act() { return ""; } + } + + @Property + @PropertyLayout(named = "someAction") // member-id clash + @RequiredArgsConstructor + public static class PropertyMixin1 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public String prop() { return ""; } + } + + @Property + @PropertyLayout(named = "someProperty") // member-id clash + @RequiredArgsConstructor + public static class PropertyMixin2 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public String prop() { return ""; } + } + + @Property + @PropertyLayout(named = "someCollection") // member-id clash + @RequiredArgsConstructor + public static class PropertyMixin3 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public String prop() { return ""; } + } + + @Property + @PropertyLayout(named = "mixinA") // member-id clash + @RequiredArgsConstructor + public static class PropertyMixin4 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public String prop() { return ""; } + } + + @Property + @PropertyLayout(named = "mixinC") // member-id clash + @RequiredArgsConstructor + public static class PropertyMixin5 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public String prop() { return ""; } + } + + @Collection + @CollectionLayout(named = "someAction") // member-id clash + @RequiredArgsConstructor + public static class CollectionMixin1 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public Set<String> coll() { return null; } + } + + @Collection + @CollectionLayout(named = "someProperty") // member-id clash + @RequiredArgsConstructor + public static class CollectionMixin2 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public Set<String> coll() { return null; } + } + + @Collection + @CollectionLayout(named = "someCollection") // member-id clash + @RequiredArgsConstructor + public static class CollectionMixin3 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public Set<String> coll() { return null; } + } + + @Collection + @CollectionLayout(named = "mixinB") // member-id clash + @RequiredArgsConstructor + public static class CollectionMixin4 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public Set<String> coll() { return null; } + } + + @Collection + @CollectionLayout(named = "mixinC") // member-id clash + @RequiredArgsConstructor + public static class CollectionMixin5 { + @SuppressWarnings("unused") + private final InvalidMemberIdClash memberIdClash; + @MemberSupport public Set<String> coll() { return null; } + } + +}
