/*
* Copyright Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ehcache.core.internal.store;
import org.ehcache.config.ResourceType;
import org.ehcache.core.internal.service.ServiceLocator;
import org.ehcache.core.spi.store.Store;
import org.ehcache.spi.service.ServiceProvider;
import org.ehcache.spi.service.Service;
import org.ehcache.spi.service.ServiceConfiguration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Defines methods supporting working with {@link Store} implementations.
*/
public final class StoreSupport {
/**
* Private, niladic constructor to prevent instantiation.
*/
private StoreSupport() {
}
/**
* Chooses a {@link org.ehcache.core.spi.store.Store.Provider Store.Provider} from those
* available through the {@link ServiceLocator} that best supports the resource types and
* service configurations provided. This method relies on the
* {@link Store.Provider#rank(Set, Collection) Store.Provider.rank} method in making the
* selection.
*
* @param serviceProvider the {@code ServiceProvider} instance to use
* @param resourceTypes the set of {@code ResourceType}s that must be supported by the provider
* @param serviceConfigs the collection of {@code ServiceConfiguration}s used to influence the
* selection
*
* @return the non-{@code null} {@code Store.Provider} implementation chosen
*
* @throws IllegalStateException if no suitable {@code Store.Provider} is available or if
* multiple {@code Store.Provider} implementations return the same top ranking
*/
public static Store.Provider selectStoreProvider(
final ServiceProvider<Service> serviceProvider, final Set<ResourceType<?>> resourceTypes, final Collection<ServiceConfiguration<?>> serviceConfigs) {
final Collection<Store.Provider> storeProviders = serviceProvider.getServicesOfType(Store.Provider.class);
int highRank = 0;
List<Store.Provider> rankingProviders = new ArrayList<Store.Provider>();
for (final Store.Provider provider : storeProviders) {
int rank = provider.rank(resourceTypes, serviceConfigs);
if (rank > highRank) {
highRank = rank;
rankingProviders.clear();
rankingProviders.add(provider);
} else if (rank != 0 && rank == highRank) {
rankingProviders.add(provider);
}
}
if (rankingProviders.isEmpty()) {
final StringBuilder sb = new StringBuilder("No Store.Provider found to handle configured resource types ");
sb.append(resourceTypes);
sb.append(" from ");
formatStoreProviders(storeProviders, sb);
throw new IllegalStateException(sb.toString());
} else if (rankingProviders.size() > 1) {
final StringBuilder sb = new StringBuilder("Multiple Store.Providers found to handle configured resource types ");
sb.append(resourceTypes);
sb.append(": ");
formatStoreProviders(rankingProviders, sb);
throw new IllegalStateException(sb.toString());
}
return rankingProviders.get(0);
}
private static StringBuilder formatStoreProviders(final Collection<Store.Provider> storeProviders, final StringBuilder sb) {
sb.append('{');
boolean prependSeparator = false;
for (final Store.Provider provider : storeProviders) {
if (prependSeparator) {
sb.append(", ");
} else {
prependSeparator = true;
}
sb.append(provider.getClass().getName());
}
sb.append('}');
return sb;
}
}