eschew laziness in descriptor model as TCK tests (rightly) depend on the creation of the metamodel detecting all issues eagerly; address some issues that became apparent with the removal of said laziness
Project: http://git-wip-us.apache.org/repos/asf/bval/repo Commit: http://git-wip-us.apache.org/repos/asf/bval/commit/a7d88a5c Tree: http://git-wip-us.apache.org/repos/asf/bval/tree/a7d88a5c Diff: http://git-wip-us.apache.org/repos/asf/bval/diff/a7d88a5c Branch: refs/heads/bv2 Commit: a7d88a5c45e7b234bbda0d021573f6f4674c1661 Parents: 2cdeb84 Author: Matt Benson <[email protected]> Authored: Sat Feb 24 13:58:20 2018 -0600 Committer: Matt Benson <[email protected]> Committed: Sat Feb 24 13:58:40 2018 -0600 ---------------------------------------------------------------------- .../org/apache/bval/jsr/descriptor/BeanD.java | 46 ++++------ .../jsr/descriptor/CascadableContainerD.java | 7 +- .../apache/bval/jsr/descriptor/ConstraintD.java | 91 ++++++++++---------- .../bval/jsr/descriptor/DescriptorManager.java | 9 +- .../bval/jsr/descriptor/MetadataReader.java | 15 ++-- .../apache/bval/jsr/descriptor/ParameterD.java | 2 +- .../bval/jsr/metadata/CompositeBuilder.java | 6 +- .../bval/jsr/metadata/HierarchyBuilder.java | 5 +- 8 files changed, 92 insertions(+), 89 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/bval/blob/a7d88a5c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java index e1e97ee..b6e7e2e 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/BeanD.java @@ -34,33 +34,26 @@ import javax.validation.metadata.PropertyDescriptor; import org.apache.bval.jsr.metadata.Signature; import org.apache.bval.jsr.util.ToUnmodifiable; import org.apache.bval.util.Exceptions; -import org.apache.bval.util.Lazy; import org.apache.bval.util.StringUtils; public class BeanD extends ElementD<Class<?>, MetadataReader.ForBean> implements BeanDescriptor { - private static boolean constrainedProperty(PropertyDescriptor pd) { - return pd.hasConstraints() || pd.isCascaded(); - } - private final Class<?> beanClass; - - private final Lazy<List<Class<?>>> groupSequence; - private final Lazy<Map<String, PropertyDescriptor>> propertiesMap; - private final Lazy<Set<PropertyDescriptor>> properties; - private final Lazy<Map<Signature, ConstructorD>> constructors; - private final Lazy<Map<Signature, MethodD>> methods; + private final List<Class<?>> groupSequence; + private final Map<String, PropertyDescriptor> propertiesMap; + private final Set<PropertyDescriptor> properties; + private final Map<Signature, ConstructorD> constructors; + private final Map<Signature, MethodD> methods; BeanD(MetadataReader.ForBean reader) { super(reader); this.beanClass = reader.meta.getHost(); - groupSequence = new Lazy<>(reader::getGroupSequence); - propertiesMap = new Lazy<>(() -> reader.getProperties(this)); - properties = new Lazy<>(() -> propertiesMap.get().values().stream().filter(BeanD::constrainedProperty) - .collect(ToUnmodifiable.set())); - constructors = new Lazy<>(() -> reader.getConstructors(this)); - methods = new Lazy<>(() -> reader.getMethods(this)); + groupSequence = reader.getGroupSequence(); + propertiesMap = reader.getProperties(this); + properties = propertiesMap.values().stream().filter(DescriptorManager::isConstrained).collect(ToUnmodifiable.set()); + constructors = reader.getConstructors(this); + methods = reader.getMethods(this); } @Override @@ -70,22 +63,21 @@ public class BeanD extends ElementD<Class<?>, MetadataReader.ForBean> implements @Override public boolean isBeanConstrained() { - return hasConstraints() || properties.get().stream().anyMatch(DescriptorManager::isConstrained); + return hasConstraints() || properties.stream().anyMatch(DescriptorManager::isConstrained); } @Override public PropertyDescriptor getConstraintsForProperty(String propertyName) { - return Optional.ofNullable(getProperty(propertyName)).filter(BeanD::constrainedProperty).orElse(null); + return Optional.ofNullable(getProperty(propertyName)).filter(DescriptorManager::isConstrained).orElse(null); } @Override public Set<PropertyDescriptor> getConstrainedProperties() { - return properties.get(); + return properties; } @Override public MethodDescriptor getConstraintsForMethod(String methodName, Class<?>... parameterTypes) { - final Map<Signature, MethodD> methods = this.methods.get(); final Signature key = new Signature(methodName, parameterTypes); return methods.get(key); } @@ -93,26 +85,26 @@ public class BeanD extends ElementD<Class<?>, MetadataReader.ForBean> implements @SuppressWarnings("unlikely-arg-type") @Override public Set<MethodDescriptor> getConstrainedMethods(MethodType methodType, MethodType... methodTypes) { - EnumSet<MethodType> filter = EnumSet.of(methodType, methodTypes); - return methods.get().values().stream().filter(m -> filter.contains(m.getMethodType())) + final EnumSet<MethodType> filter = EnumSet.of(methodType, methodTypes); + return methods.values().stream().filter(m -> filter.contains(m.getMethodType())) .collect(ToUnmodifiable.set()); } @Override public ConstructorDescriptor getConstraintsForConstructor(Class<?>... parameterTypes) { - return constructors.get().get(new Signature(beanClass.getName(), parameterTypes)); + return constructors.get(new Signature(beanClass.getName(), parameterTypes)); } @Override public Set<ConstructorDescriptor> getConstrainedConstructors() { - return constructors.get().values().stream().collect(ToUnmodifiable.set()); + return constructors.values().stream().collect(ToUnmodifiable.set()); } public PropertyDescriptor getProperty(String propertyName) { Exceptions.raiseIf(StringUtils.isBlank(propertyName), IllegalArgumentException::new, "propertyName was null/empty/blank"); - return propertiesMap.get().get(propertyName); + return propertiesMap.get(propertyName); } @Override @@ -122,7 +114,7 @@ public class BeanD extends ElementD<Class<?>, MetadataReader.ForBean> implements @Override public List<Class<?>> getGroupSequence() { - return groupSequence.get(); + return groupSequence; } public final Type getGenericType() { http://git-wip-us.apache.org/repos/asf/bval/blob/a7d88a5c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CascadableContainerD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CascadableContainerD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CascadableContainerD.java index 8c76fb0..8e6410a 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CascadableContainerD.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/CascadableContainerD.java @@ -30,7 +30,6 @@ import javax.validation.metadata.GroupConversionDescriptor; import org.apache.bval.jsr.GraphContext; import org.apache.bval.jsr.util.ToUnmodifiable; -import org.apache.bval.util.Lazy; import org.apache.bval.util.Validate; import org.apache.bval.util.reflection.TypeUtils; @@ -39,13 +38,13 @@ public abstract class CascadableContainerD<P extends ElementD<?, ?>, E extends A private final boolean cascaded; private final Set<GroupConversion> groupConversions; - private final Lazy<Set<ContainerElementTypeD>> containerElementTypes; + private final Set<ContainerElementTypeD> containerElementTypes; protected CascadableContainerD(MetadataReader.ForContainer<E> reader, P parent) { super(reader, parent); cascaded = reader.isCascaded(); groupConversions = reader.getGroupConversions(); - containerElementTypes = new Lazy<>(() -> reader.getContainerElementTypes(this)); + containerElementTypes = reader.getContainerElementTypes(this); } @Override @@ -66,7 +65,7 @@ public abstract class CascadableContainerD<P extends ElementD<?, ?>, E extends A @Override public Set<ContainerElementTypeDescriptor> getConstrainedContainerElementTypes() { - return containerElementTypes.get().stream().filter(DescriptorManager::isConstrained) + return containerElementTypes.stream().filter(DescriptorManager::isConstrained) .collect(ToUnmodifiable.set()); } http://git-wip-us.apache.org/repos/asf/bval/blob/a7d88a5c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstraintD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstraintD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstraintD.java index c812cf5..c5000e2 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstraintD.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ConstraintD.java @@ -57,11 +57,18 @@ import org.apache.bval.jsr.util.AnnotationsManager; import org.apache.bval.jsr.util.ToUnmodifiable; import org.apache.bval.jsr.valueextraction.ValueExtractors; import org.apache.bval.util.Exceptions; -import org.apache.bval.util.Lazy; import org.apache.bval.util.Validate; import org.apache.bval.util.reflection.TypeUtils; public class ConstraintD<A extends Annotation> implements ConstraintDescriptor<A> { + private enum Optionality { + OPTIONAL, REQUIRED; + + public boolean isOptional() { + return this == Optionality.OPTIONAL; + } + } + private static <T> Set<T> set(Supplier<T[]> array) { return Stream.of(array.get()).collect(ToUnmodifiable.set()); } @@ -69,42 +76,37 @@ public class ConstraintD<A extends Annotation> implements ConstraintDescriptor<A private final A annotation; private final Scope scope; private final Metas<?> meta; - private final Class<?> validatedType; - - private final Lazy<Set<Class<?>>> groups = new Lazy<>(this::computeGroups); private final Set<Class<? extends Payload>> payload; + private final Class<?> validatedType; - private final Lazy<Boolean> reportAsSingle = - new Lazy<>(() -> getAnnotation().annotationType().isAnnotationPresent(ReportAsSingleViolation.class)); - - private final Lazy<ValidateUnwrappedValue> valueUnwrapping = new Lazy<>(this::computeValidateUnwrappedValue); + private final Set<Class<?>> groups; + private final boolean reportAsSingle; + private final ValidateUnwrappedValue valueUnwrapping; + private final Map<String, Object> attributes; - private final Lazy<Map<String, Object>> attributes; - private final Lazy<Set<ConstraintDescriptor<?>>> composingConstraints; - private final Lazy<List<Class<? extends ConstraintValidator<A, ?>>>> constraintValidatorClasses; - private final Lazy<Class<? extends ConstraintValidator<A, ?>>> constraintValidatorClass; + private final Set<ConstraintDescriptor<?>> composingConstraints; + private final List<Class<? extends ConstraintValidator<A, ?>>> constraintValidatorClasses; + private final Class<? extends ConstraintValidator<A, ?>> constraintValidatorClass; public ConstraintD(A annotation, Scope scope, Metas<?> meta, ApacheValidatorFactory validatorFactory) { this.annotation = Validate.notNull(annotation, "annotation"); this.scope = Validate.notNull(scope, "scope"); this.meta = Validate.notNull(meta, "meta"); - this.payload = computePayload(); - this.validatedType = computeValidatedType(validatorFactory); - - attributes = new Lazy<>(() -> AnnotationsManager.readAttributes(annotation)); - // retain no references to the validatorFactory; only wrap it in lazy - // suppliers - Validate.notNull(validatorFactory, "validatorFactory"); - composingConstraints = new Lazy<>(computeComposingConstraints(validatorFactory)); - constraintValidatorClasses = new Lazy<>(computeConstraintValidatorClasses(validatorFactory)); + payload = computePayload(); + validatedType = computeValidatedType(validatorFactory); - final Supplier<Class<? extends ConstraintValidator<A, ?>>> computeConstraintValidatorClass = - new ComputeConstraintValidatorClass<>(validatorFactory, meta.getValidationTargets(), annotation, - validatedType); + groups = computeGroups(); + reportAsSingle = annotation.annotationType().isAnnotationPresent(ReportAsSingleViolation.class); + valueUnwrapping = computeValidateUnwrappedValue(); + attributes = AnnotationsManager.readAttributes(annotation); - constraintValidatorClass = new Lazy<>(computeConstraintValidatorClass); + Validate.notNull(validatorFactory, "validatorFactory"); + composingConstraints = computeComposingConstraints(validatorFactory); + constraintValidatorClasses = computeConstraintValidatorClasses(validatorFactory); + constraintValidatorClass = new ComputeConstraintValidatorClass<>(validatorFactory, meta.getValidationTargets(), + annotation, validatedType).get(); } @Override @@ -114,7 +116,7 @@ public class ConstraintD<A extends Annotation> implements ConstraintDescriptor<A @Override public Set<Class<?>> getGroups() { - return groups.get(); + return groups; } @Override @@ -124,28 +126,27 @@ public class ConstraintD<A extends Annotation> implements ConstraintDescriptor<A @Override public List<Class<? extends ConstraintValidator<A, ?>>> getConstraintValidatorClasses() { - return constraintValidatorClasses.get(); + return constraintValidatorClasses; } @Override public Map<String, Object> getAttributes() { - return attributes.get(); + return attributes; } @Override public Set<ConstraintDescriptor<?>> getComposingConstraints() { - return composingConstraints.get(); + return composingConstraints; } @Override public boolean isReportAsSingleViolation() { - return reportAsSingle.get().booleanValue(); + return reportAsSingle; } @Override public String getMessageTemplate() { - final boolean required = true; - return read(ConstraintAnnotationAttributes.MESSAGE, required); + return read(ConstraintAnnotationAttributes.MESSAGE, Optionality.REQUIRED); } @Override @@ -155,7 +156,7 @@ public class ConstraintD<A extends Annotation> implements ConstraintDescriptor<A @Override public ValidateUnwrappedValue getValueUnwrapping() { - return valueUnwrapping.get(); + return valueUnwrapping; } @Override @@ -184,35 +185,34 @@ public class ConstraintD<A extends Annotation> implements ConstraintDescriptor<A } public Class<? extends ConstraintValidator<A, ?>> getConstraintValidatorClass() { - return constraintValidatorClass.get(); + return constraintValidatorClass; } private <T> T read(ConstraintAnnotationAttributes attr) { - return read(attr, false); + return read(attr, Optionality.OPTIONAL); } - private <T> T read(ConstraintAnnotationAttributes attr, boolean required) { + private <T> T read(ConstraintAnnotationAttributes attr, Optionality optionality) { final Class<? extends Annotation> constraintType = annotation.annotationType(); final Optional<T> result = Optional.of(constraintType).map(attr::analyze).filter(Worker::isValid).map(w -> w.<T> read(annotation)); - Exceptions.raiseIf(required && !result.isPresent(), ConstraintDefinitionException::new, + Exceptions.raiseUnless(optionality.isOptional() || result.isPresent(), ConstraintDefinitionException::new, "Required attribute %s missing from constraint type %s", attr.getAttributeName(), constraintType); return result.orElse(null); } - private Supplier<Set<ConstraintDescriptor<?>>> computeComposingConstraints( - ApacheValidatorFactory validatorFactory) { - return () -> Stream.of(validatorFactory.getAnnotationsManager().getComposingConstraints(annotation)) + private Set<ConstraintDescriptor<?>> computeComposingConstraints(ApacheValidatorFactory validatorFactory) { + return Stream.of(validatorFactory.getAnnotationsManager().getComposingConstraints(annotation)) .map(c -> new ConstraintD<>(c, scope, meta, validatorFactory)) .collect(ToUnmodifiable.set(LinkedHashSet::new)); } @SuppressWarnings("unchecked") - private Supplier<List<Class<? extends ConstraintValidator<A, ?>>>> computeConstraintValidatorClasses( + private List<Class<? extends ConstraintValidator<A, ?>>> computeConstraintValidatorClasses( ApacheValidatorFactory validatorFactory) { - return () -> validatorFactory.getConstraintsCache() + return validatorFactory.getConstraintsCache() .getConstraintValidatorClasses((Class<A>) annotation.annotationType()); } @@ -229,8 +229,7 @@ public class ConstraintD<A extends Annotation> implements ConstraintDescriptor<A } private Set<Class<?>> computeGroups() { - final boolean required = true; - final Class<?>[] groups = read(ConstraintAnnotationAttributes.GROUPS, required); + final Class<?>[] groups = read(ConstraintAnnotationAttributes.GROUPS, Optionality.REQUIRED); if (groups.length == 0) { return Collections.singleton(Default.class); } @@ -238,8 +237,8 @@ public class ConstraintD<A extends Annotation> implements ConstraintDescriptor<A } private Set<Class<? extends Payload>> computePayload() { - final boolean required = true; - final Set<Class<? extends Payload>> result = set(() -> read(ConstraintAnnotationAttributes.PAYLOAD, required)); + final Set<Class<? extends Payload>> result = + set(() -> read(ConstraintAnnotationAttributes.PAYLOAD, Optionality.REQUIRED)); Exceptions.raiseIf(result.containsAll(Arrays.asList(Unwrapping.Unwrap.class, Unwrapping.Skip.class)), ConstraintDeclarationException::new, "Constraint %s declared at %s specifies conflicting value unwrapping hints", annotation, meta.getHost()); http://git-wip-us.apache.org/repos/asf/bval/blob/a7d88a5c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java index 96a0017..e90527e 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/DescriptorManager.java @@ -17,6 +17,7 @@ package org.apache.bval.jsr.descriptor; import java.util.List; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -52,7 +53,13 @@ public class DescriptorManager { public BeanDescriptor getBeanDescriptor(Class<?> beanClass) { Validate.notNull(beanClass, IllegalArgumentException::new, "beanClass"); - return beanDescriptors.computeIfAbsent(beanClass, k -> new BeanD(metadataReader.forBean(k, builder(k)))); + + // cannot use computeIfAbsent due to likely recursion: + if (beanDescriptors.containsKey(beanClass)) { + return beanDescriptors.get(beanClass); + } + final BeanD beanD = new BeanD(metadataReader.forBean(beanClass, builder(beanClass))); + return Optional.ofNullable(beanDescriptors.putIfAbsent(beanClass, beanD)).orElse(beanD); } private MetadataBuilder.ForBean builder(Class<?> beanClass) { http://git-wip-us.apache.org/repos/asf/bval/blob/a7d88a5c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java index c2f9f0c..ba49ed4 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/MetadataReader.java @@ -175,14 +175,15 @@ class MetadataReader { } } } - if (result != null) { - Exceptions.raiseUnless(result.contains(meta.getHost()), GroupDefinitionException::new, - "@%s for %s must contain %<s", GroupSequence.class.getSimpleName(), meta.getHost()); - Exceptions.raiseIf(result.contains(Default.class), GroupDefinitionException::new, - "@%s for %s must not contain %s", GroupSequence.class.getSimpleName(), meta.getHost(), - Default.class.getName()); + if (result == null) { + return null; } - return result; + Exceptions.raiseUnless(result.contains(meta.getHost()), GroupDefinitionException::new, + "@%s for %s must contain %<s", GroupSequence.class.getSimpleName(), meta.getHost()); + Exceptions.raiseIf(result.contains(Default.class), GroupDefinitionException::new, + "@%s for %s must not contain %s", GroupSequence.class.getSimpleName(), meta.getHost(), + Default.class.getName()); + return Collections.unmodifiableList(result); } } http://git-wip-us.apache.org/repos/asf/bval/blob/a7d88a5c/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ParameterD.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ParameterD.java b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ParameterD.java index 951eccb..e041275 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ParameterD.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/descriptor/ParameterD.java @@ -33,7 +33,7 @@ public class ParameterD<P extends ExecutableD<?, ?, P>> extends CascadableContai private final String name; private final Class<?> type; - protected ParameterD(Metas.ForParameter meta, int index, MetadataReader.ForContainer<Parameter> reader, P parent) { + ParameterD(Metas.ForParameter meta, int index, MetadataReader.ForContainer<Parameter> reader, P parent) { super(reader, parent); Validate.isTrue(index >= 0 && index < meta.getHost().getDeclaringExecutable().getParameterCount(), http://git-wip-us.apache.org/repos/asf/bval/blob/a7d88a5c/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/CompositeBuilder.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/CompositeBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/CompositeBuilder.java index 52a7407..54ff0f8 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/CompositeBuilder.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/CompositeBuilder.java @@ -184,8 +184,10 @@ public class CompositeBuilder { final Set<Integer> parameterCounts = parameterLists.stream().map(List::size).collect(Collectors.toSet()); Validate.validState(parameterCounts.size() == 1, "Mismatched parameter counts: %s", parameterCounts); - return IntStream.range(0, parameterCounts.iterator().next().intValue()) - .mapToObj(n -> new CompositeBuilder.ForContainer<>(parameterLists.get(n))) + final int parameterCount = parameterCounts.iterator().next().intValue(); + return IntStream.range(0, parameterCount) + .mapToObj(n -> new CompositeBuilder.ForContainer<>( + parameterLists.stream().map(l -> l.get(n)).collect(Collectors.toList()))) .collect(ToUnmodifiable.list()); } http://git-wip-us.apache.org/repos/asf/bval/blob/a7d88a5c/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/HierarchyBuilder.java ---------------------------------------------------------------------- diff --git a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/HierarchyBuilder.java b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/HierarchyBuilder.java index a33ac4c..693c065 100644 --- a/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/HierarchyBuilder.java +++ b/bval-jsr/src/main/java/org/apache/bval/jsr/metadata/HierarchyBuilder.java @@ -72,9 +72,12 @@ public class HierarchyBuilder extends CompositeBuilder { return delegate.getGetters(hierarchyType); } + @SuppressWarnings("unlikely-arg-type") @Override public Map<Signature, MetadataBuilder.ForExecutable<Constructor<?>>> getConstructors(Metas<Class<?>> meta) { - return delegate.getConstructors(hierarchyType); + // suppress hierarchical ctors: + return hierarchyType.equals(meta.getHost()) ? delegate.getConstructors(hierarchyType) + : Collections.emptyMap(); } @Override
