Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WFCORE-6863 Add ServiceDescriptor convenience method for adding a requirement to a RuntimeCapability. #6046

Merged
merged 1 commit into from
Jun 25, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

package org.jboss.as.controller.capability;

import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.ServiceNameFactory;
Expand Down Expand Up @@ -133,22 +133,14 @@ private RuntimeCapability(Builder<T> builder) {
assert builder.baseName != null;
this.name = builder.baseName;
this.dynamic = builder.dynamic;
this.requirements = establishRequirements(builder.requirements);
this.requirements = builder.requirements;
this.dynamicNameMapper = Objects.requireNonNullElse(builder.dynamicNameMapper, UnaryCapabilityNameResolver.DEFAULT);
this.runtimeAPI = builder.runtimeAPI;
this.serviceValueType = builder.serviceValueType;
this.allowMultipleRegistrations = builder.allowMultipleRegistrations;
this.stability = builder.stability;
}

private static Set<String> establishRequirements(Set<String> input) {
if (input != null && !input.isEmpty()) {
return Set.copyOf(input);
} else {
return Collections.emptySet();
}
}

/**
* Constructor for use by {@link #fromBaseCapability(String...)}
*/
Expand All @@ -161,7 +153,7 @@ private RuntimeCapability(String baseName, Class<?> serviceValueType, ServiceNam
) {
this.name = buildDynamicCapabilityName(baseName, dynamicElement);
this.dynamic = false;
this.requirements = establishRequirements(requirements);
this.requirements = requirements;
this.dynamicNameMapper = Objects.requireNonNullElse(dynamicNameMapper, UnaryCapabilityNameResolver.DEFAULT);
this.runtimeAPI = runtimeAPI;
this.serviceValueType = serviceValueType;
Expand Down Expand Up @@ -321,8 +313,8 @@ public RuntimeCapability<T> fromBaseCapability(String ... dynamicElement) {
assert isDynamicallyNamed();
assert dynamicElement != null;
assert dynamicElement.length > 0;
return new RuntimeCapability<>(getName(), serviceValueType, getServiceName(), runtimeAPI,
getRequirements(), allowMultipleRegistrations,dynamicNameMapper, this.stability, dynamicElement);
return new RuntimeCapability<>(this.name, serviceValueType, getServiceName(), runtimeAPI,
this.requirements, allowMultipleRegistrations, dynamicNameMapper, this.stability, dynamicElement);

}

Expand All @@ -349,8 +341,8 @@ public RuntimeCapability<T> fromBaseCapability(PathAddress path) {
assert path != null;
String[] dynamicElement = dynamicNameMapper.apply(path);
assert dynamicElement.length > 0;
return new RuntimeCapability<>(getName(), serviceValueType, getServiceName(), runtimeAPI,
getRequirements(), allowMultipleRegistrations, dynamicNameMapper, this.stability, dynamicElement);
return new RuntimeCapability<>(this.name, serviceValueType, getServiceName(), runtimeAPI,
this.requirements, allowMultipleRegistrations, dynamicNameMapper, this.stability, dynamicElement);
}

@Override
Expand Down Expand Up @@ -420,7 +412,7 @@ public static class Builder<T> {
private final T runtimeAPI;
private final boolean dynamic;
private Class<?> serviceValueType;
private Set<String> requirements;
private Set<String> requirements = Set.of();
private boolean allowMultipleRegistrations = ALLOW_MULTIPLE;
private Function<PathAddress, String[]> dynamicNameMapper = UnaryCapabilityNameResolver.DEFAULT;
private Stability stability = Stability.DEFAULT;
Expand Down Expand Up @@ -562,13 +554,35 @@ public Builder<T> setServiceType(Class<?> type) {
*/
public Builder<T> addRequirements(String... requirements) {
assert requirements != null;
if (this.requirements == null) {
this.requirements = new HashSet<>(requirements.length);
if (requirements.length > 0) {
this.requirements = this.requirements.isEmpty() ? Set.of(requirements) : Stream.concat(this.requirements.stream(), Stream.of(requirements)).collect(Collectors.toUnmodifiableSet());
}
Collections.addAll(this.requirements, requirements);
return this;
}

/**
* Adds the names of other capabilities that this capability requires. The requirement
* for these capabilities will automatically be registered when this capability is registered.
*
* @param requirements the capability names
* @return the builder
*/
public Builder<T> addRequirements(NullaryServiceDescriptor<?>... requirements) {
assert requirements != null;
switch (requirements.length) {
case 0:
return this;
case 1:
return this.addRequirements(requirements[0].getName());
case 2:
return this.addRequirements(requirements[0].getName(), requirements[1].getName());
default:
Stream<String> mapped = Stream.of(requirements).map(NullaryServiceDescriptor::getName);
this.requirements = (this.requirements.isEmpty() ? mapped : Stream.concat(this.requirements.stream(), mapped)).collect(Collectors.toUnmodifiableSet());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this.requirements.isEmpty() is true, this.requirements should be assigned to an unmodificable Set, however Stream<String> mapped is not an unmodificable set at this point.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, out of curiosity, why not use the code for the default: case always and remove the need for a switch? I mean, why use case 1 and 2?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this.requirements.isEmpty() is true, this.requirements should be assigned to an unmodificable Set, however Stream mapped is not an unmodificable set at this point.

I'm not sure what you mean. Both cases use the same collector that returns an unmodifiable set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, out of curiosity, why not use the code for the default: case always and remove the need for a switch? I mean, why use case 1 and 2?

Because we want to avoid allocating a hash table for only 1 or 2 entries, if possible.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pferraro

I'm not sure what you mean. Both cases use the same collector that returns an unmodifiable set.

Forget it, I see it now, sorry for the noise about that.

return this;
}
}

/**
* Sets whether this capability can be registered at more than one point within the same
* overall scope.
Expand Down