Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.sportradar.unifiedodds.sdk.caching.impl.ci.CompetitorCIImpl Maven / Gradle / Ivy
/*
* Copyright (C) Sportradar AG. See LICENSE for full license governing this code
*/
package com.sportradar.unifiedodds.sdk.caching.impl.ci;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.sportradar.uf.sportsapi.datamodel.*;
import com.sportradar.unifiedodds.sdk.ExceptionHandlingStrategy;
import com.sportradar.unifiedodds.sdk.caching.CompetitorCI;
import com.sportradar.unifiedodds.sdk.caching.DataRouterManager;
import com.sportradar.unifiedodds.sdk.caching.ci.JerseyCI;
import com.sportradar.unifiedodds.sdk.caching.ci.ManagerCI;
import com.sportradar.unifiedodds.sdk.caching.ci.ReferenceIdCI;
import com.sportradar.unifiedodds.sdk.caching.ci.VenueCI;
import com.sportradar.unifiedodds.sdk.exceptions.ObjectNotFoundException;
import com.sportradar.unifiedodds.sdk.exceptions.internal.CommunicationException;
import com.sportradar.unifiedodds.sdk.exceptions.internal.DataRouterStreamException;
import com.sportradar.unifiedodds.sdk.impl.UnifiedFeedConstants;
import com.sportradar.utils.SdkHelper;
import com.sportradar.utils.URN;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
/**
* An implementation of the {@link CompetitorCI}
*/
class CompetitorCIImpl implements CompetitorCI {
private static final Logger logger = LoggerFactory.getLogger(CompetitorCIImpl.class);
/**
* An {@link URN} specifying the id of the associated sport event
*/
private final URN id;
/**
* A {@link Locale} specifying the default language
*/
private final Locale defaultLocale;
/**
* The {@link DataRouterManager} which is used to trigger data fetches
*/
private final DataRouterManager dataRouterManager;
/**
* An indication on how should be the SDK exceptions handled
*/
private final ExceptionHandlingStrategy exceptionHandlingStrategy;
/**
* A {@link Map} containing competitor names in different languages
*/
private final Map names = Maps.newConcurrentMap();
/**
* A {@link Map} containing competitor's country name in different languages
*/
private final Map countryNames = Maps.newConcurrentMap();
/**
* A {@link Map} containing competitor abbreviations in different languages
*/
private final Map abbreviations = Maps.newConcurrentMap();
/**
* A value indicating whether represented competitor is virtual
*/
private boolean isVirtual;
/**
* A {@link String} representation of a country code
*/
private String countryCode;
/**
* The reference ids associated with the current instance
*/
private ReferenceIdCI referenceId;
/**
* A {@link List} of associated player {@link URN}s
*/
private List associatedPlayerIds;
/**
* A {@link List} of known competitor jerseys
*/
private List jerseys;
/**
* The associated competitor manager
*/
private ManagerCI manager;
/**
* The associated competitor home venue
*/
private VenueCI venue;
/**
* The locales which are merged into the CI
*/
private final List cachedLocales = Collections.synchronizedList(new ArrayList<>());
private final ReentrantLock fetchLock = new ReentrantLock();
CompetitorCIImpl(URN id, DataRouterManager dataRouterManager, Locale defaultLocale, ExceptionHandlingStrategy exceptionHandlingStrategy) {
Preconditions.checkNotNull(id);
Preconditions.checkNotNull(dataRouterManager);
Preconditions.checkNotNull(defaultLocale);
Preconditions.checkNotNull(exceptionHandlingStrategy);
this.id = id;
this.defaultLocale = defaultLocale;
this.dataRouterManager = dataRouterManager;
this.exceptionHandlingStrategy = exceptionHandlingStrategy;
}
CompetitorCIImpl(URN id, DataRouterManager dataRouterManager, Locale defaultLocale, ExceptionHandlingStrategy exceptionHandlingStrategy, SAPICompetitorProfileEndpoint data, Locale dataLocale) {
this(id, dataRouterManager, defaultLocale, exceptionHandlingStrategy);
merge(data, dataLocale);
}
CompetitorCIImpl(URN id, DataRouterManager dataRouterManager, Locale defaultLocale, ExceptionHandlingStrategy exceptionHandlingStrategy, SAPITeam data, Locale dataLocale) {
this(id, dataRouterManager, defaultLocale, exceptionHandlingStrategy);
merge(data, dataLocale);
}
CompetitorCIImpl(URN id, DataRouterManager dataRouterManager, Locale defaultLocale, ExceptionHandlingStrategy exceptionHandlingStrategy, SAPIPlayerCompetitor data, Locale dataLocale) {
this(id, dataRouterManager, defaultLocale, exceptionHandlingStrategy);
merge(data, dataLocale);
}
CompetitorCIImpl(URN id, DataRouterManager dataRouterManager, Locale defaultLocale, ExceptionHandlingStrategy exceptionHandlingStrategy, SAPISimpleTeamProfileEndpoint data, Locale dataLocale) {
this(id, dataRouterManager, defaultLocale, exceptionHandlingStrategy);
merge(data, dataLocale);
}
/**
* Returns the {@link URN} representing id of the related entity
*
* @return the {@link URN} representing id of the related entity
*/
@Override
public URN getId() {
return id;
}
/**
* Returns the {@link Map} containing translated names of the competitor
*
* @param locales a {@link List} specifying the required languages
* @return the {@link Map} containing translated names of the competitor
*/
@Override
public Map getNames(List locales) {
if (names.keySet().containsAll(locales)) {
return ImmutableMap.copyOf(names);
}
if (cachedLocales.containsAll(locales)) {
return ImmutableMap.copyOf(names);
}
requestMissingCompetitorData(locales);
return ImmutableMap.copyOf(names);
}
/**
* Returns the {@link Map} containing translated country names
*
* @param locales a {@link List} specifying the required languages
* @return the {@link Map} containing translated country names
*/
@Override
public Map getCountryNames(List locales) {
if (countryNames.keySet().containsAll(locales)) {
return ImmutableMap.copyOf(countryNames);
}
if (cachedLocales.containsAll(locales)) {
return ImmutableMap.copyOf(countryNames);
}
requestMissingCompetitorData(locales);
return ImmutableMap.copyOf(countryNames);
}
/**
* Returns the {@link Map} containing translated competitor abbreviations
*
* @param locales a {@link List} specifying the required languages
* @return the {@link Map} containing translated competitor abbreviations
*/
@Override
public Map getAbbreviations(List locales) {
if (abbreviations.keySet().containsAll(locales)) {
return ImmutableMap.copyOf(abbreviations);
}
if (cachedLocales.containsAll(locales)) {
return ImmutableMap.copyOf(abbreviations);
}
requestMissingCompetitorData(locales);
return ImmutableMap.copyOf(abbreviations);
}
/**
* Returns a value indicating whether represented competitor is virtual
*
* @return - a value indicating whether represented competitor is virtual
*/
@Override
public boolean isVirtual() {
ensureDataLoaded(isVirtual);
return isVirtual;
}
/**
* Returns a {@link String} representation of a country code
*
* @return - a {@link String} representation of a country code
*/
@Override
public String getCountryCode() {
ensureDataLoaded(countryCode);
return countryCode;
}
/**
* Returns the reference ids associated with the current instance
*
* @return - the reference ids associated with the current instance
*/
@Override
public ReferenceIdCI getReferenceId() {
ensureDataLoaded(referenceId);
return referenceId;
}
/**
* Returns a {@link List} of associated player ids
*
* @param locales the locales in which the players data should be pre-fetched
* @return {@link List} of associated player ids
*/
@Override
public List getAssociatedPlayerIds(List locales) {
if (cachedLocales.containsAll(locales)) {
return associatedPlayerIds == null ? null : ImmutableList.copyOf(associatedPlayerIds);
}
requestMissingCompetitorData(locales);
return associatedPlayerIds == null ? null : ImmutableList.copyOf(associatedPlayerIds);
}
/**
* Returns a {@link List} of known competitor jerseys
*
* @return {@link List} of known competitor jerseys
*/
@Override
public List getJerseys() {
ensureDataLoaded(jerseys);
return jerseys;
}
/**
* Returns the associated competitor manager
*
* @param locales the locales in which the data should be translated
* @return the associated competitor manager
*/
@Override
public ManagerCI getManager(List locales) {
if (manager != null && manager.hasTranslationsFor(locales)) {
return manager;
}
if (cachedLocales.containsAll(locales)) {
return manager;
}
requestMissingCompetitorData(locales);
return manager;
}
/**
* Return the associated competitor home venue
*
* @param locales the locales in which the data should be translated
* @return the associated competitor home venue
*/
@Override
public VenueCI getVenue(List locales) {
if (venue != null && venue.hasTranslationsFor(locales)) {
return venue;
}
if (cachedLocales.containsAll(locales)) {
return venue;
}
requestMissingCompetitorData(locales);
return venue;
}
/**
* Determines whether the current instance has translations for the specified languages
*
* @param localeList a {@link List} specifying the required languages
* @return true
if the current instance contains data in the required locals, otherwise false
.
*/
@Override
public boolean hasTranslationsLoadedFor(List localeList) {
return false;
}
@Override
public void merge(T endpointData, Locale dataLocale) {
if (endpointData instanceof SAPITeamCompetitor) {
internalMerge((SAPITeamCompetitor) endpointData, dataLocale);
} else if (endpointData instanceof SAPITeam) {
internalMerge((SAPITeam) endpointData, dataLocale);
} else if (endpointData instanceof SAPICompetitorProfileEndpoint) {
internalMerge((SAPICompetitorProfileEndpoint) endpointData, dataLocale);
cachedLocales.add(dataLocale);
} else if (endpointData instanceof SAPIPlayerCompetitor) {
internalMerge((SAPIPlayerCompetitor) endpointData, dataLocale);
} else if (endpointData instanceof SAPISimpleTeamProfileEndpoint) {
internalMerge((SAPISimpleTeamProfileEndpoint) endpointData, dataLocale);
cachedLocales.add(dataLocale);
}
}
private void internalMerge(SAPITeamCompetitor data, Locale dataLocale) {
Preconditions.checkNotNull(data);
Preconditions.checkNotNull(dataLocale);
internalMerge((SAPITeam) data, dataLocale);
}
private void internalMerge(SAPICompetitorProfileEndpoint data, Locale dataLocale) {
Preconditions.checkNotNull(data);
Preconditions.checkNotNull(dataLocale);
internalMerge(data.getCompetitor(), dataLocale);
associatedPlayerIds = Optional.ofNullable(data.getPlayers())
.map(p -> p.getPlayer().stream().map(pp -> URN.parse(pp.getId())).collect(Collectors.toList()))
.orElse(null);
jerseys = Optional.ofNullable(data.getJerseys())
.map(j -> j.getJersey().stream().map(JerseyCI::new).collect(Collectors.toList()))
.orElse(null);
if (data.getManager() != null) {
if (manager == null) {
manager = new ManagerCI(data.getManager(), dataLocale);
} else {
manager.merge(data.getManager(), dataLocale);
}
}
if (data.getVenue() != null){
if (venue == null) {
venue = new VenueCI(data.getVenue(), dataLocale);
} else {
venue.merge(data.getVenue(), dataLocale);
}
}
if (!abbreviations.keySet().contains(dataLocale)) {
if(data.getCompetitor().getAbbreviation() == null) {
abbreviations.put(dataLocale, SdkHelper.getAbbreviationFromName(data.getCompetitor().getName(), 3));
}
else {
abbreviations.put(dataLocale, data.getCompetitor().getAbbreviation());
}
}
}
private void internalMerge(SAPITeam competitor, Locale dataLocale) {
Preconditions.checkNotNull(competitor);
Preconditions.checkNotNull(dataLocale);
isVirtual = competitor.isVirtual() == null ? false : competitor.isVirtual();
countryCode = competitor.getCountryCode();
Optional.ofNullable(competitor.getName()).ifPresent(s -> names.put(dataLocale, s));
Optional.ofNullable(competitor.getCountry()).ifPresent(s -> countryNames.put(dataLocale, s));
Optional.ofNullable(competitor.getAbbreviation()).ifPresent(s -> abbreviations.put(dataLocale, s));
referenceId = competitor.getReferenceIds() == null ? null :
new ReferenceIdCI(competitor.getReferenceIds().getReferenceId().stream()
.filter(r -> r.getName() != null && r.getValue() != null)
.collect(HashMap::new, (map, i) -> map.put(i.getName(), i.getValue()), HashMap::putAll));
if (id.getType().equals(UnifiedFeedConstants.SIMPLETEAM_URN_TYPE) ||
id.toString().startsWith(UnifiedFeedConstants.OUTCOMETEXT_VARIANT_VALUE)) {
handleSimpleTeamReference();
}
if(competitor.getAbbreviation() == null) {
abbreviations.put(dataLocale, SdkHelper.getAbbreviationFromName(competitor.getName(), 3));
}
else {
abbreviations.put(dataLocale, competitor.getAbbreviation());
}
}
private void internalMerge(SAPIPlayerCompetitor competitor, Locale dataLocale) {
Preconditions.checkNotNull(competitor);
Preconditions.checkNotNull(dataLocale);
Optional.ofNullable(competitor.getName()).ifPresent(s -> names.put(dataLocale, s));
// Optional.ofNullable(competitor.getNationality()).ifPresent(s -> nat.put(dataLocale, s));
Optional.ofNullable(competitor.getAbbreviation()).ifPresent(s -> abbreviations.put(dataLocale, s));
if(competitor.getAbbreviation() == null) {
abbreviations.put(dataLocale, SdkHelper.getAbbreviationFromName(competitor.getName(), 3));
}
else {
abbreviations.put(dataLocale, competitor.getAbbreviation());
}
}
private void internalMerge(SAPISimpleTeamProfileEndpoint data, Locale dataLocale) {
Preconditions.checkNotNull(data);
Preconditions.checkNotNull(dataLocale);
internalMerge(data.getCompetitor(), dataLocale);
}
private void requestMissingCompetitorData(List requiredLocales) {
Preconditions.checkNotNull(requiredLocales);
List missingLocales = SdkHelper.findMissingLocales(cachedLocales, requiredLocales);
if (missingLocales.isEmpty()) {
return;
}
fetchLock.lock();
try {
// recheck missing locales after lock
missingLocales = SdkHelper.findMissingLocales(cachedLocales, requiredLocales);
if (missingLocales.isEmpty()) {
return;
}
logger.debug("Fetching competitor data for id='{}' for languages '{}'",
id, missingLocales.stream()
.map(Locale::getLanguage).collect(Collectors.joining(", ")));
missingLocales.forEach(l -> {
try {
if (id.getType().equals(UnifiedFeedConstants.SIMPLETEAM_URN_TYPE) ||
id.toString().startsWith(UnifiedFeedConstants.OUTCOMETEXT_VARIANT_VALUE)) {
dataRouterManager.requestSimpleTeamEndpoint(l, id, this);
} else {
dataRouterManager.requestCompetitorEndpoint(l, id, this);
}
} catch (CommunicationException e) {
throw new DataRouterStreamException(e.getMessage(), e);
}
});
} catch (DataRouterStreamException e) {
handleException(String.format("requestMissingCompetitorData(%s)", missingLocales), e);
} finally {
fetchLock.unlock();
}
}
private void handleSimpleTeamReference() {
if (referenceId != null && referenceId.getReferenceIds().containsKey("betradar")) {
return;
}
referenceId = new ReferenceIdCI(
ImmutableMap.builder()
.put("betradar", String.valueOf(id.getId()))
.putAll(referenceId != null ? referenceId.getReferenceIds() : ImmutableMap.of())
.build()
);
}
private void ensureDataLoaded(Object object) {
if (object != null || !cachedLocales.isEmpty()) {
return;
}
requestMissingCompetitorData(Collections.singletonList(defaultLocale));
}
private void handleException(String request, Exception e) {
if (exceptionHandlingStrategy == ExceptionHandlingStrategy.Throw) {
if (e == null) {
throw new ObjectNotFoundException("CompetitorCI[" + id + "], request(" + request + ")");
} else {
throw new ObjectNotFoundException(request, e);
}
} else {
if (e == null) {
logger.warn("Error providing CompetitorCI[{}] request({})", id, request);
} else {
logger.warn("Error providing CompetitorCI[{}] request({}), ex:", id, request, e);
}
}
}
}