/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.isis.core.metamodel.facets.object.domainobject; import java.lang.reflect.Method; import java.util.Collection; import java.util.Map; import javax.annotation.PostConstruct; 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; import org.apache.isis.applib.annotation.DomainObject; import org.apache.isis.applib.annotation.Immutable; import org.apache.isis.applib.annotation.Nature; import org.apache.isis.applib.annotation.ObjectType; import org.apache.isis.applib.annotation.PublishedObject; import org.apache.isis.applib.services.HasTransactionId; import org.apache.isis.applib.services.eventbus.ObjectCreatedEvent; import org.apache.isis.applib.services.eventbus.ObjectLoadedEvent; import org.apache.isis.applib.services.eventbus.ObjectPersistedEvent; import org.apache.isis.applib.services.eventbus.ObjectPersistingEvent; import org.apache.isis.applib.services.eventbus.ObjectRemovingEvent; import org.apache.isis.applib.services.eventbus.ObjectUpdatedEvent; import org.apache.isis.applib.services.eventbus.ObjectUpdatingEvent; import org.apache.isis.core.commons.config.IsisConfiguration; import org.apache.isis.core.commons.lang.Nullable; import org.apache.isis.core.metamodel.facetapi.Facet; import org.apache.isis.core.metamodel.facetapi.FacetHolder; import org.apache.isis.core.metamodel.facetapi.FacetUtil; import org.apache.isis.core.metamodel.facetapi.FeatureType; import org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner; import org.apache.isis.core.metamodel.facets.Annotations; import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract; import org.apache.isis.core.metamodel.facets.MethodFinderUtils; import org.apache.isis.core.metamodel.facets.PostConstructMethodCache; import org.apache.isis.core.metamodel.facets.object.audit.AuditableFacet; import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedLifecycleEventFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.callbacks.LoadedLifecycleEventFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.callbacks.PersistedLifecycleEventFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.callbacks.PersistingLifecycleEventFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.callbacks.RemovingLifecycleEventFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatedLifecycleEventFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingLifecycleEventFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.domainobject.auditing.AuditableFacetForAuditedAnnotation; import org.apache.isis.core.metamodel.facets.object.domainobject.auditing.AuditableFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.domainobject.autocomplete.AutoCompleteFacetForAutoCompleteAnnotation; import org.apache.isis.core.metamodel.facets.object.domainobject.autocomplete.AutoCompleteFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.domainobject.choices.ChoicesFacetForDomainObjectAnnotation; 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.ObjectSpecIdFacetForJdoPersistenceCapableAnnotation; 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.mixin.MetaModelValidatorForMixinTypes; import org.apache.isis.core.metamodel.facets.object.mixin.MixinFacet; import org.apache.isis.core.metamodel.facets.object.mixin.MixinFacetForDomainObjectAnnotation; 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.services.ServicesInjector; import org.apache.isis.core.metamodel.services.persistsession.PersistenceSessionServiceInternal; import org.apache.isis.core.metamodel.spec.ObjectSpecId; import org.apache.isis.core.metamodel.spec.ObjectSpecification; 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.MetaModelValidatorForValidationFailures; import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting; import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures; import org.apache.isis.core.metamodel.util.EventUtil; import org.apache.isis.objectstore.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet; public class DomainObjectAnnotationFacetFactory extends FacetFactoryAbstract implements MetaModelValidatorRefiner, PostConstructMethodCache { private final MetaModelValidatorForDeprecatedAnnotation auditedValidator = new MetaModelValidatorForDeprecatedAnnotation(Audited.class); private final MetaModelValidatorForDeprecatedAnnotation publishedObjectValidator = new MetaModelValidatorForDeprecatedAnnotation(PublishedObject.class); private final MetaModelValidatorForDeprecatedAnnotation autoCompleteValidator = new MetaModelValidatorForDeprecatedAnnotation(AutoComplete.class); private final MetaModelValidatorForDeprecatedAnnotation boundedValidator = new MetaModelValidatorForDeprecatedAnnotation(Bounded.class); private final MetaModelValidatorForDeprecatedAnnotation immutableValidator = new MetaModelValidatorForDeprecatedAnnotation(Immutable.class); private final MetaModelValidatorForDeprecatedAnnotation objectTypeValidator = new MetaModelValidatorForDeprecatedAnnotation(ObjectType.class); private final MetaModelValidatorForValidationFailures autoCompleteInvalid = new MetaModelValidatorForValidationFailures(); private final MetaModelValidatorForMixinTypes mixinTypeValidator = new MetaModelValidatorForMixinTypes("@DomainObject#nature=MIXIN"); public DomainObjectAnnotationFacetFactory() { super(FeatureType.OBJECTS_ONLY); } @Override public void process(final ProcessClassContext processClassContext) { processAuditing(processClassContext); processPublishing(processClassContext); processAutoComplete(processClassContext); processBounded(processClassContext); processEditing(processClassContext); processObjectType(processClassContext); processNature(processClassContext); processLifecycleEvents(processClassContext); } void processAuditing(final ProcessClassContext processClassContext) { final Class<?> cls = processClassContext.getCls(); final DomainObject domainObject = Annotations.getAnnotation(cls, DomainObject.class); final FacetHolder holder = processClassContext.getFacetHolder(); // // this rule originally implemented only in AuditableFacetFromConfigurationFactory // but think should apply in general // if(HasTransactionId.class.isAssignableFrom(cls)) { // do not install on any implementation of HasTransactionId // (ie commands, audit entries, published events). return; } AuditableFacet auditableFacet; // check for the deprecated annotation first final Audited annotation = Annotations.getAnnotation(cls, Audited.class); auditableFacet = auditedValidator.flagIfPresent( AuditableFacetForAuditedAnnotation.create(annotation, holder), null); // else check for @DomainObject(auditing=....) if(auditableFacet == null) { auditableFacet = AuditableFacetForDomainObjectAnnotation.create(domainObject, getConfiguration(), holder); } // then add FacetUtil.addFacet(auditableFacet); } void processPublishing(final ProcessClassContext processClassContext) { final Class<?> cls = processClassContext.getCls(); final DomainObject domainObject = Annotations.getAnnotation(cls, DomainObject.class); final FacetHolder facetHolder = processClassContext.getFacetHolder(); // // this rule inspired by a similar rule for auditing, see above // if(HasTransactionId.class.isAssignableFrom(cls)) { // do not install on any implementation of HasTransactionId // (ie commands, audit entries, published events). return; } PublishedObjectFacet publishedObjectFacet; // check for the deprecated @PublishedObject annotation first final PublishedObject publishedObject = Annotations.getAnnotation(processClassContext.getCls(), PublishedObject.class); publishedObjectFacet = publishedObjectValidator.flagIfPresent( PublishedObjectFacetForPublishedObjectAnnotation.create(publishedObject, facetHolder)); // else check from @DomainObject(publishing=...) if(publishedObjectFacet == null) { publishedObjectFacet= PublishedObjectFacetForDomainObjectAnnotation.create(domainObject, getConfiguration(), facetHolder); } // then add FacetUtil.addFacet(publishedObjectFacet); } void processAutoComplete(final ProcessClassContext processClassContext) { final Class<?> cls = processClassContext.getCls(); final FacetHolder facetHolder = processClassContext.getFacetHolder(); // check for the deprecated @AutoComplete annotation first final AutoComplete autoCompleteAnnot = Annotations.getAnnotation(cls, AutoComplete.class); Facet facet = autoCompleteValidator.flagIfPresent(createFor(facetHolder, autoCompleteAnnot, cls)); // else check from @DomainObject(auditing=...) if(facet == null) { final DomainObject domainObjectAnnot = Annotations.getAnnotation(cls, DomainObject.class); facet = createFor(domainObjectAnnot, facetHolder, cls); } // then add FacetUtil.addFacet(facet); } private AutoCompleteFacet createFor( final FacetHolder facetHolder, final AutoComplete annotation, final Class<?> cls) { if(annotation == null) { return null; } final Class<?> repositoryClass = annotation.repository(); final String actionName = annotation.action(); if(!isServiceType(cls, "@AutoComplete", repositoryClass)) { return null; } final Method repositoryMethod = findRepositoryMethod(cls, "@AutoComplete", repositoryClass, actionName); if(repositoryMethod == null) { return null; } return new AutoCompleteFacetForAutoCompleteAnnotation( facetHolder, repositoryClass, repositoryMethod, servicesInjector); } private AutoCompleteFacet createFor( final DomainObject domainObject, final FacetHolder facetHolder, final Class<?> cls) { if(domainObject == null) { return null; } final Class<?> repositoryClass = domainObject.autoCompleteRepository(); if(repositoryClass == Object.class) { return null; } final String actionName = domainObject.autoCompleteAction(); if(!isServiceType(cls, "@DomainObject", repositoryClass)) { return null; } final Method repositoryMethod = findRepositoryMethod(cls, "@DomainObject", repositoryClass, actionName); if(repositoryMethod == null) { return null; } return new AutoCompleteFacetForDomainObjectAnnotation( facetHolder, repositoryClass, repositoryMethod, servicesInjector); } private boolean isServiceType( final Class<?> cls, final String annotationName, final Class<?> repositoryClass) { final boolean isRegistered = servicesInjector.isRegisteredService(repositoryClass); if(!isRegistered) { autoCompleteInvalid.addFailure( "%s annotation on %s specifies unknown repository '%s'", annotationName, cls.getName(), repositoryClass.getName()); } return isRegistered; } private Method findRepositoryMethod( final Class<?> cls, final String annotationName, final Class<?> repositoryClass, final String methodName) { final Method[] methods = repositoryClass.getMethods(); for (Method method : methods) { if(method.getName().equals(methodName)) { final Class<?>[] parameterTypes = method.getParameterTypes(); if(parameterTypes.length == 1 && parameterTypes[0].equals(String.class)) { return method; } } } autoCompleteInvalid.addFailure( "%s annotation on %s specifies method '%s' that does not exist in repository '%s'", annotationName, cls.getName(), methodName, repositoryClass.getName()); return null; } void processBounded(final ProcessClassContext processClassContext) { final Class<?> cls = processClassContext.getCls(); final DomainObject domainObject = Annotations.getAnnotation(cls, DomainObject.class); final FacetHolder facetHolder = processClassContext.getFacetHolder(); // check for the deprecated @Bounded annotation first final Bounded annotation = Annotations.getAnnotation(processClassContext.getCls(), Bounded.class); Facet facet = boundedValidator.flagIfPresent( ChoicesFacetFromBoundedAnnotation.create(annotation, processClassContext.getFacetHolder(), getDeploymentCategory(), getAuthenticationSessionProvider(), persistenceSessionServiceInternal)); // else check from @DomainObject(bounded=...) if(facet == null) { facet = ChoicesFacetForDomainObjectAnnotation.create(domainObject, facetHolder, getDeploymentCategory(), getAuthenticationSessionProvider(), persistenceSessionServiceInternal); } // then add FacetUtil.addFacet(facet); } void processEditing(final ProcessClassContext processClassContext) { final Class<?> cls = processClassContext.getCls(); final DomainObject domainObject = Annotations.getAnnotation(cls, DomainObject.class); final FacetHolder facetHolder = processClassContext.getFacetHolder(); // check for the deprecated annotation first final Immutable annotation = Annotations.getAnnotation(processClassContext.getCls(), Immutable.class); ImmutableFacet facet = immutableValidator.flagIfPresent( ImmutableFacetForImmutableAnnotation.create(annotation, processClassContext.getFacetHolder())); // else check from @DomainObject(editing=...) if(facet == null) { facet = ImmutableFacetForDomainObjectAnnotation.create(domainObject, getConfiguration(), facetHolder); } // then add FacetUtil.addFacet(facet); } void processObjectType(final ProcessClassContext processClassContext) { final Class<?> cls = processClassContext.getCls(); final DomainObject domainObject = Annotations.getAnnotation(cls, DomainObject.class); final FacetHolder facetHolder = processClassContext.getFacetHolder(); // check for the deprecated annotation first final ObjectType annotation = Annotations.getAnnotation(processClassContext.getCls(), ObjectType.class); Facet facet = objectTypeValidator.flagIfPresent( ObjectSpecIdFacetFromObjectTypeAnnotation.create(annotation, processClassContext.getFacetHolder())); // else check from @DomainObject(objectType=...) if(facet == null) { facet = ObjectSpecIdFacetForDomainObjectAnnotation.create(domainObject, facetHolder); } // else check for @PersistenceCapable(schema=...) if(facet == null) { final JdoPersistenceCapableFacet jdoPersistenceCapableFacet = facetHolder.getFacet(JdoPersistenceCapableFacet.class); if(jdoPersistenceCapableFacet != null) { facet = ObjectSpecIdFacetForJdoPersistenceCapableAnnotation.create(jdoPersistenceCapableFacet, facetHolder); } } // then add FacetUtil.addFacet(facet); } void processNature(final ProcessClassContext processClassContext) { final Class<?> cls = processClassContext.getCls(); final DomainObject domainObject = Annotations.getAnnotation(cls, DomainObject.class); if(domainObject == null) { return; } final FacetHolder facetHolder = processClassContext.getFacetHolder(); final PostConstructMethodCache postConstructMethodCache = this; final ViewModelFacet recreatableObjectFacet = RecreatableObjectFacetForDomainObjectAnnotation.create( domainObject, getSpecificationLoader(), persistenceSessionServiceInternal, servicesInjector, facetHolder, postConstructMethodCache); if(recreatableObjectFacet != null) { FacetUtil.addFacet(recreatableObjectFacet); } else { if(domainObject.nature() == Nature.MIXIN) { if(!mixinTypeValidator.ensureMixinType(cls)) { return; } final MixinFacet mixinFacet = MixinFacetForDomainObjectAnnotation.create(domainObject, cls, facetHolder, servicesInjector); FacetUtil.addFacet(mixinFacet); } } } private void processLifecycleEvents(final ProcessClassContext processClassContext) { final Class<?> cls = processClassContext.getCls(); final DomainObject domainObject = Annotations.getAnnotation(cls, DomainObject.class); if(domainObject == null) { return; } final FacetHolder holder = processClassContext.getFacetHolder(); processLifecycleEventCreated(domainObject, holder); processLifecycleEventLoaded(domainObject, holder); processLifecycleEventPersisted(domainObject, holder); processLifecycleEventPersisting(domainObject, holder); processLifecycleEventRemoving(domainObject, holder); processLifecycleEventUpdated(domainObject, holder); processLifecycleEventUpdating(domainObject, holder); } private void processLifecycleEventCreated(final DomainObject domainObject, final FacetHolder holder) { final Class<? extends ObjectCreatedEvent<?>> lifecycleEvent = domainObject.createdLifecycleEvent(); final CreatedLifecycleEventFacetForDomainObjectAnnotation facet = new CreatedLifecycleEventFacetForDomainObjectAnnotation( holder, lifecycleEvent, getSpecificationLoader()); if(EventUtil.eventTypeIsPostable( facet.getEventType(), ObjectCreatedEvent.Noop.class, ObjectCreatedEvent.Default.class, "isis.reflector.facet.domainObjectAnnotation.createdLifecycleEvent.postForDefault", getConfiguration())) { FacetUtil.addFacet(facet); } } private void processLifecycleEventLoaded(final DomainObject domainObject, final FacetHolder holder) { final Class<? extends ObjectLoadedEvent<?>> lifecycleEvent = domainObject.loadedLifecycleEvent(); final LoadedLifecycleEventFacetForDomainObjectAnnotation facet = new LoadedLifecycleEventFacetForDomainObjectAnnotation( holder, lifecycleEvent, getSpecificationLoader()); if(EventUtil.eventTypeIsPostable( facet.getEventType(), ObjectLoadedEvent.Noop.class, ObjectLoadedEvent.Default.class, "isis.reflector.facet.domainObjectAnnotation.loadedLifecycleEvent.postForDefault", getConfiguration())) { FacetUtil.addFacet(facet); } } private void processLifecycleEventPersisting(final DomainObject domainObject, final FacetHolder holder) { final Class<? extends ObjectPersistingEvent<?>> lifecycleEvent = domainObject.persistingLifecycleEvent(); final PersistingLifecycleEventFacetForDomainObjectAnnotation facet = new PersistingLifecycleEventFacetForDomainObjectAnnotation( holder, lifecycleEvent, getSpecificationLoader()); if(EventUtil.eventTypeIsPostable( facet.getEventType(), ObjectPersistingEvent.Noop.class, ObjectPersistingEvent.Default.class, "isis.reflector.facet.domainObjectAnnotation.persistingLifecycleEvent.postForDefault", getConfiguration())) { FacetUtil.addFacet(facet); } } private void processLifecycleEventPersisted(final DomainObject domainObject, final FacetHolder holder) { final Class<? extends ObjectPersistedEvent<?>> lifecycleEvent = domainObject.persistedLifecycleEvent(); final PersistedLifecycleEventFacetForDomainObjectAnnotation facet = new PersistedLifecycleEventFacetForDomainObjectAnnotation( holder, lifecycleEvent, getSpecificationLoader()); if(EventUtil.eventTypeIsPostable( facet.getEventType(), ObjectPersistedEvent.Noop.class, ObjectPersistedEvent.Default.class, "isis.reflector.facet.domainObjectAnnotation.persistedLifecycleEvent.postForDefault", getConfiguration())) { FacetUtil.addFacet(facet); } } private void processLifecycleEventRemoving(final DomainObject domainObject, final FacetHolder holder) { final Class<? extends ObjectRemovingEvent<?>> lifecycleEvent = domainObject.removingLifecycleEvent(); final RemovingLifecycleEventFacetForDomainObjectAnnotation facet = new RemovingLifecycleEventFacetForDomainObjectAnnotation( holder, lifecycleEvent, getSpecificationLoader()); if(EventUtil.eventTypeIsPostable( facet.getEventType(), ObjectRemovingEvent.Noop.class, ObjectRemovingEvent.Default.class, "isis.reflector.facet.domainObjectAnnotation.removingLifecycleEvent.postForDefault", getConfiguration())) { FacetUtil.addFacet(facet); } } private void processLifecycleEventUpdated(final DomainObject domainObject, final FacetHolder holder) { final Class<? extends ObjectUpdatedEvent<?>> lifecycleEvent = domainObject.updatedLifecycleEvent(); final UpdatedLifecycleEventFacetForDomainObjectAnnotation facet = new UpdatedLifecycleEventFacetForDomainObjectAnnotation( holder, lifecycleEvent, getSpecificationLoader()); if(EventUtil.eventTypeIsPostable( facet.getEventType(), ObjectUpdatedEvent.Noop.class, ObjectUpdatedEvent.Default.class, "isis.reflector.facet.domainObjectAnnotation.updatedLifecycleEvent.postForDefault", getConfiguration())) { FacetUtil.addFacet(facet); } } private void processLifecycleEventUpdating(final DomainObject domainObject, final FacetHolder holder) { final Class<? extends ObjectUpdatingEvent<?>> lifecycleEvent = domainObject.updatingLifecycleEvent(); final UpdatingLifecycleEventFacetForDomainObjectAnnotation facet = new UpdatingLifecycleEventFacetForDomainObjectAnnotation( holder, lifecycleEvent, getSpecificationLoader()); if(EventUtil.eventTypeIsPostable( facet.getEventType(), ObjectUpdatingEvent.Noop.class, ObjectUpdatingEvent.Default.class, "isis.reflector.facet.domainObjectAnnotation.updatingLifecycleEvent.postForDefault", getConfiguration())) { FacetUtil.addFacet(facet); } } // ////////////////////////////////////// @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) { validate(thisSpec, validationFailures); return true; } private void validate(final ObjectSpecification thisSpec, final ValidationFailures validationFailures) { if(!thisSpec.isPersistenceCapableOrViewModel()) { return; } final Map<ObjectSpecId, ObjectSpecification> specById = Maps.newHashMap(); final Collection<ObjectSpecification> allSpecifications = getSpecificationLoader().allSpecifications(); for (final ObjectSpecification otherSpec : allSpecifications) { if(thisSpec == otherSpec) { continue; } if(!otherSpec.isPersistenceCapableOrViewModel()) { continue; } final ObjectSpecId objectSpecId = otherSpec.getSpecId(); if (objectSpecId == null) { continue; } final ObjectSpecification existingSpec = specById.put(objectSpecId, otherSpec); if (existingSpec == null) { continue; } validationFailures.add( "%s: cannot have two entities with same object type (@Discriminator, @DomainObject(objectType=...), @ObjectType or @PersistenceCapable(schema=...)); %s " + "has same value (%s).", existingSpec.getFullIdentifier(), otherSpec.getFullIdentifier(), objectSpecId); } } })); metaModelValidator.add(publishedObjectValidator); metaModelValidator.add(auditedValidator); metaModelValidator.add(autoCompleteValidator); metaModelValidator.add(boundedValidator); metaModelValidator.add(immutableValidator); metaModelValidator.add(objectTypeValidator); metaModelValidator.add(autoCompleteInvalid); metaModelValidator.add(mixinTypeValidator); } // ////////////////////////////////////// @Override public void setServicesInjector(final ServicesInjector servicesInjector) { super.setServicesInjector(servicesInjector); IsisConfiguration configuration = getConfiguration(); publishedObjectValidator.setConfiguration(configuration); auditedValidator.setConfiguration(configuration); autoCompleteValidator.setConfiguration(configuration); boundedValidator.setConfiguration(configuration); immutableValidator.setConfiguration(configuration); objectTypeValidator.setConfiguration(configuration); this.persistenceSessionServiceInternal = servicesInjector.getPersistenceSessionServiceInternal(); } // ////////////////////////////////////// private final Map<Class, Nullable<Method>> postConstructMethods = Maps.newHashMap(); public Method postConstructMethodFor(final Object pojo) { return MethodFinderUtils.findAnnotatedMethod(pojo, PostConstruct.class, postConstructMethods); } PersistenceSessionServiceInternal persistenceSessionServiceInternal; }