This is an automated email from the ASF dual-hosted git repository. borinquenkid pushed a commit to branch 8.0.x-hibernate7 in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 4b13270674330415ed4003bc7e176889af06cc62 Author: Walter Duque de Estrada <[email protected]> AuthorDate: Sat Feb 28 19:10:11 2026 -0600 refactor more MultiTenantFilterBinder --- .../cfg/domainbinding/binder/SubClassBinder.java | 16 +++- .../hibernate/GrailsHibernatePersistentEntity.java | 12 +-- .../util/MultiTenantFilterBinder.java | 97 +++++++++++++++------- .../cfg/domainbinding/CollectionBinderSpec.groovy | 2 +- .../domainbinding/GrailsPropertyBinderSpec.groovy | 2 +- .../secondpass/ListSecondPassBinderSpec.groovy | 2 +- .../secondpass/MapSecondPassBinderSpec.groovy | 2 +- .../util/MultiTenantFilterBinderSpec.groovy | 34 ++++---- 8 files changed, 111 insertions(+), 56 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinder.java index fd4480d896..b1049a5e4b 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/SubClassBinder.java @@ -23,11 +23,13 @@ import java.util.Collection; import org.grails.orm.hibernate.cfg.Mapping; import org.grails.orm.hibernate.cfg.MappingCacheHolder; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity; -import org.grails.orm.hibernate.cfg.domainbinding.util.DefaultColumnNameFetcher; import org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterBinder; import org.hibernate.boot.spi.InFlightMetadataCollector; +import org.hibernate.mapping.JoinedSubclass; import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.SingleTableSubclass; import org.hibernate.mapping.Subclass; +import org.hibernate.mapping.UnionSubclass; /** Binder for subclasses. */ public class SubClassBinder { @@ -67,7 +69,7 @@ public class SubClassBinder { parent.addSubclass(subClass); mappings.addEntityBinding(subClass); - multiTenantFilterBinder.bind(sub, subClass); + bindMultiTenantFilter(sub, subClass); Collection<GrailsHibernatePersistentEntity> children = sub.getChildEntities(dataSourceName); if (!children.isEmpty()) { @@ -75,4 +77,14 @@ public class SubClassBinder { children.forEach(sub1 -> bindSubClass(sub1, subClass, mappings, m)); } } + + private void bindMultiTenantFilter(GrailsHibernatePersistentEntity sub, Subclass subClass) { + if (subClass instanceof SingleTableSubclass singleTableSubclass) { + multiTenantFilterBinder.bind(sub, singleTableSubclass); + } else if (subClass instanceof JoinedSubclass joinedSubclass) { + multiTenantFilterBinder.bind(sub, joinedSubclass); + } else if (subClass instanceof UnionSubclass unionSubclass) { + multiTenantFilterBinder.bind(sub, unionSubclass); + } + } } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentEntity.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentEntity.java index ad0b36e45e..17409f1c39 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentEntity.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/hibernate/GrailsHibernatePersistentEntity.java @@ -201,13 +201,13 @@ public interface GrailsHibernatePersistentEntity extends PersistentEntity { .forEach(new ConfigureDerivedPropertiesConsumer(getMappedForm())); } + default HibernatePersistentProperty getHibernateTenantId() { + return (HibernatePersistentProperty) getTenantId(); + } + default String getMultiTenantFilterCondition(DefaultColumnNameFetcher fetcher) { - return Optional.ofNullable(getTenantId()) - .map( - tenantId -> - tenantId instanceof HibernatePersistentProperty ghpp - ? fetcher.getDefaultColumnName(ghpp) - : tenantId.getName()) + return Optional.ofNullable(getHibernateTenantId()) + .map(fetcher::getDefaultColumnName) .map(defaultColumnName -> ":tenantId = " + defaultColumnName) .orElse(null); } diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java index e43f08202d..1b0a44141f 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinder.java @@ -23,13 +23,17 @@ import jakarta.annotation.Nullable; import java.util.Collections; import java.util.Optional; import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.model.types.TenantId; import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity; +import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty; import org.hibernate.boot.spi.InFlightMetadataCollector; import org.hibernate.engine.spi.FilterDefinition; +import org.hibernate.mapping.BasicValue; +import org.hibernate.mapping.JoinedSubclass; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.RootClass; +import org.hibernate.mapping.SingleTableSubclass; +import org.hibernate.mapping.UnionSubclass; /** * Utility class for binding multi-tenant filters to the Hibernate meta model. @@ -55,23 +59,69 @@ public class MultiTenantFilterBinder { } /** - * Binds a multi-tenant filter to the given persistent class if necessary. + * Binds a multi-tenant filter to the given root class if necessary. * * @param entity The target persistent entity - * @param persistentClass The persistent class to add the filter to + * @param rootClass The root class to add the filter to * @return The filter definition applied, or null if none */ @Nullable public FilterDefinition bind( + @Nonnull GrailsHibernatePersistentEntity entity, @Nonnull RootClass rootClass) { + return doBind(entity, rootClass); + } + + /** + * Binds a multi-tenant filter to the given single table subclass if necessary. + * + * @param entity The target persistent entity + * @param subclass The single table subclass + * @return null as it's redundant for single table subclasses + */ + @Nullable + public FilterDefinition bind( + @Nonnull GrailsHibernatePersistentEntity entity, @Nonnull SingleTableSubclass subclass) { + return null; // Redundant for SingleTableSubclass + } + + /** + * Binds a multi-tenant filter to the given joined subclass if necessary. + * + * @param entity The target persistent entity + * @param subclass The joined subclass + * @return The filter definition applied, or null if none + */ + @Nullable + public FilterDefinition bind( + @Nonnull GrailsHibernatePersistentEntity entity, @Nonnull JoinedSubclass subclass) { + return doBind(entity, subclass); + } + + /** + * Binds a multi-tenant filter to the given union subclass if necessary. + * + * @param entity The target persistent entity + * @param subclass The union subclass + * @return The filter definition applied, or null if none + */ + @Nullable + public FilterDefinition bind( + @Nonnull GrailsHibernatePersistentEntity entity, @Nonnull UnionSubclass subclass) { + return doBind(entity, subclass); + } + + @Nullable + private FilterDefinition doBind( @Nonnull GrailsHibernatePersistentEntity entity, @Nonnull PersistentClass persistentClass) { if (!entity.isMultiTenant()) { return null; } - return Optional.ofNullable(entity.getTenantId()) - .map(TenantId::getName) + return Optional.ofNullable(entity.getHibernateTenantId()) + .map(HibernatePersistentProperty::getName) .map(name -> grailsPropertyResolver.getProperty(persistentClass, name)) + .filter(property -> shouldApplyFilter(entity, persistentClass, property)) .map( property -> { var filterName = GormProperties.TENANT_IDENTITY; @@ -83,33 +133,26 @@ public class MultiTenantFilterBinder { } } - applyFilterToPersistentClass(entity, persistentClass, filterName, property); + if (filterDefinition != null) { + persistentClass.addFilter( + filterName, + entity.getMultiTenantFilterCondition(fetcher), + true, // autoAliasInjection + Collections.emptyMap(), + Collections.emptyMap()); + } return filterDefinition; }) .orElse(null); } - private void applyFilterToPersistentClass( - GrailsHibernatePersistentEntity entity, - PersistentClass persistentClass, - String filterName, - Property property) { - - if (shouldApplyFilter(entity, persistentClass, property)) { - persistentClass.addFilter( - filterName, - entity.getMultiTenantFilterCondition(fetcher), - true, // autoAliasInjection - Collections.emptyMap(), - Collections.emptyMap()); - } - } - private boolean shouldApplyFilter( GrailsHibernatePersistentEntity entity, PersistentClass persistentClass, Property property) { - boolean isRoot = - persistentClass instanceof RootClass - || persistentClass.equals(persistentClass.getRootClass()); + if (!(property.getValue() instanceof BasicValue)) { + return false; + } + + boolean isRoot = persistentClass instanceof RootClass; var table = persistentClass.getTable(); var propertyValue = property.getValue(); @@ -117,10 +160,6 @@ public class MultiTenantFilterBinder { boolean isInherited = table != null && propertyTable != null && !table.equals(propertyTable); - // Apply if it's the root or if the subclass has its own table containing the column - // (UnionSubclass). - // Skip if it's a SingleTable subclass (redundant) or JoinedSubclass where column is in root - // (alias safety). if (isRoot || !isInherited) { return isRoot || !entity.isTablePerHierarchySubclass(); } diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy index 69a2d7be6c..0da2b5f3d9 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/CollectionBinderSpec.groovy @@ -112,7 +112,7 @@ class CollectionBinderSpec extends HibernateGormDatastoreSpec { ClassBinder classBinder = new ClassBinder() ClassPropertiesBinder classPropertiesBinder = new ClassPropertiesBinder(propertyBinder, propertyFromValueCreator) - MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataCollector(), defaultColumnNameFetcher) + MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataBuildingContext().getMetadataCollector(), defaultColumnNameFetcher) JoinedSubClassBinder joinedSubClassBinder = new JoinedSubClassBinder(metadataBuildingContext, namingStrategy, new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), columnNameForPropertyAndPathFetcher, classBinder) UnionSubclassBinder unionSubclassBinder = new UnionSubclassBinder(metadataBuildingContext, namingStrategy, classBinder) SingleTableSubclassBinder singleTableSubclassBinder = new SingleTableSubclassBinder(classBinder) diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy index d42d951f2b..1c535e7f2a 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/GrailsPropertyBinderSpec.groovy @@ -172,7 +172,7 @@ class GrailsPropertyBinderSpec extends HibernateGormDatastoreSpec { ClassBinder classBinder = new ClassBinder() ClassPropertiesBinder classPropertiesBinder = new ClassPropertiesBinder(propertyBinder, propertyFromValueCreator, naturalIdentifierBinder) - MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataCollector(), defaultColumnNameFetcher) + MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataBuildingContext().getMetadataCollector(), defaultColumnNameFetcher) JoinedSubClassBinder joinedSubClassBinder = new JoinedSubClassBinder(metadataBuildingContext, namingStrategy, new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), columnNameForPropertyAndPathFetcher, classBinder) UnionSubclassBinder unionSubclassBinder = new UnionSubclassBinder(metadataBuildingContext, namingStrategy, classBinder) SingleTableSubclassBinder singleTableSubclassBinder = new SingleTableSubclassBinder(classBinder) diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy index 50cbd74416..ce263b4dc2 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/ListSecondPassBinderSpec.groovy @@ -111,7 +111,7 @@ class ListSecondPassBinderSpec extends HibernateGormDatastoreSpec { ClassBinder classBinder = new ClassBinder() ClassPropertiesBinder classPropertiesBinder = new ClassPropertiesBinder(propertyBinder, propertyFromValueCreator) - MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataCollector(), defaultColumnNameFetcher) + MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataBuildingContext().getMetadataCollector(), defaultColumnNameFetcher) JoinedSubClassBinder joinedSubClassBinder = new JoinedSubClassBinder(metadataBuildingContext, namingStrategy, new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), columnNameForPropertyAndPathFetcher, classBinder) UnionSubclassBinder unionSubclassBinder = new UnionSubclassBinder(metadataBuildingContext, namingStrategy, classBinder) SingleTableSubclassBinder singleTableSubclassBinder = new SingleTableSubclassBinder(classBinder) diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy index 3c31e59b8a..430f44876a 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/MapSecondPassBinderSpec.groovy @@ -111,7 +111,7 @@ class MapSecondPassBinderSpec extends HibernateGormDatastoreSpec { ClassBinder classBinder = new ClassBinder() ClassPropertiesBinder classPropertiesBinder = new ClassPropertiesBinder(propertyBinder, propertyFromValueCreator) - MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataCollector(), defaultColumnNameFetcher) + MultiTenantFilterBinder multiTenantFilterBinder = new MultiTenantFilterBinder(new org.grails.orm.hibernate.cfg.domainbinding.util.GrailsPropertyResolver(), new org.grails.orm.hibernate.cfg.domainbinding.util.MultiTenantFilterDefinitionBinder(), binder.getMetadataBuildingContext().getMetadataCollector(), defaultColumnNameFetcher) JoinedSubClassBinder joinedSubClassBinder = new JoinedSubClassBinder(metadataBuildingContext, namingStrategy, new org.grails.orm.hibernate.cfg.domainbinding.binder.SimpleValueColumnBinder(), columnNameForPropertyAndPathFetcher, classBinder) UnionSubclassBinder unionSubclassBinder = new UnionSubclassBinder(metadataBuildingContext, namingStrategy, classBinder) SingleTableSubclassBinder singleTableSubclassBinder = new SingleTableSubclassBinder(classBinder) diff --git a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinderSpec.groovy b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinderSpec.groovy index 99f213eca6..9a1543fc8f 100644 --- a/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinderSpec.groovy +++ b/grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/MultiTenantFilterBinderSpec.groovy @@ -3,6 +3,7 @@ package org.grails.orm.hibernate.cfg.domainbinding.util import grails.gorm.specs.HibernateGormDatastoreSpec import org.grails.datastore.mapping.model.config.GormProperties import org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity +import org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty import org.hibernate.boot.spi.InFlightMetadataCollector import org.hibernate.mapping.BasicValue import org.hibernate.mapping.Property @@ -35,7 +36,9 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { def buildingContext = getGrailsDomainBinder().getMetadataBuildingContext() def persistentClass = new RootClass(buildingContext) - def tenantId = Mock(TenantId) + def tenantId = Mock(HibernatePersistentProperty) + tenantId.getName() >> "tenantId" + def property = new Property() property.setName("tenantId") @@ -44,8 +47,7 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { value.setTypeName("long") entity.isMultiTenant() >> true - entity.getTenantId() >> tenantId - tenantId.getName() >> "tenantId" + entity.getHibernateTenantId() >> tenantId grailsPropertyResolver.getProperty(persistentClass, "tenantId") >> property property.setValue(value) @@ -74,7 +76,8 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { rootClass.setTable(table) def persistentClass = new SingleTableSubclass(rootClass, buildingContext) - def tenantId = Mock(TenantId) + def tenantId = Mock(HibernatePersistentProperty) + tenantId.getName() >> "tenantId" def property = new Property() property.setName("tenantId") @@ -85,9 +88,8 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { rootClass.addProperty(property) entity.isMultiTenant() >> true - entity.getTenantId() >> tenantId - tenantId.getName() >> "tenantId" - grailsPropertyResolver.getProperty(persistentClass, "tenantId") >> property // Add stub here + entity.getHibernateTenantId() >> tenantId + grailsPropertyResolver.getProperty(persistentClass, "tenantId") >> property entity.isTablePerHierarchySubclass() >> true mockCollector.getFilterDefinition(_) >> Mock(FilterDefinition) @@ -113,7 +115,9 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { subTable.setName("SUB_TABLE") persistentClass.setTable(subTable) - def tenantId = Mock(TenantId) + def tenantId = Mock(HibernatePersistentProperty) + tenantId.getName() >> "tenantId" + def property = new Property() property.setName("tenantId") def value = new BasicValue(buildingContext, rootTable) @@ -123,9 +127,8 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { rootClass.addProperty(property) entity.isMultiTenant() >> true - entity.getTenantId() >> tenantId - tenantId.getName() >> "tenantId" - grailsPropertyResolver.getProperty(persistentClass, "tenantId") >> property // Add stub here + entity.getHibernateTenantId() >> tenantId + grailsPropertyResolver.getProperty(persistentClass, "tenantId") >> property mockCollector.getFilterDefinition(_) >> Mock(FilterDefinition) @@ -146,7 +149,9 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { def persistentClass = new UnionSubclass(rootClass, buildingContext) persistentClass.setTable(subTable) - def tenantId = Mock(TenantId) + def tenantId = Mock(HibernatePersistentProperty) + tenantId.getName() >> "tenantId" + def property = new Property() property.setName("tenantId") def value = new BasicValue(buildingContext, subTable) @@ -156,9 +161,8 @@ class MultiTenantFilterBinderSpec extends HibernateGormDatastoreSpec { persistentClass.addProperty(property) entity.isMultiTenant() >> true - entity.getTenantId() >> tenantId - tenantId.getName() >> "tenantId" - grailsPropertyResolver.getProperty(persistentClass, "tenantId") >> property // Add stub here + entity.getHibernateTenantId() >> tenantId + grailsPropertyResolver.getProperty(persistentClass, "tenantId") >> property entity.isTablePerHierarchySubclass() >> false mockCollector.getFilterDefinition(_) >> Mock(FilterDefinition)
