下面列出了怎么用com.google.common.base.Verify的API类实例代码及写法,或者点击链接到github查看源代码。
final RangeConstraint<N> calculateRangeConstraint(final RangeConstraint<N> baseRangeConstraint) {
if (ranges == null) {
return baseRangeConstraint;
}
// Run through alternatives and resolve them against the base type
final RangeSet<N> baseRangeSet = baseRangeConstraint.getAllowedRanges();
Verify.verify(!baseRangeSet.isEmpty(), "Base type %s does not define constraints", getBaseType());
final Range<N> baseRange = baseRangeSet.span();
final List<ValueRange> resolvedRanges = ensureResolvedRanges(ranges, baseRange);
// Next up, ensure the of boundaries match base constraints
final RangeSet<N> typedRanges = ensureTypedRanges(resolvedRanges, baseRange.lowerEndpoint().getClass());
// Now verify if new ranges are strict subset of base ranges
if (!baseRangeSet.enclosesAll(typedRanges)) {
throw new InvalidRangeConstraintException(typedRanges,
"Range constraint %s is not a subset of parent constraint %s", typedRanges, baseRangeSet);
}
return new ResolvedRangeConstraint<>(constraint, typedRanges);
}
/**
* Finds the given environment in the given set and returns the default environments for its
* group.
*/
private static Collection<EnvironmentWithGroup> getDefaults(Label env,
EnvironmentCollection allEnvironments) {
EnvironmentLabels group = null;
for (EnvironmentLabels candidateGroup : allEnvironments.getGroups()) {
if (candidateGroup.getDefaults().contains(env)) {
group = candidateGroup;
break;
}
}
Verify.verifyNotNull(group);
ImmutableSet.Builder<EnvironmentWithGroup> builder = ImmutableSet.builder();
for (Label defaultEnv : group.getDefaults()) {
builder.add(EnvironmentWithGroup.create(defaultEnv, group));
}
return builder.build();
}
/**
* Classifies an identifier's case format.
*/
static JavaCaseFormat from(String name) {
Verify.verify(!name.isEmpty());
boolean firstUppercase = false;
boolean hasUppercase = false;
boolean hasLowercase = false;
boolean first = true;
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (!Character.isAlphabetic(c)) {
continue;
}
if (first) {
firstUppercase = Character.isUpperCase(c);
first = false;
}
hasUppercase |= Character.isUpperCase(c);
hasLowercase |= Character.isLowerCase(c);
}
if (firstUppercase) {
return hasLowercase ? UPPER_CAMEL : UPPERCASE;
} else {
return hasUppercase ? LOWER_CAMEL : LOWERCASE;
}
}
/**
* 释放连接
* @param channel
* @return
*/
public Future<Void> release(Channel channel) {
Verify.verifyNotNull(channel, "channel不允许为NULL");
InetSocketAddress remoteAddress = (InetSocketAddress)channel.remoteAddress();
if(logger.isDebugEnabled()) {
logger.debug("{} channel released", remoteAddress);
}
FixedChannelPool fixedChannelPool = pollMap.get(remoteAddress);
Future<Void> releaseFuture = fixedChannelPool.release(channel);
if(!releaseFuture.isSuccess()) {
Throwable cause = releaseFuture.cause();
if(cause != null) {
logger.error("rlease local channel {}, remote channel {}, happens error {}", channel.localAddress(),
channel.remoteAddress(), ExceptionUtils.getStackTrace(releaseFuture.cause()));
}
}
return releaseFuture;
}
@SuppressWarnings("UnstableApiUsage")
@Nonnull
@Override
public PlannerGraph rewritePlannerGraph(@Nonnull List<? extends PlannerGraph> childGraphs) {
Verify.verify(childGraphs.isEmpty());
final PlannerGraph.DataNodeWithInfo dataNodeWithInfo;
dataNodeWithInfo = new PlannerGraph.DataNodeWithInfo(NodeInfo.BASE_DATA,
ImmutableList.of("record types: {{types}}"),
ImmutableMap.of("types", Attribute.gml(getRecordTypes().stream().map(Attribute::gml).collect(ImmutableList.toImmutableList()))));
return PlannerGraph.fromNodeAndChildGraphs(
new PlannerGraph.LogicalOperatorNodeWithInfo(this,
NodeInfo.SCAN_OPERATOR,
ImmutableList.of(),
ImmutableMap.of()),
ImmutableList.of(PlannerGraph.fromNodeAndChildGraphs(
dataNodeWithInfo,
childGraphs)));
}
private void validateGcsFiles(
ProcessContext c, String table, TableManifest manifest) {
org.apache.beam.sdk.extensions.gcp.util.GcsUtil gcsUtil =
c.getPipelineOptions().as(GcsOptions.class).getGcsUtil();
// Convert file names to GcsPaths.
List<GcsPath> gcsPaths =
Lists.transform(
manifest.getFilesList(),
f -> GcsPath.fromUri(importDirectory.get()).resolve(f.getName()));
List<String> checksums = FileChecksum.getGcsFileChecksums(gcsUtil, gcsPaths);
for (int i = 0; i < gcsPaths.size(); i++) {
GcsPath path = gcsPaths.get(i);
String fileName = gcsPaths.get(i).getFileName().getObject();
String expectedHash = manifest.getFiles(i).getMd5();
String actualHash = checksums.get(i);
Verify.verify(
expectedHash.equals(actualHash),
"Inconsistent file: %s expected hash %s actual hash %s",
fileName,
expectedHash,
actualHash);
c.output(KV.of(table, path.toString()));
}
}
/**
* Classifies an identifier's case format.
*/
static JavaCaseFormat from(String name) {
Verify.verify(!name.isEmpty());
boolean firstUppercase = false;
boolean hasUppercase = false;
boolean hasLowercase = false;
boolean first = true;
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (!Character.isAlphabetic(c)) {
continue;
}
if (first) {
firstUppercase = Character.isUpperCase(c);
first = false;
}
hasUppercase |= Character.isUpperCase(c);
hasLowercase |= Character.isLowerCase(c);
}
if (firstUppercase) {
return hasLowercase ? UPPER_CAMEL : UPPERCASE;
} else {
return hasUppercase ? LOWER_CAMEL : LOWERCASE;
}
}
public static <T> void registerService(
ComponentManager componentManager,
Class<T> key,
T implementation,
Disposable parentDisposable) {
@SuppressWarnings({"rawtypes", "unchecked"}) // #api193: wildcard generics added in 2020.1
List<? extends IdeaPluginDescriptor> loadedPlugins = (List) PluginManager.getLoadedPlugins();
Optional<? extends IdeaPluginDescriptor> platformPlugin =
loadedPlugins.stream()
.filter(descriptor -> descriptor.getName().startsWith("IDEA CORE"))
.findAny();
Verify.verify(platformPlugin.isPresent());
((ComponentManagerImpl) componentManager)
.registerServiceInstance(key, implementation, platformPlugin.get());
}
@Override
public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviourWithListeners<K, V, N> getNamespaceBehaviour(
final Class<N> type) {
NamespaceBehaviourWithListeners<?, ?, ?> potential = supportedNamespaces.get(type);
if (potential == null) {
final NamespaceBehaviour<K, V, N> potentialRaw = supports.get(currentPhase).getNamespaceBehaviour(type);
if (potentialRaw != null) {
potential = createNamespaceContext(potentialRaw);
supportedNamespaces.put(type, potential);
} else {
throw new NamespaceNotAvailableException("Namespace " + type + " is not available in phase "
+ currentPhase);
}
}
Verify.verify(type.equals(potential.getIdentifier()));
/*
* Safe cast, previous checkState checks equivalence of key from which
* type argument are derived
*/
return (NamespaceBehaviourWithListeners<K, V, N>) potential;
}
/**
* Returns a list of commits between two references.
*
* @param repoPath path to local git repository.
* @param startRef start reference.
* @param endRef end reference.
* @return a list of commits.
* @throws IOException if I/O error occurs.
* @throws GitAPIException if an error occurs when accessing Git API.
*/
private static Set<RevCommit> getCommitsBetweenReferences(String repoPath, String startRef,
String endRef) throws IOException, GitAPIException {
final FileRepositoryBuilder builder = new FileRepositoryBuilder();
final Path path = Paths.get(repoPath);
final Repository repo = builder.findGitDir(path.toFile()).readEnvironment().build();
final ObjectId startCommit = getActualRefObjectId(repo, startRef);
Verify.verifyNotNull(startCommit, "Start reference \"" + startRef + "\" is invalid!");
final ObjectId endCommit = getActualRefObjectId(repo, endRef);
final Iterable<RevCommit> commits =
new Git(repo).log().addRange(startCommit, endCommit).call();
return Sets.newLinkedHashSet(commits);
}
/**
* This is more advanced and does not make use of the stub. You should not normally need to do
* this, but here is how you would.
*/
void advancedAsyncCall() {
ClientCall<HelloRequest, HelloReply> call =
channel.newCall(GreeterGrpc.getSayHelloMethod(), CallOptions.DEFAULT);
final CountDownLatch latch = new CountDownLatch(1);
call.start(new ClientCall.Listener<HelloReply>() {
@Override
public void onClose(Status status, Metadata trailers) {
Verify.verify(status.getCode() == Status.Code.INTERNAL);
Verify.verify(status.getDescription().contains("Narwhal"));
// Cause is not transmitted over the wire.
latch.countDown();
}
}, new Metadata());
call.sendMessage(HelloRequest.newBuilder().setName("Marge").build());
call.halfClose();
if (!Uninterruptibles.awaitUninterruptibly(latch, 1, TimeUnit.SECONDS)) {
throw new RuntimeException("timeout!");
}
}
static <K, V> V[] adjustedArray(final Map<K, Integer> offsets, final List<K> keys, final V[] array) {
Verify.verify(offsets.size() == keys.size(), "Offsets %s do not match keys %s", offsets, keys);
// This relies on the fact that offsets has an ascending iterator
final Iterator<K> oi = offsets.keySet().iterator();
final Iterator<K> ki = keys.iterator();
while (oi.hasNext()) {
final K o = oi.next();
final K k = ki.next();
if (!k.equals(o)) {
return adjustArray(offsets, keys, array);
}
}
return array;
}
private void enforceCases(final NormalizedNode<?, ?> normalizedNode) {
Verify.verify(normalizedNode instanceof ChoiceNode);
final Collection<DataContainerChild<?, ?>> children = ((ChoiceNode) normalizedNode).getValue();
if (!children.isEmpty()) {
final DataContainerChild<?, ?> firstChild = children.iterator().next();
final CaseEnforcer enforcer = Verify.verifyNotNull(caseEnforcers.get(firstChild.getIdentifier()),
"Case enforcer cannot be null. Most probably, child node %s of choice node %s does not belong "
+ "in current tree type.", firstChild.getIdentifier(), normalizedNode.getIdentifier());
// Make sure no leaves from other cases are present
for (final CaseEnforcer other : exclusions.get(enforcer)) {
for (final PathArgument id : other.getAllChildIdentifiers()) {
final Optional<NormalizedNode<?, ?>> maybeChild = NormalizedNodes.getDirectChild(normalizedNode,
id);
Preconditions.checkArgument(!maybeChild.isPresent(),
"Child %s (from case %s) implies non-presence of child %s (from case %s), which is %s",
firstChild.getIdentifier(), enforcer, id, other, maybeChild.orElse(null));
}
}
// Make sure all mandatory children are present
enforcer.enforceOnTreeNode(normalizedNode);
}
}
void futureCallCallback() {
GreeterFutureStub stub = GreeterGrpc.newFutureStub(channel);
ListenableFuture<HelloReply> response =
stub.sayHello(HelloRequest.newBuilder().setName("Maggie").build());
final CountDownLatch latch = new CountDownLatch(1);
Futures.addCallback(
response,
new FutureCallback<HelloReply>() {
@Override
public void onSuccess(@Nullable HelloReply result) {
// Won't be called, since the server in this example always fails.
}
@Override
public void onFailure(Throwable t) {
Status status = Status.fromThrowable(t);
Verify.verify(status.getCode() == Status.Code.INTERNAL);
Verify.verify(status.getDescription().contains("Crybaby"));
// Cause is not transmitted over the wire..
latch.countDown();
}
},
directExecutor());
if (!Uninterruptibles.awaitUninterruptibly(latch, 1, TimeUnit.SECONDS)) {
throw new RuntimeException("timeout!");
}
}
/**
* Checks whether the {@code traversal}'s path refers to a package directory.
*
* @return the result of the lookup; it contains potentially new {@link TraversalRequest} and
* {@link FileInfo} so the caller should use these instead of the old ones (this happens when
* a package is found, but under a different root than expected)
*/
private static PkgLookupResult checkIfPackage(
Environment env, TraversalRequest traversal, FileInfo rootInfo)
throws MissingDepException, IOException, InterruptedException {
Preconditions.checkArgument(rootInfo.type.exists() && !rootInfo.type.isFile(),
"{%s} {%s}", traversal, rootInfo);
PackageLookupValue pkgLookup =
(PackageLookupValue)
getDependentSkyValue(env,
PackageLookupValue.key(traversal.root.asRootedPath().getRootRelativePath()));
if (pkgLookup.packageExists()) {
if (traversal.isRootGenerated) {
// The traversal's root was a generated directory, but its root-relative path conflicts with
// an existing package.
return PkgLookupResult.conflict(traversal, rootInfo);
} else {
// The traversal's root was a source directory and it defines a package.
Root pkgRoot = pkgLookup.getRoot();
if (!pkgRoot.equals(traversal.root.asRootedPath().getRoot())) {
// However the root of this package is different from what we expected. stat() the real
// BUILD file of that package.
traversal = traversal.forChangedRootPath(pkgRoot);
rootInfo = lookUpFileInfo(env, traversal);
Verify.verify(rootInfo.type.exists(), "{%s} {%s}", traversal, rootInfo);
}
return PkgLookupResult.pkg(traversal, rootInfo);
}
} else {
// The traversal's root was a directory (source or generated one), no package exists under the
// same root-relative path.
return PkgLookupResult.directory(traversal, rootInfo);
}
}
static void verifyErrorReply(Throwable t) {
Status status = Status.fromThrowable(t);
Metadata trailers = Status.trailersFromThrowable(t);
Verify.verify(status.getCode() == Status.Code.INTERNAL);
Verify.verify(trailers.containsKey(DEBUG_INFO_TRAILER_KEY));
Verify.verify(status.getDescription().equals(DEBUG_DESC));
try {
Verify.verify(trailers.get(DEBUG_INFO_TRAILER_KEY).equals(DEBUG_INFO));
} catch (IllegalArgumentException e) {
throw new VerifyException(e);
}
}
/**
* This is more advanced and does not make use of the stub. You should not normally need to do
* this, but here is how you would.
*/
void advancedAsyncCall() {
ClientCall<HelloRequest, HelloReply> call =
channel.newCall(GreeterGrpc.getSayHelloMethod(), CallOptions.DEFAULT);
final CountDownLatch latch = new CountDownLatch(1);
call.start(new ClientCall.Listener<HelloReply>() {
@Override
public void onClose(Status status, Metadata trailers) {
Verify.verify(status.getCode() == Status.Code.INTERNAL);
Verify.verify(trailers.containsKey(DEBUG_INFO_TRAILER_KEY));
try {
Verify.verify(trailers.get(DEBUG_INFO_TRAILER_KEY).equals(DEBUG_INFO));
} catch (IllegalArgumentException e) {
throw new VerifyException(e);
}
latch.countDown();
}
}, new Metadata());
call.sendMessage(HelloRequest.newBuilder().build());
call.halfClose();
if (!Uninterruptibles.awaitUninterruptibly(latch, 1, TimeUnit.SECONDS)) {
throw new RuntimeException("timeout!");
}
}
private void visitAnnotatedArrayType(Tree node) {
TypeWithDims extractedDims = DimensionHelpers.extractDims(node, SortedDims.YES);
builder.open(plusFour);
scan(extractedDims.node, null);
Deque<List<AnnotationTree>> dims = new ArrayDeque<>(extractedDims.dims);
maybeAddDims(dims);
Verify.verify(dims.isEmpty());
builder.close();
}
@Override
public Optional<? extends XPathResult<?>> evaluate(final XPathDocument document,
final YangInstanceIdentifier path) throws XPathExpressionException {
checkArgument(document instanceof JaxenDocument);
final NormalizedNodeContextSupport contextSupport = NormalizedNodeContextSupport.create(
(JaxenDocument)document, converter);
final Object result = evaluate(contextSupport.createContext(path));
if (result instanceof String) {
return Optional.of((XPathStringResult) () -> (String) result);
} else if (result instanceof Number) {
return Optional.of((XPathNumberResult) () -> (Number) result);
} else if (result instanceof Boolean) {
return Optional.of((XPathBooleanResult) () -> (Boolean) result);
} else if (result == null) {
return Optional.empty();
}
Verify.verify(result instanceof List, "Unhandled result %s", result);
@SuppressWarnings("unchecked")
final List<NormalizedNodeContext> resultList = (List<NormalizedNodeContext>) result;
return Optional.of((XPathNodesetResult) () -> {
// XXX: Will this really work, or do we need to perform deep transformation?
return Lists.transform(resultList,
context -> new SimpleImmutableEntry<>(context.getPath(), context.getNode()));
});
}
private static Bootstrap initBootStrap() {
Bootstrap cb = new Bootstrap();
Verify.verifyNotNull(cb);
cb.group(ApplicationRuntime.FTDC_LOOP_GROUP);
cb.channel(NioSocketChannel.class);
cb.option(ChannelOption.SO_KEEPALIVE, false);
return cb;
}
@Override
public void onRspError(RspError error, int reqId) {
UserSession session = session();
if (session == null) {
logger.error(LOGGR_TEMPLATE_ERROR, reqId);
return;
}
RequestIdentity requestIdentity = ApplicationRuntime.unbindRequestIdentity(session.getBrokerId(),
session.getUserID(), reqId);
Verify.verifyNotNull(requestIdentity, VERIFY_TEMPLATE, requestIdentity);
doRspError(requestIdentity, error);
}
private RequestIdentity getRequestIdentity(int reqId, boolean isLast, String brokerId, String userid) {
RequestIdentity requestIdentity;
if (isLast) {
requestIdentity = ApplicationRuntime.unbindRequestIdentity(brokerId, userid, reqId);
} else {
requestIdentity = ApplicationRuntime.getRequestIdentity(brokerId, userid, reqId);
}
Verify.verifyNotNull(requestIdentity, VERIFY_TEMPLATE, requestIdentity, reqId, brokerId, userid);
return requestIdentity;
}
static void verifyErrorReply(Throwable t) {
Status status = Status.fromThrowable(t);
Metadata trailers = Status.trailersFromThrowable(t);
Verify.verify(status.getCode() == Status.Code.INTERNAL);
Verify.verify(trailers.containsKey(DEBUG_INFO_TRAILER_KEY));
Verify.verify(status.getDescription().equals(DEBUG_DESC));
try {
Verify.verify(trailers.get(DEBUG_INFO_TRAILER_KEY).equals(DEBUG_INFO));
} catch (IllegalArgumentException e) {
throw new VerifyException(e);
}
}
/**
* Expand a SetValue flag policy on a repeatable flag. SetValue operations are the only flag
* policies that set the flag, and so interact with repeatable flags, flags that can be set
* multiple times, in subtle ways.
*
* @param subflagDesc, the description of the flag the SetValue'd expansion flag expands to.
* @param subflagValue, the values that the SetValue'd expansion flag expands to for this flag.
* @param originalPolicy, the original policy on the expansion flag.
* @return the flag policy for the subflag given, this will be part of the expanded form of the
* SetValue policy on the original flag.
*/
private static FlagPolicyWithContext getSetValueSubflagAsPolicy(
OptionDescription subflagDesc,
List<String> subflagValue,
OptionInstanceOrigin subflagOrigin,
FlagPolicyWithContext originalPolicy) {
// Some sanity checks.
OptionDefinition subflag = subflagDesc.getOptionDefinition();
Verify.verify(originalPolicy.policy.getOperationCase().equals(OperationCase.SET_VALUE));
if (!subflag.allowsMultiple()) {
Verify.verify(subflagValue.size() <= 1);
}
// Flag value from the expansion, overridability from the original policy, unless the flag is
// repeatable, in which case we care about appendability, not overridability.
SetValue.Builder setValueExpansion = SetValue.newBuilder();
for (String value : subflagValue) {
setValueExpansion.addFlagValue(value);
}
if (subflag.allowsMultiple()) {
setValueExpansion.setAppend(originalPolicy.policy.getSetValue().getOverridable());
} else {
setValueExpansion.setOverridable(originalPolicy.policy.getSetValue().getOverridable());
}
// Commands from the original policy, flag name of the expansion
return new FlagPolicyWithContext(
FlagPolicy.newBuilder()
.addAllCommands(originalPolicy.policy.getCommandsList())
.setFlagName(subflag.getOptionName())
.setSetValue(setValueExpansion)
.build(),
subflagDesc,
subflagOrigin);
}
void blockingCall() {
GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);
try {
stub.sayHello(HelloRequest.newBuilder().setName("Bart").build());
} catch (Exception e) {
Status status = Status.fromThrowable(e);
Verify.verify(status.getCode() == Status.Code.INTERNAL);
Verify.verify(status.getDescription().contains("Eggplant"));
// Cause is not transmitted over the wire.
}
}
/**
* Rewrite the planner graph for better visualization of a query index plan.
* @return the rewritten planner graph that models the index as a separate node that is connected to the
* actual index scan plan node.
*/
@Nonnull
@Override
public PlannerGraph rewritePlannerGraph(@Nonnull final List<? extends PlannerGraph> childGraphs) {
Verify.verify(childGraphs.isEmpty());
return createIndexPlannerGraph(this,
NodeInfo.TEXT_INDEX_SCAN_OPERATOR,
ImmutableList.of(),
ImmutableMap.of());
}
@Nonnull
private static GraphExporter<PlannerGraph.Node, PlannerGraph.Edge> createDotExporter() {
final ClusterProvider<PlannerGraph.Node, PlannerGraph.Edge> clusterProvider =
n -> n.nodes()
.stream()
.filter(node -> node instanceof PlannerGraph.ExpressionRefHeadNode || node instanceof PlannerGraph.ExpressionRefMemberNode)
.collect(Collectors.groupingBy(node -> {
if (node instanceof PlannerGraph.ExpressionRefHeadNode) {
return node;
}
if (node instanceof PlannerGraph.ExpressionRefMemberNode) {
final PlannerGraph.Node head =
n.incidentNodes(Iterables.getOnlyElement(n.outEdges(node)))
.nodeV();
Verify.verify(head instanceof PlannerGraph.ExpressionRefHeadNode);
return head;
}
throw new IllegalArgumentException("impossible case");
}, Collectors.toSet()));
final ComponentAttributeProvider<PlannerGraph.Node> clusterAttributeProvider =
node -> ImmutableMap.<String, Attribute>builder()
.put("style", Attribute.dot("filled"))
.put("fillcolor", Attribute.dot("lightgrey"))
.put("fontsize", Attribute.dot("6"))
.put("rank", Attribute.dot("same"))
.put("label", Attribute.dot("group"))
.build();
return new DotExporter<>(new CountingIdProvider<>(),
PlannerGraph.Node::getAttributes,
PlannerGraph.Edge::getAttributes,
ImmutableMap.of("fontname", Attribute.dot("courier"),
"rankdir", Attribute.dot("BT")),
clusterProvider,
clusterAttributeProvider);
}
private void validateLocalFiles(ProcessContext c, String table, TableManifest manifest) {
for (TableManifest.File file : manifest.getFilesList()) {
Path filePath = Paths.get(importDirectory.get(), file.getName());
String actualHash = FileChecksum.getLocalFileChecksum(filePath);
String expectedHash = file.getMd5();
Verify.verify(
expectedHash.equals(actualHash),
"Inconsistent file: %s expected hash %s actual hash %s",
filePath,
expectedHash,
actualHash);
c.output(KV.of(table, filePath.toString()));
}
}
private static void verifyNameIsUnique(Set<TypeName> seenNames, TypeName name) {
boolean isNewName = seenNames.add(name);
Verify.verify(
isNewName,
"Type, error, and service names must be unique across locally defined and imported "
+ "types/errors: %s\n%s",
seenNames,
name);
}
@Override
public Class<? extends TransitiveInfoProvider> load(
Class<? extends TransitiveInfoProvider> providerClass) {
Set<Class<? extends TransitiveInfoProvider>> result =
getDirectImplementations(providerClass);
Verify.verify(!result.isEmpty()); // impossible
Preconditions.checkState(
result.size() == 1,
"Effective provider class for %s is ambiguous (%s), specify explicitly.",
providerClass,
Joiner.on(',').join(result));
return result.iterator().next();
}