diff --git a/subsystem/src/main/java/org/wildfly/subsystem/resource/capability/ResourceCapabilityReferenceRecorder.java b/subsystem/src/main/java/org/wildfly/subsystem/resource/capability/ResourceCapabilityReferenceRecorder.java index 6210c7f0383..2b32b7ec3b8 100644 --- a/subsystem/src/main/java/org/wildfly/subsystem/resource/capability/ResourceCapabilityReferenceRecorder.java +++ b/subsystem/src/main/java/org/wildfly/subsystem/resource/capability/ResourceCapabilityReferenceRecorder.java @@ -13,6 +13,7 @@ import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.capability.BinaryCapabilityNameResolver; +import org.jboss.as.controller.capability.QuaternaryCapabilityNameResolver; import org.jboss.as.controller.capability.RuntimeCapability; import org.jboss.as.controller.capability.TernaryCapabilityNameResolver; import org.jboss.as.controller.capability.UnaryCapabilityNameResolver; @@ -20,6 +21,7 @@ import org.jboss.dmr.ModelNode; import org.wildfly.service.descriptor.BinaryServiceDescriptor; import org.wildfly.service.descriptor.NullaryServiceDescriptor; +import org.wildfly.service.descriptor.QuaternaryServiceDescriptor; import org.wildfly.service.descriptor.ServiceDescriptor; import org.wildfly.service.descriptor.TernaryServiceDescriptor; import org.wildfly.service.descriptor.UnaryServiceDescriptor; @@ -61,62 +63,103 @@ default void removeCapabilityRequirements(OperationContext context, Resource res } /** - * Creates a new reference between the specified capability and the specified requirement. + * Creates a builder for a new reference between the specified capability and the specified requirement. * @param capability the capability referencing the specified requirement * @param requirement the requirement of the specified capability */ static Builder builder(RuntimeCapability capability, NullaryServiceDescriptor requirement) { - return new Builder<>(capability, requirement, ResourceCapabilityServiceDescriptorReference.EMPTY_RESOLVER); + return new DefaultBuilder<>(capability, requirement, ResourceCapabilityServiceDescriptorReference.EMPTY_RESOLVER); } /** - * Creates a new reference between the specified capability and the specified requirement. + * Creates a builder for a new reference between the specified capability and the specified requirement. + * By default, the requirement name will resolve against the path of the current resource. + * @param capability the capability referencing the specified requirement + * @param requirement the requirement of the specified capability + */ + static NaryBuilder builder(RuntimeCapability capability, UnaryServiceDescriptor requirement) { + return new DefaultBuilder<>(capability, requirement, UnaryCapabilityNameResolver.DEFAULT); + } + + /** + * Creates a builder for a new reference between the specified capability and the specified requirement. + * By default, the requirement name will resolve against the paths of the parent and current resources, respectively. * @param capability the capability referencing the specified requirement * @param requirement the requirement of the specified capability * @param requirementNameResolver function for resolving the dynamic components of the requirement name */ - static Builder builder(RuntimeCapability capability, UnaryServiceDescriptor requirement, UnaryCapabilityNameResolver requirementNameResolver) { - return new Builder<>(capability, requirement, requirementNameResolver); + static NaryBuilder builder(RuntimeCapability capability, BinaryServiceDescriptor requirement) { + return new DefaultBuilder<>(capability, requirement, BinaryCapabilityNameResolver.PARENT_CHILD); } /** - * Creates a new reference between the specified capability and the specified requirement. + * Creates a builder for a new reference between the specified capability and the specified requirement. + * By default, the requirement name will resolve against the paths of the grandparent, parent, and current resources, respectively. * @param capability the capability referencing the specified requirement * @param requirement the requirement of the specified capability * @param requirementNameResolver function for resolving the dynamic components of the requirement name */ - static Builder builder(RuntimeCapability capability, BinaryServiceDescriptor requirement, BinaryCapabilityNameResolver requirementNameResolver) { - return new Builder<>(capability, requirement, requirementNameResolver); + static NaryBuilder builder(RuntimeCapability capability, TernaryServiceDescriptor requirement) { + return new DefaultBuilder<>(capability, requirement, TernaryCapabilityNameResolver.GRANDPARENT_PARENT_CHILD); } /** - * Creates a new reference between the specified capability and the specified requirement. + * Creates a builder for a new reference between the specified capability and the specified requirement. + * By default, the requirement name will resolve against the paths of the great-grandparent, grandparent, parent, and current resources, respectively. * @param capability the capability referencing the specified requirement * @param requirement the requirement of the specified capability * @param requirementNameResolver function for resolving the dynamic components of the requirement name */ - static Builder builder(RuntimeCapability capability, TernaryServiceDescriptor requirement, TernaryCapabilityNameResolver requirementNameResolver) { - return new Builder<>(capability, requirement, requirementNameResolver); + static NaryBuilder builder(RuntimeCapability capability, QuaternaryServiceDescriptor requirement) { + return new DefaultBuilder<>(capability, requirement, QuaternaryCapabilityNameResolver.GREATGRANDPARENT_GRANDPARENT_PARENT_CHILD); + } + + interface Builder { + /** + * Only reference the provided capability if value of the specified attribute complies with the specified predicate. + * @param attribute an attribute of the resource to use for conditional registration + * @param predicate conditionally determines whether to require this capability, depending on the resolve value of the specified attribute + * @return a reference to this builder + */ + Builder when(AttributeDefinition attribute, Predicate predicate); + + /** + * Builds the configured capability reference recorder. + * @return a capability reference recorder + */ + org.wildfly.subsystem.resource.capability.ResourceCapabilityReferenceRecorder build(); } - static class Builder { + interface NaryBuilder extends Builder { + /** + * Overrides the default requirement name resolver. + * @param requirementNameResolver a capability name resolver + * @return a reference to this builder + */ + Builder withRequirementNameResolver(Function requirementNameResolver); + } + + static class DefaultBuilder implements NaryBuilder { private final RuntimeCapability capability; private final ServiceDescriptor requirement; - private final Function requirementNameResolver; + private Function requirementNameResolver; private BiPredicate predicate = ResourceCapabilityServiceDescriptorReference.ALWAYS; - Builder(RuntimeCapability capability, ServiceDescriptor requirement, Function requirementNameResolver) { + DefaultBuilder(RuntimeCapability capability, ServiceDescriptor requirement, Function defaultRequirementNameResolver) { this.capability = capability; this.requirement = requirement; + this.requirementNameResolver = defaultRequirementNameResolver; + } + + + @Override + public Builder withRequirementNameResolver(Function requirementNameResolver) { this.requirementNameResolver = requirementNameResolver; + return this; } - /** - * Only reference the provided capability if value of the specified attribute complies with the specified predicate. - * @param attribute an attribute of the resource to use for conditional registration - * @param predicate conditionally determines whether to require this capability, depending on the resolve value of the specified attribute - */ + @Override public Builder when(AttributeDefinition attribute, Predicate predicate) { this.predicate = new BiPredicate<>() { @Override @@ -133,10 +176,7 @@ public boolean test(OperationContext context, Resource resource) { return this; } - /** - * Builds the configured capability reference recorder. - * @return a capability reference recorder - */ + @Override public org.wildfly.subsystem.resource.capability.ResourceCapabilityReferenceRecorder build() { return new ResourceCapabilityServiceDescriptorReference<>(this.capability, this.requirement, this.requirementNameResolver, this.predicate); } @@ -194,23 +234,8 @@ public void removeCapabilityRequirements(OperationContext context, Resource reso } private String resolveRequirementName(OperationContext context) { - String[] parts = this.getRequirementNameResolver().apply(context.getCurrentAddress()); - return (parts.length > 0) ? RuntimeCapability.buildDynamicCapabilityName(this.getBaseRequirementName(), parts) : this.getBaseRequirementName(); - } - - static BiPredicate attributePredicate(AttributeDefinition attribute, Predicate predicate) { - return new BiPredicate<>() { - @Override - public boolean test(OperationContext context, Resource resource) { - try { - return predicate.test(attribute.resolveModelAttribute(context, resource.getModel())); - } catch (OperationFailedException e) { - // OFE would be due to an expression that can't be resolved right now (OperationContext.Stage.MODEL). - // Very unlikely an expression is used and that it uses a resolution source not available in MODEL. - return true; - } - } - }; + String[] segments = this.getRequirementNameResolver().apply(context.getCurrentAddress()); + return (segments.length > 0) ? RuntimeCapability.buildDynamicCapabilityName(this.getBaseRequirementName(), segments) : this.getBaseRequirementName(); } } }