ISIS-1027: refactoring the metamodel validation for detecting duplicates ObjectSpecIdFacet.
Previously this was performed by the ObjectReflectorDefafult, called by the default "not quite no-op" MetaModelValidatorDefault". Have now moved to DomainObjectAnnotationFacetFactory, and removed the API from ObjectReflector. In addition, updated isis.properties comments for simpleapp and todoapp. Project: http://git-wip-us.apache.org/repos/asf/isis/repo Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/e4040123 Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/e4040123 Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/e4040123 Branch: refs/heads/master Commit: e4040123ecb84d35f94f960278c1c5e7026a4c00 Parents: 255ec22 Author: Dan Haywood <[email protected]> Authored: Fri Feb 6 13:06:42 2015 +0000 Committer: Dan Haywood <[email protected]> Committed: Fri Feb 6 13:06:42 2015 +0000 ---------------------------------------------------------------------- .../DomainObjectAnnotationFacetFactory.java | 41 +++++++++++++++++++- .../dflt/MetaModelValidatorDefault.java | 6 +-- .../metamodel/spec/SpecificationLoaderSpi.java | 6 --- .../specloader/ObjectReflectorDefault.java | 15 ------- .../specloader/ReflectorConstants.java | 6 ++- .../metamodel/facets/ProgrammableReflector.java | 6 --- .../src/main/webapp/WEB-INF/isis.properties | 31 ++++++++------- .../dom/src/main/java/app/ToDoAppDashboard.java | 34 ++++++++-------- .../main/java/app/ToDoAppDashboardService.java | 20 ++++++++-- .../src/main/webapp/WEB-INF/isis.properties | 26 ++++++++----- 10 files changed, 111 insertions(+), 80 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/isis/blob/e4040123/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java index 347de04..a5e3e96 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java @@ -19,6 +19,9 @@ package org.apache.isis.core.metamodel.facets.object.domainobject; +import java.util.Collection; +import java.util.Map; +import com.google.common.collect.Maps; import org.apache.isis.applib.annotation.Audited; import org.apache.isis.applib.annotation.AutoComplete; import org.apache.isis.applib.annotation.Bounded; @@ -49,19 +52,23 @@ import org.apache.isis.core.metamodel.facets.object.domainobject.choices.Choices import org.apache.isis.core.metamodel.facets.object.domainobject.choices.ChoicesFacetFromBoundedAnnotation; import org.apache.isis.core.metamodel.facets.object.domainobject.editing.ImmutableFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.domainobject.objectspecid.ObjectSpecIdFacetForDomainObjectAnnotation; +import org.apache.isis.core.metamodel.facets.object.domainobject.objectspecid.ObjectSpecIdFacetFromObjectTypeAnnotation; import org.apache.isis.core.metamodel.facets.object.domainobject.publishing.PublishedObjectFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.domainobject.publishing.PublishedObjectFacetForPublishedObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.domainobject.recreatable.RecreatableObjectFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.immutable.ImmutableFacet; import org.apache.isis.core.metamodel.facets.object.immutable.immutableannot.ImmutableFacetForImmutableAnnotation; -import org.apache.isis.core.metamodel.facets.object.domainobject.objectspecid.ObjectSpecIdFacetFromObjectTypeAnnotation; import org.apache.isis.core.metamodel.facets.object.publishedobject.PublishedObjectFacet; import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet; import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector; import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware; +import org.apache.isis.core.metamodel.spec.ObjectSpecId; +import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.metamodel.spec.SpecificationLoaderAware; import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite; import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorForDeprecatedAnnotation; +import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting; +import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures; public class DomainObjectAnnotationFacetFactory extends FacetFactoryAbstract implements IsisConfigurationAware, AdapterManagerAware, ServicesInjectorAware, SpecificationLoaderAware, QuerySubmitterAware, MetaModelValidatorRefiner { @@ -252,6 +259,38 @@ public class DomainObjectAnnotationFacetFactory extends FacetFactoryAbstract imp @Override public void refineMetaModelValidator(final MetaModelValidatorComposite metaModelValidator, final IsisConfiguration configuration) { + + metaModelValidator.add(new MetaModelValidatorVisiting(new MetaModelValidatorVisiting.Visitor() { + @Override + public boolean visit(final ObjectSpecification thisSpec, final ValidationFailures validationFailures) { + + final Map<ObjectSpecId, ObjectSpecification> specById = Maps.newHashMap(); + final Collection<ObjectSpecification> allSpecifications = getSpecificationLoader().allSpecifications(); + for (final ObjectSpecification otherSpec : allSpecifications) { + + if(thisSpec == otherSpec) { + continue; + } + final ObjectSpecId objectSpecId = otherSpec.getSpecId(); + if (objectSpecId == null) { + continue; + } + final ObjectSpecification existingSpec = specById.put(objectSpecId, otherSpec); + if (existingSpec == null) { + continue; + } + validationFailures.add( + "Cannot have two entities with same object type (@DomainObject(objectType=...) or @ObjectType); " + + "both %s and %s are annotated with value of ''%s''.", + existingSpec.getFullIdentifier(), + otherSpec.getFullIdentifier(), + objectSpecId); + } + + return true; + } + })); + metaModelValidator.add(publishedObjectValidator); metaModelValidator.add(auditedValidator); metaModelValidator.add(autoCompleteValidator); http://git-wip-us.apache.org/repos/asf/isis/blob/e4040123/core/metamodel/src/main/java/org/apache/isis/core/metamodel/metamodelvalidator/dflt/MetaModelValidatorDefault.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/metamodelvalidator/dflt/MetaModelValidatorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/metamodelvalidator/dflt/MetaModelValidatorDefault.java index 80d9387..9682a65 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/metamodelvalidator/dflt/MetaModelValidatorDefault.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/metamodelvalidator/dflt/MetaModelValidatorDefault.java @@ -26,14 +26,10 @@ public class MetaModelValidatorDefault extends MetaModelValidatorAbstract { /** * Does nothing. + * @param validationFailures */ @Override public void validate(ValidationFailures validationFailures) { - validateSpecifications(validationFailures); - } - - private void validateSpecifications(ValidationFailures validationFailures) { - getSpecificationLoaderSpi().validateSpecifications(validationFailures); } } http://git-wip-us.apache.org/repos/asf/isis/blob/e4040123/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java index 049fee3..0b53830 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/SpecificationLoaderSpi.java @@ -32,12 +32,6 @@ public interface SpecificationLoaderSpi extends ApplicationScopedComponent, Debu */ void setServiceInjector(ServicesInjectorSpi services); - /** - * Populated as a result of running metamodel validation after all specs have been loaded. - * @param validationFailures - */ - void validateSpecifications(ValidationFailures validationFailures); - void invalidateCacheFor(Object domainObject); void invalidateCache(Class<?> domainClass); http://git-wip-us.apache.org/repos/asf/isis/blob/e4040123/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java index 36b3ed8..ce25255 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java @@ -644,21 +644,6 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App return metaModelValidator; } - @Override - public void validateSpecifications(ValidationFailures validationFailures) { - final Map<ObjectSpecId, ObjectSpecification> specById = Maps.newHashMap(); - for (final ObjectSpecification objSpec : allSpecifications()) { - final ObjectSpecId objectSpecId = objSpec.getSpecId(); - if (objectSpecId == null) { - continue; - } - final ObjectSpecification existingSpec = specById.put(objectSpecId, objSpec); - if (existingSpec == null) { - continue; - } - validationFailures.add("Cannot have two entities with same object type (@ObjectType facet or equivalent) Value; " + "both %s and %s are annotated with value of ''%s''.", existingSpec.getFullIdentifier(), objSpec.getFullIdentifier(), objectSpecId); - } - } http://git-wip-us.apache.org/repos/asf/isis/blob/e4040123/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ReflectorConstants.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ReflectorConstants.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ReflectorConstants.java index 45ff59c..c603ba0 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ReflectorConstants.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ReflectorConstants.java @@ -24,8 +24,10 @@ import org.apache.isis.core.commons.config.IsisConfiguration; import org.apache.isis.core.metamodel.facetdecorator.FacetDecorator; import org.apache.isis.core.metamodel.facets.FacetFactory; import org.apache.isis.core.metamodel.layoutmetadata.json.LayoutMetadataReaderFromJson; +import org.apache.isis.core.metamodel.metamodelvalidator.dflt.MetaModelValidatorDefault; import org.apache.isis.core.metamodel.progmodel.ProgrammingModel; import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator; +import org.apache.isis.progmodels.dflt.ProgrammingModelFacetsJava5; public final class ReflectorConstants { @@ -37,14 +39,14 @@ public final class ReflectorConstants { * @see #FACET_FACTORY_EXCLUDE_CLASS_NAME_LIST */ public static final String PROGRAMMING_MODEL_FACETS_CLASS_NAME = ConfigurationConstants.ROOT + "reflector.facets"; - public static final String PROGRAMMING_MODEL_FACETS_CLASS_NAME_DEFAULT = "org.apache.isis.progmodels.dflt.ProgrammingModelFacetsJava5"; + public static final String PROGRAMMING_MODEL_FACETS_CLASS_NAME_DEFAULT = ProgrammingModelFacetsJava5.class.getName(); /** * Key used to lookup implementation of {@link MetaModelValidator} in * {@link IsisConfiguration}. */ public static final String META_MODEL_VALIDATOR_CLASS_NAME = ConfigurationConstants.ROOT + "reflector.validator"; - public static final String META_MODEL_VALIDATOR_CLASS_NAME_DEFAULT = "org.apache.isis.core.metamodel.metamodelvalidator.dflt.MetaModelValidatorDefault"; + public static final String META_MODEL_VALIDATOR_CLASS_NAME_DEFAULT = MetaModelValidatorDefault.class.getName(); /** http://git-wip-us.apache.org/repos/asf/isis/blob/e4040123/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java index 7529a44..39fd850 100644 --- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java +++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/ProgrammableReflector.java @@ -34,7 +34,6 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecId; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.metamodel.spec.SpecificationLoaderAbstract; import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi; -import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures; public class ProgrammableReflector extends SpecificationLoaderAbstract implements SpecificationLoaderSpi, ApplicationScopedComponent, RuntimeContextAware { @@ -127,11 +126,6 @@ public class ProgrammableReflector extends SpecificationLoaderAbstract implement } @Override - public void validateSpecifications(ValidationFailures validationFailures) { - throw new NotYetImplementedException(); - } - - @Override public ObjectSpecification introspectIfRequired(ObjectSpecification spec) { throw new NotYetImplementedException(); } http://git-wip-us.apache.org/repos/asf/isis/blob/e4040123/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/isis.properties ---------------------------------------------------------------------- diff --git a/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/isis.properties b/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/isis.properties index 822709b..9a57b37 100644 --- a/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/isis.properties +++ b/example/application/simpleapp/webapp/src/main/webapp/WEB-INF/isis.properties @@ -76,38 +76,40 @@ isis.authorization=shiro # -# additional programming model facets +# Additional programming model facet factories, or remove standard facet factories. +# Comma separated list of fully qualified class names. # - #isis.reflector.facets.include= #isis.reflector.facets.exclude= # -# metamodel validator +# Metamodel validation (in addition to that automatically performed by the programming model facet factories) +# Default implementation does nothing. # - -#isis.reflector.validator= +# Use a custom implementation to enforce additional constraints specific to your app/project/company. +# +#isis.reflector.validator=org.apache.isis.core.metamodel.metamodelvalidator.dflt.MetaModelValidatorDefault # -# Whether deprecated annotations or method prefixes should raise metamodel validation errors. Default is false. +# Whether to allow deprecated annotations/method prefixes (otherwise raise metamodel validation errors). +# If not specified, default is to allow. # -#isis.reflector.validator.allowDeprecated=false +isis.reflector.validator.allowDeprecated=false # -# layoutMetadataReader(s) +# Implementation to use for reading dynamic layout. Default implementation reads Xxx.layout.json files from classpath. # - -# isis.reflector.layoutMetadataReaders=org.apache.isis.core.metamodel.layoutmetadata.json.LayoutMetadataReaderFromJson +#isis.reflector.layoutMetadataReaders=org.apache.isis.core.metamodel.layoutmetadata.json.LayoutMetadataReaderFromJson # -# patterns for applying CssClassFa facet (font-awesome icons) to member names +# patterns for applying CssClassFa facet (font-awesome icons), matching on action names # isis.reflector.facet.cssClassFa.patterns=\ new.*:fa-plus,\ @@ -135,11 +137,12 @@ isis.reflector.facet.cssClassFa.patterns=\ install.*:fa-wrench +# +# patterns for applying CssClass facet (CSS styles), matching on member names +# isis.reflector.facet.cssClass.patterns=\ - update.*:btn-default,\ delete.*:btn-warning,\ - .*:btn-primary - + .*:btn-default ################################################################################# http://git-wip-us.apache.org/repos/asf/isis/blob/e4040123/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboard.java ---------------------------------------------------------------------- diff --git a/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboard.java b/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboard.java index 4844d12..65311cf 100644 --- a/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboard.java +++ b/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboard.java @@ -19,13 +19,15 @@ package app; import java.util.List; -import org.apache.isis.applib.AbstractViewModel; import org.apache.isis.applib.annotation.Collection; import org.apache.isis.applib.annotation.CollectionLayout; +import org.apache.isis.applib.annotation.DomainObject; import org.apache.isis.applib.annotation.Editing; +import org.apache.isis.applib.annotation.Nature; import org.apache.isis.applib.annotation.RenderType; -public class ToDoAppDashboard extends AbstractViewModel { +@DomainObject(nature = Nature.VIEW_MODEL) +public class ToDoAppDashboard { //region > identification in the UI public String title() { @@ -33,20 +35,19 @@ public class ToDoAppDashboard extends AbstractViewModel { } //endregion - //region > ViewModel contract - private String memento; - - @Override - public String viewModelMemento() { - return memento; - } - - @Override - public void viewModelInit(final String memento) { - this.memento = memento; - } - - //endregion +// //region > memento (property) +// private String memento = "Dashboard"; +// +// @Property(hidden = Where.EVERYWHERE) +// @MemberOrder(sequence = "1") +// public String getMemento() { +// return memento; +// } +// +// public void setMemento(final String memento) { +// this.memento = memento; +// } +// //endregion //region > getAnalysisByCategory (collection) @CollectionLayout( @@ -77,7 +78,6 @@ public class ToDoAppDashboard extends AbstractViewModel { //region > injected services @javax.inject.Inject private ToDoItemAnalysis toDoItemAnalysis; - //endregion } http://git-wip-us.apache.org/repos/asf/isis/blob/e4040123/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboardService.java ---------------------------------------------------------------------- diff --git a/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboardService.java b/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboardService.java index c60f255..3bc371c 100644 --- a/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboardService.java +++ b/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboardService.java @@ -18,15 +18,27 @@ */ package app; +import javax.inject.Inject; +import org.apache.isis.applib.DomainObjectContainer; +import org.apache.isis.applib.annotation.Action; import org.apache.isis.applib.annotation.DomainService; +import org.apache.isis.applib.annotation.HomePage; import org.apache.isis.applib.annotation.NatureOfService; -import org.apache.isis.applib.services.homepage.AbstractHomePageDashboardService; +import org.apache.isis.applib.annotation.SemanticsOf; @DomainService(nature = NatureOfService.DOMAIN) -public class ToDoAppDashboardService extends AbstractHomePageDashboardService<ToDoAppDashboard> { +public class ToDoAppDashboardService { - public ToDoAppDashboardService() { - super(ToDoAppDashboard.class); + @Action( + semantics = SemanticsOf.SAFE + //hidden = Where.EVERYWHERE + ) + @HomePage + public ToDoAppDashboard lookup() { + return container.injectServicesInto(new ToDoAppDashboard()); } + @Inject + private DomainObjectContainer container; + } http://git-wip-us.apache.org/repos/asf/isis/blob/e4040123/example/application/todoapp/webapp/src/main/webapp/WEB-INF/isis.properties ---------------------------------------------------------------------- diff --git a/example/application/todoapp/webapp/src/main/webapp/WEB-INF/isis.properties b/example/application/todoapp/webapp/src/main/webapp/WEB-INF/isis.properties index ec5195a..3bfaeed 100644 --- a/example/application/todoapp/webapp/src/main/webapp/WEB-INF/isis.properties +++ b/example/application/todoapp/webapp/src/main/webapp/WEB-INF/isis.properties @@ -76,38 +76,40 @@ isis.authorization=shiro # -# additional programming model facets +# Additional programming model facet factories, or remove standard facet factories. +# Comma separated list of fully qualified class names. # - #isis.reflector.facets.include= #isis.reflector.facets.exclude= # -# metamodel validator +# Metamodel validation (in addition to that automatically performed by the programming model facet factories) +# Default implementation does nothing. # - -#isis.reflector.validator= +# Use a custom implementation to enforce additional constraints specific to your app/project/company. +# +#isis.reflector.validator=org.apache.isis.core.metamodel.metamodelvalidator.dflt.MetaModelValidatorDefault # -# Whether deprecated annotations or method prefixes should raise metamodel validation errors. Default is false. +# Whether to allow deprecated annotations/method prefixes (otherwise raise metamodel validation errors). +# If not specified, default is to allow. # isis.reflector.validator.allowDeprecated=false # -# layoutMetadataReader(s) +# Implementation to use for reading dynamic layout. Default implementation reads Xxx.layout.json files from classpath. # - -# isis.reflector.layoutMetadataReaders=org.apache.isis.core.metamodel.layoutmetadata.json.LayoutMetadataReaderFromJson +#isis.reflector.layoutMetadataReaders=org.apache.isis.core.metamodel.layoutmetadata.json.LayoutMetadataReaderFromJson # -# patterns for applying CssClassFa facet (font-awesome icons) to member names +# patterns for applying CssClassFa facet (font-awesome icons), matching on action names # isis.reflector.facet.cssClassFa.patterns=\ new.*:fa-plus,\ @@ -134,6 +136,10 @@ isis.reflector.facet.cssClassFa.patterns=\ refresh.*:fa-refresh, \ install.*:fa-wrench + +# +# patterns for applying CssClass facet (CSS styles), matching on member names +# isis.reflector.facet.cssClass.patterns=\ delete.*:btn-warning,\ .*:btn-default
