impsToStoredRequestId) {
+
+ return storedDataFuture
+ .compose(result -> !result.getErrors().isEmpty()
+ ? Future.failedFuture(new InvalidStoredRequestException(result.getErrors()))
+ : Future.succeededFuture(result))
+ .map(result -> mergeBidRequestAndImps(
+ bidRequest, storedBidRequestId, impsToStoredRequestId, result));
+ }
+
+ /**
+ * Runs {@link BidRequest} and {@link Imp}s merge processes.
+ *
+ * The merging priority is: original request > stored request > default request
+ */
+ private BidRequest mergeBidRequestAndImps(BidRequest bidRequest,
+ String storedRequestId,
+ Map impToStoredId,
+ StoredDataResult storedDataResult) {
+
+ final BidRequest mergedWithStoredRequest = mergeBidRequest(bidRequest, storedRequestId, storedDataResult);
+
+ final BidRequest mergedWithDefaultRequest = mergeDefaultRequest(mergedWithStoredRequest);
+
+ return mergeImps(mergedWithDefaultRequest, impToStoredId, storedDataResult);
+ }
+
+ private BidRequest mergeDefaultRequest(BidRequest bidRequest) {
+ return jsonMerger.merge(bidRequest, defaultBidRequest, BidRequest.class);
+ }
+
+ /**
+ * Merges original request with request from stored request source. Values from original request
+ * has higher priority than stored request values.
+ */
+ private BidRequest mergeBidRequest(BidRequest originalRequest,
+ String storedRequestId,
+ StoredDataResult storedDataResult) {
+
+ final String storedRequest = storedDataResult.getStoredIdToRequest().get(storedRequestId);
+ return StringUtils.isNotBlank(storedRequestId)
+ ? jsonMerger.merge(originalRequest, storedRequest, storedRequestId, BidRequest.class)
+ : originalRequest;
+ }
+
+ /**
+ * Merges {@link Imp}s from original request with Imps from stored request source. Values from original request
+ * has higher priority than stored request values.
+ */
+ private BidRequest mergeImps(BidRequest bidRequest,
+ Map impToStoredId,
+ StoredDataResult storedDataResult) {
+
+ if (impToStoredId.isEmpty()) {
+ return bidRequest;
+ }
+ final List mergedImps = new ArrayList<>(bidRequest.getImp());
+ for (int i = 0; i < mergedImps.size(); i++) {
+ final Imp imp = mergedImps.get(i);
+ final String storedRequestId = impToStoredId.get(imp);
+ if (storedRequestId != null) {
+ final String storedImp = storedDataResult.getStoredIdToImp().get(storedRequestId);
+ final Imp mergedImp = jsonMerger.merge(imp, storedImp, storedRequestId, Imp.class);
+ mergedImps.set(i, mergedImp);
+ }
+ }
+ return bidRequest.toBuilder().imp(mergedImps).build();
+ }
+
+ private BidRequest generateBidRequestIdForApp(BidRequest bidRequest) {
+ return bidRequest.getApp() != null
+ ? generateBidRequestId(bidRequest)
+ : bidRequest;
+ }
+
+ private BidRequest generateBidRequestId(BidRequest bidRequest) {
+ return generateBidRequestId || Objects.equals(bidRequest.getId(), OVERRIDE_BID_REQUEST_ID_TEMPLATE)
+ ? bidRequest.toBuilder().id(idGenerator.generateId()).build()
+ : bidRequest;
+ }
+
+ /**
+ * Maps object to its StoredRequestId if exists. If object's extension contains storedRequest field, expected
+ * that it includes id too, in another case error about missed id in stored request will be added to error list.
+ * Gathers all errors into list, and in case if it is not empty, throws {@link InvalidRequestException} with list
+ * of errors.
+ */
+ private static Map mapStoredRequestHolderToStoredRequestId(
+ List storedRequestHolders,
+ Function storedRequestIdExtractor) {
+
+ if (CollectionUtils.isEmpty(storedRequestHolders)) {
+ return Collections.emptyMap();
+ }
+
+ final Map holderToPreBidRequest = new HashMap<>();
+
+ for (K storedRequestHolder : storedRequestHolders) {
+ final String storedRequestId = storedRequestIdExtractor.apply(storedRequestHolder);
+ if (storedRequestId != null) {
+ holderToPreBidRequest.put(storedRequestHolder, storedRequestId);
+ }
+ }
+
+ return holderToPreBidRequest;
+ }
+
+ private static String getStoredRequestIdFromBidRequest(BidRequest bidRequest) {
+ final ExtRequestPrebid prebid = ObjectUtil.getIfNotNull(bidRequest.getExt(), ExtRequest::getPrebid);
+ final ExtStoredRequest extStoredRequest = ObjectUtil.getIfNotNull(prebid, ExtRequestPrebid::getStoredrequest);
+
+ if (extStoredRequest == null) {
+ return null;
+ }
+
+ final String storedRequestId = extStoredRequest.getId();
+ if (storedRequestId == null) {
+ throw new InvalidStoredRequestException("Id is not found in storedRequest");
+ }
+
+ return storedRequestId;
+ }
+
+ private String getStoredRequestIdFromImp(Imp imp) {
+ if (imp.getExt() == null) {
+ return null;
+ }
+
+ final ExtImp extImp;
+ try {
+ extImp = mapper.mapper().treeToValue(imp.getExt(), ExtImp.class);
+ } catch (JsonProcessingException e) {
+ throw new InvalidStoredImpException(
+ "Incorrect Imp extension format for Imp with id " + imp.getId() + ": " + e.getMessage());
+ }
+
+ final ExtStoredRequest extStoredRequest = ObjectUtil.getIfNotNull(
+ extImp.getPrebid(), ExtImpPrebid::getStoredrequest);
+ if (extStoredRequest == null) {
+ return null;
+ }
+
+ final String storedRequestId = extStoredRequest.getId();
+ if (storedRequestId == null) {
+ throw new InvalidStoredImpException("Id is not found in storedRequest");
+ }
+
+ return storedRequestId;
+ }
+
+ /**
+ * If the request defines tmax explicitly, then it is returned as is. Otherwise, default timeout is returned.
+ */
+ private Timeout timeout(BidRequest bidRequest) {
+ final Long tmax = bidRequest.getTmax();
+ return timeoutFactory.create(tmax != null && tmax > 0 ? tmax : defaultTimeout);
+ }
+}
diff --git a/src/main/java/org/prebid/server/auction/StoredResponseProcessor.java b/src/main/java/org/prebid/server/auction/StoredResponseProcessor.java
new file mode 100644
index 00000000000..2257320ef69
--- /dev/null
+++ b/src/main/java/org/prebid/server/auction/StoredResponseProcessor.java
@@ -0,0 +1,484 @@
+package org.prebid.server.auction;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.iab.openrtb.request.BidRequest;
+import com.iab.openrtb.request.Imp;
+import com.iab.openrtb.response.Bid;
+import com.iab.openrtb.response.SeatBid;
+import io.vertx.core.Future;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.map.CaseInsensitiveMap;
+import org.apache.commons.lang3.StringUtils;
+import org.prebid.server.auction.model.AuctionParticipation;
+import org.prebid.server.auction.model.BidRejectionTracker;
+import org.prebid.server.auction.model.BidderRequest;
+import org.prebid.server.auction.model.BidderResponse;
+import org.prebid.server.auction.model.StoredResponseResult;
+import org.prebid.server.auction.model.Tuple2;
+import org.prebid.server.bidder.model.BidderBid;
+import org.prebid.server.bidder.model.BidderSeatBid;
+import org.prebid.server.exception.InvalidRequestException;
+import org.prebid.server.exception.PreBidException;
+import org.prebid.server.execution.timeout.Timeout;
+import org.prebid.server.json.JacksonMapper;
+import org.prebid.server.proto.openrtb.ext.request.ExtImp;
+import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid;
+import org.prebid.server.proto.openrtb.ext.request.ExtStoredAuctionResponse;
+import org.prebid.server.proto.openrtb.ext.request.ExtStoredBidResponse;
+import org.prebid.server.proto.openrtb.ext.response.BidType;
+import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid;
+import org.prebid.server.settings.ApplicationSettings;
+import org.prebid.server.settings.model.StoredResponseDataResult;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * Resolves stored response data retrieving and BidderResponse merging processes.
+ */
+public class StoredResponseProcessor {
+
+ private static final String PREBID_EXT = "prebid";
+ private static final String DEFAULT_BID_CURRENCY = "USD";
+ private static final String PBS_IMPID_MACRO = "##PBSIMPID##";
+
+ private static final TypeReference> SEATBID_LIST_TYPE =
+ new TypeReference<>() {
+ };
+
+ private final ApplicationSettings applicationSettings;
+ private final JacksonMapper mapper;
+
+ public StoredResponseProcessor(ApplicationSettings applicationSettings,
+ JacksonMapper mapper) {
+
+ this.applicationSettings = Objects.requireNonNull(applicationSettings);
+ this.mapper = Objects.requireNonNull(mapper);
+ }
+
+ Future getStoredResponseResult(List imps, Timeout timeout) {
+ final Map impExtPrebids = getImpsExtPrebid(imps);
+ final Map impIdsToStoredResponses = getAuctionStoredResponses(impExtPrebids);
+ final List requiredRequestImps = excludeStoredAuctionResponseImps(imps, impIdsToStoredResponses);
+
+ final Map> impToBidderToStoredBidResponseId =
+ getStoredBidResponses(impExtPrebids, requiredRequestImps);
+
+ final Set storedResponses = new HashSet<>(impIdsToStoredResponses.values());
+
+ impToBidderToStoredBidResponseId.values()
+ .forEach(bidderToStoredResponse -> storedResponses.addAll(bidderToStoredResponse.values()));
+
+ if (storedResponses.isEmpty()) {
+ return Future.succeededFuture(
+ StoredResponseResult.of(imps, Collections.emptyList(), Collections.emptyMap()));
+ }
+
+ return getStoredResponses(storedResponses, timeout)
+ .recover(exception -> Future.failedFuture(new InvalidRequestException(
+ "Stored response fetching failed with reason: " + exception.getMessage())))
+ .map(storedResponseDataResult -> StoredResponseResult.of(
+ requiredRequestImps,
+ convertToSeatBid(storedResponseDataResult, impIdsToStoredResponses),
+ mapStoredBidResponseIdsToValues(
+ storedResponseDataResult.getIdToStoredResponses(),
+ impToBidderToStoredBidResponseId)));
+ }
+
+ Future getStoredResponseResult(String storedId, Timeout timeout) {
+ return applicationSettings.getStoredResponses(Collections.singleton(storedId), timeout)
+ .recover(exception -> Future.failedFuture(new InvalidRequestException(
+ "Stored response fetching failed with reason: " + exception.getMessage())))
+ .map(storedResponseDataResult -> StoredResponseResult.of(
+ Collections.emptyList(),
+ convertToSeatBid(storedResponseDataResult),
+ Collections.emptyMap()));
+ }
+
+ private Map getImpsExtPrebid(List imps) {
+ return imps.stream()
+ .collect(Collectors.toMap(Imp::getId, imp -> getExtImp(imp.getExt(), imp.getId()).getPrebid()));
+ }
+
+ private ExtImp getExtImp(ObjectNode extImpNode, String impId) {
+ try {
+ return mapper.mapper().treeToValue(extImpNode, ExtImp.class);
+ } catch (JsonProcessingException e) {
+ throw new InvalidRequestException(
+ "Error decoding bidRequest.imp.ext for impId = %s : %s".formatted(impId, e.getMessage()));
+ }
+ }
+
+ private Map getAuctionStoredResponses(Map extImpPrebids) {
+ return extImpPrebids.entrySet().stream()
+ .map(impIdToExtPrebid -> Tuple2.of(
+ impIdToExtPrebid.getKey(),
+ extractAuctionStoredResponseId(impIdToExtPrebid.getValue())))
+ .filter(impIdToStoredResponseId -> impIdToStoredResponseId.getRight() != null)
+ .collect(Collectors.toMap(Tuple2::getLeft, Tuple2::getRight));
+ }
+
+ private StoredResponse extractAuctionStoredResponseId(ExtImpPrebid extImpPrebid) {
+ final ExtStoredAuctionResponse storedAuctionResponse = extImpPrebid.getStoredAuctionResponse();
+ return Optional.ofNullable(storedAuctionResponse)
+ .map(ExtStoredAuctionResponse::getSeatBid)
+ .map(StoredResponse.StoredResponseObject::new)
+ .or(() -> Optional.ofNullable(storedAuctionResponse)
+ .map(ExtStoredAuctionResponse::getId)
+ .map(StoredResponse.StoredResponseId::new))
+ .orElse(null);
+ }
+
+ private List excludeStoredAuctionResponseImps(List imps,
+ Map impIdToStoredResponse) {
+
+ return imps.stream()
+ .filter(imp -> !impIdToStoredResponse.containsKey(imp.getId()))
+ .toList();
+ }
+
+ private Map> getStoredBidResponses(
+ Map extImpPrebids,
+ List imps) {
+
+ // PBS supports stored bid response only for requests with single impression, but it can be changed in future
+ if (imps.size() != 1) {
+ return Collections.emptyMap();
+ }
+
+ return extImpPrebids.entrySet().stream()
+ .filter(impIdToExtPrebid ->
+ CollectionUtils.isNotEmpty(impIdToExtPrebid.getValue().getStoredBidResponse()))
+ .collect(Collectors.toMap(
+ Map.Entry::getKey,
+ impIdToStoredResponses ->
+ resolveStoredBidResponse(impIdToStoredResponses.getValue().getStoredBidResponse())));
+ }
+
+ private Map resolveStoredBidResponse(
+ List storedBidResponse) {
+
+ return storedBidResponse.stream()
+ .collect(Collectors.toMap(
+ ExtStoredBidResponse::getBidder,
+ extStoredBidResponse -> new StoredResponse.StoredResponseId(extStoredBidResponse.getId())));
+ }
+
+ private Future getStoredResponses(Set storedResponses, Timeout timeout) {
+ return applicationSettings.getStoredResponses(
+ storedResponses.stream()
+ .filter(StoredResponse.StoredResponseId.class::isInstance)
+ .map(StoredResponse.StoredResponseId.class::cast)
+ .map(StoredResponse.StoredResponseId::id)
+ .collect(Collectors.toSet()),
+ timeout);
+ }
+
+ private List convertToSeatBid(StoredResponseDataResult storedResponseDataResult,
+ Map impIdsToStoredResponses) {
+
+ final List resolvedSeatBids = new ArrayList<>();
+ final Map idToStoredResponses = storedResponseDataResult.getIdToStoredResponses();
+ for (Map.Entry impIdToStoredResponse : impIdsToStoredResponses.entrySet()) {
+ final String impId = impIdToStoredResponse.getKey();
+ final StoredResponse storedResponse = impIdToStoredResponse.getValue();
+ final List seatBids = resolveSeatBids(storedResponse, idToStoredResponses, impId);
+
+ validateStoredSeatBid(seatBids);
+ resolvedSeatBids.addAll(seatBids.stream()
+ .map(seatBid -> updateSeatBidBids(seatBid, impId))
+ .toList());
+ }
+ return mergeSameBidderSeatBid(resolvedSeatBids);
+ }
+
+ private List convertToSeatBid(StoredResponseDataResult storedResponseDataResult) {
+ final List resolvedSeatBids = new ArrayList<>();
+ final Map idToStoredResponses = storedResponseDataResult.getIdToStoredResponses();
+ for (Map.Entry storedIdToImpId : idToStoredResponses.entrySet()) {
+ final String id = storedIdToImpId.getKey();
+ final String rowSeatBid = storedIdToImpId.getValue();
+ if (rowSeatBid == null) {
+ throw new InvalidRequestException(
+ "Failed to fetch stored auction response for storedAuctionResponse id = %s.".formatted(id));
+ }
+ final List seatBids = parseSeatBid(id, rowSeatBid);
+ validateStoredSeatBid(seatBids);
+ resolvedSeatBids.addAll(seatBids);
+ }
+ return mergeSameBidderSeatBid(resolvedSeatBids);
+ }
+
+ private List resolveSeatBids(StoredResponse storedResponse,
+ Map idToStoredResponses,
+ String impId) {
+
+ if (storedResponse instanceof StoredResponse.StoredResponseObject storedResponseObject) {
+ return Collections.singletonList(storedResponseObject.seatBid());
+ }
+
+ final String storedResponseId = ((StoredResponse.StoredResponseId) storedResponse).id();
+ final String rowSeatBid = idToStoredResponses.get(storedResponseId);
+ if (rowSeatBid == null) {
+ throw new InvalidRequestException(
+ "Failed to fetch stored auction response for impId = %s and storedAuctionResponse id = %s."
+ .formatted(impId, storedResponseId));
+ }
+
+ return parseSeatBid(storedResponseId, rowSeatBid);
+ }
+
+ private List parseSeatBid(String id, String rowSeatBid) {
+ try {
+ return mapper.mapper().readValue(rowSeatBid, SEATBID_LIST_TYPE);
+ } catch (IOException e) {
+ throw new InvalidRequestException("Can't parse Json for stored response with id " + id);
+ }
+ }
+
+ private void validateStoredSeatBid(List seatBids) {
+ for (final SeatBid seatBid : seatBids) {
+ if (StringUtils.isEmpty(seatBid.getSeat())) {
+ throw new InvalidRequestException("Seat can't be empty in stored response seatBid");
+ }
+
+ if (CollectionUtils.isEmpty(seatBid.getBid())) {
+ throw new InvalidRequestException("There must be at least one bid in stored response seatBid");
+ }
+ }
+ }
+
+ private SeatBid updateSeatBidBids(SeatBid seatBid, String impId) {
+ return seatBid.toBuilder().bid(updateBidsWithImpId(seatBid.getBid(), impId)).build();
+ }
+
+ private List updateBidsWithImpId(List bids, String impId) {
+ return bids.stream().map(bid -> updateBidWithImpId(bid, impId)).toList();
+ }
+
+ private static Bid updateBidWithImpId(Bid bid, String impId) {
+ return bid.toBuilder().impid(impId).build();
+ }
+
+ private List mergeSameBidderSeatBid(List seatBids) {
+ return seatBids.stream().collect(Collectors.groupingBy(SeatBid::getSeat, Collectors.toList()))
+ .entrySet().stream()
+ .map(bidderToSeatBid -> makeMergedSeatBid(bidderToSeatBid.getKey(), bidderToSeatBid.getValue()))
+ .toList();
+ }
+
+ private SeatBid makeMergedSeatBid(String seat, List storedSeatBids) {
+ return SeatBid.builder()
+ .bid(storedSeatBids.stream().map(SeatBid::getBid).flatMap(List::stream).toList())
+ .seat(seat)
+ .ext(storedSeatBids.stream().map(SeatBid::getExt).filter(Objects::nonNull).findFirst().orElse(null))
+ .build();
+ }
+
+ private Map> mapStoredBidResponseIdsToValues(
+ Map idToStoredResponses,
+ Map> impToBidderToStoredBidResponseId) {
+
+ return impToBidderToStoredBidResponseId.entrySet().stream()
+ .collect(Collectors.toMap(
+ Map.Entry::getKey,
+ entry -> entry.getValue().entrySet().stream()
+ .filter(bidderToId -> idToStoredResponses.containsKey(bidderToId.getValue().id()))
+ .collect(Collectors.toMap(
+ Map.Entry::getKey,
+ bidderToId -> idToStoredResponses.get(bidderToId.getValue().id()),
+ (first, second) -> second,
+ CaseInsensitiveMap::new))));
+ }
+
+ public List updateStoredBidResponse(List auctionParticipations) {
+ return auctionParticipations.stream()
+ .map(StoredResponseProcessor::updateStoredBidResponse)
+ .collect(Collectors.toList());
+ }
+
+ private static AuctionParticipation updateStoredBidResponse(AuctionParticipation auctionParticipation) {
+ final BidderRequest bidderRequest = auctionParticipation.getBidderRequest();
+ final BidRequest bidRequest = bidderRequest.getBidRequest();
+
+ final List imps = bidRequest.getImp();
+ // Аor now, Stored Bid Response works only for bid requests with single imp
+ if (imps.size() > 1 || StringUtils.isEmpty(bidderRequest.getStoredResponse())) {
+ return auctionParticipation;
+ }
+
+ final BidderResponse bidderResponse = auctionParticipation.getBidderResponse();
+ final BidderSeatBid initialSeatBid = bidderResponse.getSeatBid();
+ final BidderSeatBid adjustedSeatBid = updateSeatBid(initialSeatBid, imps.getFirst().getId());
+
+ return auctionParticipation.with(bidderResponse.with(adjustedSeatBid));
+ }
+
+ private static BidderSeatBid updateSeatBid(BidderSeatBid bidderSeatBid, String impId) {
+ final List bids = bidderSeatBid.getBids().stream()
+ .map(bidderBid -> resolveBidImpId(bidderBid, impId))
+ .collect(Collectors.toList());
+
+ return bidderSeatBid.with(bids);
+ }
+
+ private static BidderBid resolveBidImpId(BidderBid bidderBid, String impId) {
+ final Bid bid = bidderBid.getBid();
+ final String bidImpId = bid.getImpid();
+ if (!StringUtils.contains(bidImpId, PBS_IMPID_MACRO)) {
+ return bidderBid;
+ }
+
+ return bidderBid.toBuilder()
+ .bid(bid.toBuilder().impid(bidImpId.replace(PBS_IMPID_MACRO, impId)).build())
+ .build();
+ }
+
+ List mergeWithBidderResponses(List auctionParticipations,
+ List storedAuctionResponses,
+ List imps,
+ Map bidRejectionTrackers) {
+
+ if (CollectionUtils.isEmpty(storedAuctionResponses)) {
+ return auctionParticipations;
+ }
+
+ final Map bidderToAuctionParticipation = auctionParticipations.stream()
+ .collect(Collectors.toMap(AuctionParticipation::getBidder, Function.identity()));
+ final Map bidderToSeatBid = storedAuctionResponses.stream()
+ .collect(Collectors.toMap(SeatBid::getSeat, Function.identity()));
+ final Map impIdToBidType = imps.stream()
+ .collect(Collectors.toMap(Imp::getId, this::resolveBidType));
+ final Set responseBidders = new HashSet<>(bidderToAuctionParticipation.keySet());
+ responseBidders.addAll(bidderToSeatBid.keySet());
+
+ return responseBidders.stream()
+ .map(bidder -> updateBidderResponse(
+ bidderToAuctionParticipation.get(bidder),
+ bidderToSeatBid.get(bidder),
+ impIdToBidType))
+ .map(auctionParticipation -> restoreStoredBidsFromRejection(bidRejectionTrackers, auctionParticipation))
+ .toList();
+ }
+
+ private BidType resolveBidType(Imp imp) {
+ BidType bidType = BidType.banner;
+ if (imp.getBanner() != null) {
+ return bidType;
+ } else if (imp.getVideo() != null) {
+ bidType = BidType.video;
+ } else if (imp.getXNative() != null) {
+ bidType = BidType.xNative;
+ } else if (imp.getAudio() != null) {
+ bidType = BidType.audio;
+ }
+ return bidType;
+ }
+
+ private AuctionParticipation updateBidderResponse(AuctionParticipation auctionParticipation,
+ SeatBid storedSeatBid,
+ Map impIdToBidType) {
+
+ if (auctionParticipation != null) {
+ if (auctionParticipation.isRequestBlocked()) {
+ return auctionParticipation;
+ }
+
+ final BidderResponse bidderResponse = auctionParticipation.getBidderResponse();
+ final BidderSeatBid bidderSeatBid = bidderResponse.getSeatBid();
+ final BidderSeatBid updatedSeatBid = storedSeatBid == null
+ ? bidderSeatBid
+ : makeBidderSeatBid(bidderSeatBid, storedSeatBid, impIdToBidType);
+ final BidderResponse updatedBidderResponse = BidderResponse.of(bidderResponse.getBidder(),
+ updatedSeatBid, bidderResponse.getResponseTime());
+ return auctionParticipation.with(updatedBidderResponse);
+ } else {
+ final String bidder = storedSeatBid != null ? storedSeatBid.getSeat() : null;
+ final BidderSeatBid updatedSeatBid = makeBidderSeatBid(null, storedSeatBid, impIdToBidType);
+ final BidderResponse updatedBidderResponse = BidderResponse.of(bidder, updatedSeatBid, 0);
+ return AuctionParticipation.builder()
+ .bidder(bidder)
+ .bidderResponse(updatedBidderResponse)
+ .build();
+ }
+ }
+
+ private BidderSeatBid makeBidderSeatBid(BidderSeatBid bidderSeatBid,
+ SeatBid seatBid,
+ Map impIdToBidType) {
+
+ final boolean nonNullBidderSeatBid = bidderSeatBid != null;
+ final String bidCurrency = nonNullBidderSeatBid
+ ? bidderSeatBid.getBids().stream()
+ .map(BidderBid::getBidCurrency)
+ .filter(Objects::nonNull)
+ .findAny()
+ .orElse(DEFAULT_BID_CURRENCY)
+ : DEFAULT_BID_CURRENCY;
+ final List bidderBids = seatBid != null
+ ? seatBid.getBid().stream()
+ .map(bid -> makeBidderBid(bid, bidCurrency, seatBid.getSeat(), impIdToBidType))
+ .collect(Collectors.toCollection(ArrayList::new))
+ : new ArrayList<>();
+ if (nonNullBidderSeatBid) {
+ bidderBids.addAll(bidderSeatBid.getBids());
+ }
+ return nonNullBidderSeatBid
+ ? bidderSeatBid.with(bidderBids)
+ : BidderSeatBid.of(bidderBids);
+ }
+
+ private BidderBid makeBidderBid(Bid bid, String bidCurrency, String seat, Map impIdToBidType) {
+ return BidderBid.of(bid, getBidType(bid.getExt(), impIdToBidType.get(bid.getImpid())), seat, bidCurrency);
+ }
+
+ private BidType getBidType(ObjectNode bidExt, BidType bidType) {
+ final ObjectNode bidExtPrebid = bidExt != null ? (ObjectNode) bidExt.get(PREBID_EXT) : null;
+ final ExtBidPrebid extBidPrebid = bidExtPrebid != null ? parseExtBidPrebid(bidExtPrebid) : null;
+ return extBidPrebid != null ? extBidPrebid.getType() : bidType;
+ }
+
+ private ExtBidPrebid parseExtBidPrebid(ObjectNode bidExtPrebid) {
+ try {
+ return mapper.mapper().treeToValue(bidExtPrebid, ExtBidPrebid.class);
+ } catch (JsonProcessingException e) {
+ throw new PreBidException("Error decoding stored response bid.ext.prebid");
+ }
+ }
+
+ private static AuctionParticipation restoreStoredBidsFromRejection(
+ Map bidRejectionTrackers,
+ AuctionParticipation auctionParticipation) {
+
+ final BidRejectionTracker bidRejectionTracker = bidRejectionTrackers.get(auctionParticipation.getBidder());
+
+ if (bidRejectionTracker != null) {
+ Optional.ofNullable(auctionParticipation.getBidderResponse())
+ .map(BidderResponse::getSeatBid)
+ .map(BidderSeatBid::getBids)
+ .ifPresent(bidRejectionTracker::restoreFromRejection);
+ }
+
+ return auctionParticipation;
+ }
+
+ private sealed interface StoredResponse {
+
+ record StoredResponseId(String id) implements StoredResponse {
+ }
+
+ record StoredResponseObject(SeatBid seatBid) implements StoredResponse {
+ }
+ }
+}
diff --git a/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java b/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java
index f3beeb57e6c..aa136016aae 100644
--- a/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java
+++ b/src/main/java/org/prebid/server/auction/VideoStoredRequestProcessor.java
@@ -129,9 +129,15 @@ private static BidRequest readBidRequest(String defaultBidRequestPath,
: null;
}
+<<<<<<< HEAD
private StoredDataResult updateMetrics(StoredDataResult storedDataResult,
Set requestIds,
Set impIds) {
+=======
+ private StoredDataResult updateMetrics(StoredDataResult storedDataResult,
+ Set requestIds,
+ Set impIds) {
+>>>>>>> 04d9d4a13 (Initial commit)
requestIds.forEach(
id -> metrics.updateStoredRequestMetric(storedDataResult.getStoredIdToRequest().containsKey(id)));
@@ -142,7 +148,11 @@ private StoredDataResult updateMetrics(StoredDataResult storedDa
return storedDataResult;
}
+<<<<<<< HEAD
private WithPodErrors toBidRequestWithPodErrors(StoredDataResult storedResult,
+=======
+ private WithPodErrors toBidRequestWithPodErrors(StoredDataResult storedResult,
+>>>>>>> 04d9d4a13 (Initial commit)
BidRequestVideo videoRequest,
String storedBidRequestId) {
@@ -161,7 +171,11 @@ private WithPodErrors toBidRequestWithPodErrors(StoredDataResult storedDataResult) {
+=======
+ StoredDataResult storedDataResult) {
+>>>>>>> 04d9d4a13 (Initial commit)
final String storedRequest = storedDataResult.getStoredIdToRequest().get(storedRequestId);
if (enforceStoredRequest && StringUtils.isBlank(storedRequest)) {
diff --git a/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java
index e1c5e4240ce..1940e157c82 100644
--- a/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java
+++ b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java
@@ -23,8 +23,12 @@
import org.prebid.server.auction.ImplicitParametersExtractor;
import org.prebid.server.auction.OrtbTypesResolver;
import org.prebid.server.auction.PriceGranularity;
+<<<<<<< HEAD
import org.prebid.server.auction.externalortb.ProfilesProcessor;
import org.prebid.server.auction.externalortb.StoredRequestProcessor;
+=======
+import org.prebid.server.auction.StoredRequestProcessor;
+>>>>>>> 04d9d4a13 (Initial commit)
import org.prebid.server.auction.gpp.AmpGppService;
import org.prebid.server.auction.model.AuctionContext;
import org.prebid.server.auction.model.ConsentType;
@@ -91,7 +95,10 @@ public class AmpRequestFactory {
private final Ortb2RequestFactory ortb2RequestFactory;
private final StoredRequestProcessor storedRequestProcessor;
+<<<<<<< HEAD
private final ProfilesProcessor profilesProcessor;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
private final BidRequestOrtbVersionConversionManager ortbVersionConversionManager;
private final AmpGppService gppService;
private final OrtbTypesResolver ortbTypesResolver;
@@ -105,7 +112,10 @@ public class AmpRequestFactory {
public AmpRequestFactory(Ortb2RequestFactory ortb2RequestFactory,
StoredRequestProcessor storedRequestProcessor,
+<<<<<<< HEAD
ProfilesProcessor profilesProcessor,
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
BidRequestOrtbVersionConversionManager ortbVersionConversionManager,
AmpGppService gppService,
OrtbTypesResolver ortbTypesResolver,
@@ -119,7 +129,10 @@ public AmpRequestFactory(Ortb2RequestFactory ortb2RequestFactory,
this.ortb2RequestFactory = Objects.requireNonNull(ortb2RequestFactory);
this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor);
+<<<<<<< HEAD
this.profilesProcessor = Objects.requireNonNull(profilesProcessor);
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
this.ortbVersionConversionManager = Objects.requireNonNull(ortbVersionConversionManager);
this.gppService = Objects.requireNonNull(gppService);
this.ortbTypesResolver = Objects.requireNonNull(ortbTypesResolver);
@@ -411,7 +424,10 @@ private Future updateBidRequest(AuctionContext auctionContext) {
final HttpRequestContext httpRequest = auctionContext.getHttpRequest();
return storedRequestProcessor.processAmpRequest(accountId, storedRequestId, receivedBidRequest)
+<<<<<<< HEAD
.compose(bidRequest -> profilesProcessor.process(auctionContext, bidRequest))
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
.map(ortbVersionConversionManager::convertToAuctionSupportedVersion)
.map(bidRequest -> gppService.updateBidRequest(bidRequest, auctionContext))
.map(bidRequest -> validateStoredBidRequest(storedRequestId, bidRequest))
diff --git a/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java
index d873af3e696..6a32d4913fa 100644
--- a/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java
+++ b/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java
@@ -11,8 +11,12 @@
import org.prebid.server.auction.ImplicitParametersExtractor;
import org.prebid.server.auction.InterstitialProcessor;
import org.prebid.server.auction.OrtbTypesResolver;
+<<<<<<< HEAD
import org.prebid.server.auction.externalortb.ProfilesProcessor;
import org.prebid.server.auction.externalortb.StoredRequestProcessor;
+=======
+import org.prebid.server.auction.StoredRequestProcessor;
+>>>>>>> 04d9d4a13 (Initial commit)
import org.prebid.server.auction.gpp.AuctionGppService;
import org.prebid.server.auction.model.AuctionContext;
import org.prebid.server.auction.model.AuctionStoredResult;
@@ -41,7 +45,10 @@ public class AuctionRequestFactory {
private final long maxRequestSize;
private final Ortb2RequestFactory ortb2RequestFactory;
private final StoredRequestProcessor storedRequestProcessor;
+<<<<<<< HEAD
private final ProfilesProcessor profilesProcessor;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
private final BidRequestOrtbVersionConversionManager ortbVersionConversionManager;
private final AuctionGppService gppService;
private final CookieDeprecationService cookieDeprecationService;
@@ -60,7 +67,10 @@ public class AuctionRequestFactory {
public AuctionRequestFactory(long maxRequestSize,
Ortb2RequestFactory ortb2RequestFactory,
StoredRequestProcessor storedRequestProcessor,
+<<<<<<< HEAD
ProfilesProcessor profilesProcessor,
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
BidRequestOrtbVersionConversionManager ortbVersionConversionManager,
AuctionGppService gppService,
CookieDeprecationService cookieDeprecationService,
@@ -77,7 +87,10 @@ public AuctionRequestFactory(long maxRequestSize,
this.maxRequestSize = maxRequestSize;
this.ortb2RequestFactory = Objects.requireNonNull(ortb2RequestFactory);
this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor);
+<<<<<<< HEAD
this.profilesProcessor = Objects.requireNonNull(profilesProcessor);
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
this.ortbVersionConversionManager = Objects.requireNonNull(ortbVersionConversionManager);
this.gppService = Objects.requireNonNull(gppService);
this.cookieDeprecationService = Objects.requireNonNull(cookieDeprecationService);
@@ -256,7 +269,11 @@ private Future updateBidRequest(AuctionStoredResult auctionStoredRes
final boolean hasStoredBidRequest = auctionStoredResult.hasStoredBidRequest();
+<<<<<<< HEAD
return profilesProcessor.process(auctionContext, auctionStoredResult.bidRequest())
+=======
+ return Future.succeededFuture(auctionStoredResult.bidRequest())
+>>>>>>> 04d9d4a13 (Initial commit)
.map(ortbVersionConversionManager::convertToAuctionSupportedVersion)
.map(bidRequest -> gppService.updateBidRequest(bidRequest, auctionContext))
.map(bidRequest -> paramsResolver.resolve(bidRequest, auctionContext, ENDPOINT, hasStoredBidRequest))
diff --git a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java
index ac9619f6b83..707fb954ef2 100644
--- a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java
+++ b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java
@@ -23,11 +23,17 @@
import org.prebid.server.activity.infrastructure.ActivityInfrastructure;
import org.prebid.server.activity.infrastructure.creator.ActivityInfrastructureCreator;
import org.prebid.server.auction.IpAddressHelper;
+<<<<<<< HEAD
import org.prebid.server.auction.TimeoutResolver;
import org.prebid.server.auction.externalortb.ProfilesProcessor;
import org.prebid.server.auction.externalortb.StoredRequestProcessor;
import org.prebid.server.auction.model.AuctionContext;
import org.prebid.server.auction.model.AuctionStoredResult;
+=======
+import org.prebid.server.auction.StoredRequestProcessor;
+import org.prebid.server.auction.TimeoutResolver;
+import org.prebid.server.auction.model.AuctionContext;
+>>>>>>> 04d9d4a13 (Initial commit)
import org.prebid.server.auction.model.IpAddress;
import org.prebid.server.auction.model.TimeoutContext;
import org.prebid.server.auction.model.debug.DebugContext;
@@ -103,7 +109,10 @@ public class Ortb2RequestFactory {
private final TimeoutResolver timeoutResolver;
private final TimeoutFactory timeoutFactory;
private final StoredRequestProcessor storedRequestProcessor;
+<<<<<<< HEAD
private final ProfilesProcessor profilesProcessor;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
private final ApplicationSettings applicationSettings;
private final IpAddressHelper ipAddressHelper;
private final HookStageExecutor hookStageExecutor;
@@ -119,7 +128,10 @@ public Ortb2RequestFactory(int timeoutAdjustmentFactor,
TimeoutResolver timeoutResolver,
TimeoutFactory timeoutFactory,
StoredRequestProcessor storedRequestProcessor,
+<<<<<<< HEAD
ProfilesProcessor profilesProcessor,
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
ApplicationSettings applicationSettings,
IpAddressHelper ipAddressHelper,
HookStageExecutor hookStageExecutor,
@@ -139,7 +151,10 @@ public Ortb2RequestFactory(int timeoutAdjustmentFactor,
this.timeoutResolver = Objects.requireNonNull(timeoutResolver);
this.timeoutFactory = Objects.requireNonNull(timeoutFactory);
this.storedRequestProcessor = Objects.requireNonNull(storedRequestProcessor);
+<<<<<<< HEAD
this.profilesProcessor = Objects.requireNonNull(profilesProcessor);
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
this.applicationSettings = Objects.requireNonNull(applicationSettings);
this.ipAddressHelper = Objects.requireNonNull(ipAddressHelper);
this.hookStageExecutor = Objects.requireNonNull(hookStageExecutor);
@@ -186,7 +201,11 @@ private Future fetchAccount(AuctionContext auctionContext, boolean isLo
final Timeout timeout = auctionContext.getTimeoutContext().getTimeout();
final HttpRequestContext httpRequest = auctionContext.getHttpRequest();
+<<<<<<< HEAD
return findAccountIdFrom(auctionContext, bidRequest, isLookupStoredRequest)
+=======
+ return findAccountIdFrom(bidRequest, isLookupStoredRequest)
+>>>>>>> 04d9d4a13 (Initial commit)
.map(this::validateIfAccountBlocklisted)
.compose(accountId -> loadAccount(timeout, httpRequest, accountId));
}
@@ -473,6 +492,7 @@ private Timeout timeout(BidRequest bidRequest, long startTime) {
return timeoutFactory.create(startTime, timeout);
}
+<<<<<<< HEAD
private Future findAccountIdFrom(AuctionContext auctionContext,
BidRequest bidRequest,
boolean isLookupStoredRequest) {
@@ -520,6 +540,14 @@ private Future accountIdFromStoredRequest(BidRequest bidRequest) {
private Future accountIdFromProfiles(AuctionContext auctionContext, BidRequest bidRequest) {
return profilesProcessor.process(auctionContext, bidRequest)
.map(this::accountIdFromBidRequest);
+=======
+ private Future findAccountIdFrom(BidRequest bidRequest, boolean isLookupStoredRequest) {
+ final String accountId = accountIdFrom(bidRequest);
+ return StringUtils.isNotBlank(accountId) || !isLookupStoredRequest
+ ? Future.succeededFuture(accountId)
+ : storedRequestProcessor.processAuctionRequest(accountId, bidRequest)
+ .map(storedAuctionResult -> accountIdFrom(storedAuctionResult.bidRequest()));
+>>>>>>> 04d9d4a13 (Initial commit)
}
private String validateIfAccountBlocklisted(String accountId) {
@@ -554,6 +582,43 @@ private Future ensureAccountActive(Account account) {
: Future.succeededFuture(account);
}
+<<<<<<< HEAD
+=======
+ /**
+ * Extracts publisher id either from {@link BidRequest}.app.publisher or {@link BidRequest}.site.publisher.
+ * If neither is present returns empty string.
+ */
+ private String accountIdFrom(BidRequest bidRequest) {
+ final App app = bidRequest.getApp();
+ final Publisher appPublisher = app != null ? app.getPublisher() : null;
+ final Site site = bidRequest.getSite();
+ final Publisher sitePublisher = site != null ? site.getPublisher() : null;
+ final Dooh dooh = bidRequest.getDooh();
+ final Publisher doohPublisher = dooh != null ? dooh.getPublisher() : null;
+
+ final Publisher publisher = ObjectUtils.firstNonNull(appPublisher, doohPublisher, sitePublisher);
+ final String publisherId = publisher != null ? resolvePublisherId(publisher) : null;
+ return ObjectUtils.defaultIfNull(publisherId, StringUtils.EMPTY);
+ }
+
+ /**
+ * Resolves what value should be used as a publisher id - either taken from publisher.ext.parentAccount
+ * or publisher.id in this respective priority.
+ */
+ private String resolvePublisherId(Publisher publisher) {
+ final String parentAccountId = parentAccountIdFromExtPublisher(publisher.getExt());
+ return ObjectUtils.defaultIfNull(parentAccountId, publisher.getId());
+ }
+
+ /**
+ * Parses publisher.ext and returns parentAccount value from it. Returns null if any parsing error occurs.
+ */
+ private String parentAccountIdFromExtPublisher(ExtPublisher extPublisher) {
+ final ExtPublisherPrebid extPublisherPrebid = extPublisher != null ? extPublisher.getPrebid() : null;
+ return extPublisherPrebid != null ? StringUtils.stripToNull(extPublisherPrebid.getParentAccount()) : null;
+ }
+
+>>>>>>> 04d9d4a13 (Initial commit)
private Future wrapFailure(Throwable exception, String accountId, HttpRequestContext httpRequest) {
if (exception instanceof UnauthorizedAccountException) {
return Future.failedFuture(exception);
diff --git a/src/main/java/org/prebid/server/bidder/alvads/AlvadsBidder.java b/src/main/java/org/prebid/server/bidder/alvads/AlvadsBidder.java
new file mode 100644
index 00000000000..b41756a29b6
--- /dev/null
+++ b/src/main/java/org/prebid/server/bidder/alvads/AlvadsBidder.java
@@ -0,0 +1,194 @@
+package org.prebid.server.bidder.alvads;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.iab.openrtb.request.BidRequest;
+import com.iab.openrtb.request.Imp;
+import com.iab.openrtb.response.Bid;
+import com.iab.openrtb.response.BidResponse;
+import io.vertx.core.http.HttpMethod;
+import org.apache.commons.collections4.CollectionUtils;
+import org.prebid.server.bidder.Bidder;
+import org.prebid.server.bidder.alvads.model.AlvaAdsImp;
+import org.prebid.server.bidder.alvads.model.AlvaAdsSite;
+import org.prebid.server.bidder.alvads.model.AlvadsRequestORTB;
+import org.prebid.server.bidder.model.BidderBid;
+import org.prebid.server.bidder.model.BidderCall;
+import org.prebid.server.bidder.model.BidderError;
+import org.prebid.server.bidder.model.HttpRequest;
+import org.prebid.server.bidder.model.Result;
+import org.prebid.server.exception.PreBidException;
+import org.prebid.server.json.JacksonMapper;
+import org.prebid.server.proto.openrtb.ext.ExtPrebid;
+import org.prebid.server.proto.openrtb.ext.request.alvads.AlvadsImpExt;
+import org.prebid.server.proto.openrtb.ext.response.BidType;
+import org.prebid.server.util.HttpUtil;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class AlvadsBidder implements Bidder {
+
+ private final String endpointUrl;
+ private final JacksonMapper mapper;
+ private static final TypeReference> ALVADS_EXT_TYPE_REFERENCE =
+ new TypeReference<>() { };
+
+ public AlvadsBidder(String endpointUrl, JacksonMapper mapper) {
+ this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl));
+ this.mapper = Objects.requireNonNull(mapper);
+ }
+
+ @Override
+ public final Result>> makeHttpRequests(BidRequest bidRequest) {
+ final List errors = new ArrayList<>();
+ final List> httpRequests = new ArrayList<>();
+
+ for (Imp imp : bidRequest.getImp()) {
+ try {
+ final AlvadsImpExt impExt = parseImpExt(imp);
+ final HttpRequest request = makeHttpRequest(bidRequest, imp, impExt);
+ httpRequests.add(request);
+ } catch (PreBidException e) {
+ errors.add(BidderError.badInput(e.getMessage()));
+ }
+ }
+
+ if (httpRequests.isEmpty()) {
+ errors.add(BidderError.badInput("found no valid impressions"));
+ return Result.withErrors(errors);
+ }
+
+ return Result.of(httpRequests, errors);
+ }
+
+ private HttpRequest makeHttpRequest(BidRequest request, Imp imp, AlvadsImpExt impExt) {
+ final String resolvedUrl = impExt.getEndPointUrl() != null ? impExt.getEndPointUrl() : endpointUrl;
+ try {
+ URI.create(resolvedUrl);
+ } catch (IllegalArgumentException e) {
+ throw new PreBidException("Invalid endpoint URL: " + resolvedUrl, e);
+ }
+
+ Map bannerMap = null;
+ if (imp.getBanner() != null) {
+ bannerMap = new HashMap<>();
+ if (imp.getBanner().getW() != null) {
+ bannerMap.put("w", imp.getBanner().getW());
+ }
+ if (imp.getBanner().getH() != null) {
+ bannerMap.put("h", imp.getBanner().getH());
+ }
+ }
+
+ // Build video map safely
+ Map videoMap = null;
+ if (imp.getVideo() != null) {
+ videoMap = new HashMap<>();
+ if (imp.getVideo().getW() != null) {
+ videoMap.put("w", imp.getVideo().getW());
+ }
+ if (imp.getVideo().getH() != null) {
+ videoMap.put("h", imp.getVideo().getH());
+ }
+ }
+
+ final AlvaAdsImp impObj = AlvaAdsImp.builder()
+ .id(imp.getId())
+ .tagid(imp.getTagid())
+ .bidfloor(imp.getBidfloor())
+ .banner(bannerMap)
+ .video(videoMap)
+ .build();
+
+ final AlvaAdsSite siteObj = AlvaAdsSite.builder()
+ .page(request.getSite() != null ? request.getSite().getPage() : null)
+ .ref(request.getSite() != null ? request.getSite().getPage() : null)
+ .publisher(Map.of("id", impExt.getPublisherUniqueId()))
+ .build();
+
+ final AlvadsRequestORTB alvadsRequest = AlvadsRequestORTB.builder()
+ .id(request.getId())
+ .imp(List.of(impObj))
+ .device(request.getDevice())
+ .user(request.getUser())
+ .regs(request.getRegs())
+ .site(siteObj)
+ .build();
+
+ return HttpRequest.builder()
+ .method(HttpMethod.POST)
+ .uri(resolvedUrl)
+ .headers(HttpUtil.headers())
+ .payload(alvadsRequest)
+ .body(mapper.encodeToBytes(alvadsRequest))
+ .impIds(alvadsRequest.getImp().stream()
+ .map(AlvaAdsImp::getId)
+ .collect(Collectors.toSet()))
+ .build();
+ }
+
+ private AlvadsImpExt parseImpExt(Imp imp) {
+ try {
+ return mapper.mapper().convertValue(imp.getExt(), ALVADS_EXT_TYPE_REFERENCE).getBidder();
+ } catch (IllegalArgumentException e) {
+ throw new PreBidException("Missing or invalid bidder ext in impression with id: " + imp.getId());
+ }
+ }
+
+ @Override
+ public final Result> makeBids(BidderCall httpCall,
+ BidRequest bidRequest) {
+ try {
+ final BidResponse bidResponse = mapper.decodeValue(
+ httpCall.getResponse().getBody(),
+ BidResponse.class
+ );
+ return Result.withValues(extractBids(bidResponse, httpCall.getRequest().getPayload()));
+ } catch (org.prebid.server.json.DecodeException e) {
+ return Result.withError(BidderError.badServerResponse(
+ "Failed to decode BidResponse: " + e.getMessage()
+ ));
+ }
+ }
+
+ private List extractBids(BidResponse bidResponse, AlvadsRequestORTB request) {
+ if (bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())) {
+ return Collections.emptyList();
+ }
+ return bidsFromResponse(bidResponse, request);
+ }
+
+ private List bidsFromResponse(BidResponse bidResponse, AlvadsRequestORTB request) {
+ return bidResponse.getSeatbid().stream()
+ .flatMap(seatBid -> seatBid == null || seatBid.getBid() == null
+ ? Stream.empty()
+ : seatBid.getBid().stream())
+ .map(bid -> BidderBid.of(bid, getBidType(bid, request), bidResponse.getCur()))
+ .toList();
+ }
+
+ private BidType getBidType(Bid bid, AlvadsRequestORTB request) {
+ final ExtBidAlvads bidExt = getBidExt(bid);
+ if (bidExt == null) {
+ return BidType.banner;
+ }
+ final BidType crtype = bidExt.getCrtype();
+ return request.getImp().get(0).getVideo() != null ? BidType.video : crtype == null ? BidType.banner : crtype;
+ }
+
+ private ExtBidAlvads getBidExt(Bid bid) {
+ try {
+ return mapper.mapper().convertValue(bid.getExt(), ExtBidAlvads.class);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/java/org/prebid/server/bidder/alvads/ExtBidAlvads.java b/src/main/java/org/prebid/server/bidder/alvads/ExtBidAlvads.java
new file mode 100644
index 00000000000..ad20e1f6415
--- /dev/null
+++ b/src/main/java/org/prebid/server/bidder/alvads/ExtBidAlvads.java
@@ -0,0 +1,14 @@
+package org.prebid.server.bidder.alvads;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+import org.prebid.server.proto.openrtb.ext.response.BidType;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Data
+public class ExtBidAlvads {
+
+ private BidType crtype;
+}
diff --git a/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsImp.java b/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsImp.java
new file mode 100644
index 00000000000..de791cf7b9b
--- /dev/null
+++ b/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsImp.java
@@ -0,0 +1,20 @@
+package org.prebid.server.bidder.alvads.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Builder;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Data
+@Builder
+public class AlvaAdsImp {
+
+ private String id;
+ private Map banner;
+ private Map video;
+ private String tagid;
+ private BigDecimal bidfloor;
+}
diff --git a/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsSite.java b/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsSite.java
new file mode 100644
index 00000000000..a0d46fc615f
--- /dev/null
+++ b/src/main/java/org/prebid/server/bidder/alvads/model/AlvaAdsSite.java
@@ -0,0 +1,17 @@
+package org.prebid.server.bidder.alvads.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Data
+@Builder
+public class AlvaAdsSite {
+
+ private String page;
+ private String ref;
+ private Map publisher;
+}
diff --git a/src/main/java/org/prebid/server/bidder/alvads/model/AlvadsRequestORTB.java b/src/main/java/org/prebid/server/bidder/alvads/model/AlvadsRequestORTB.java
new file mode 100644
index 00000000000..4c5855855fe
--- /dev/null
+++ b/src/main/java/org/prebid/server/bidder/alvads/model/AlvadsRequestORTB.java
@@ -0,0 +1,22 @@
+package org.prebid.server.bidder.alvads.model;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.iab.openrtb.request.Device;
+import com.iab.openrtb.request.Regs;
+import com.iab.openrtb.request.User;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.List;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Data
+@Builder
+public class AlvadsRequestORTB {
+ private String id;
+ private List imp;
+ private Device device;
+ private User user;
+ private Regs regs;
+ private AlvaAdsSite site;
+}
diff --git a/src/main/java/org/prebid/server/bidder/ix/IxBidder.java b/src/main/java/org/prebid/server/bidder/ix/IxBidder.java
index 5770772c1bd..093d9e14c17 100644
--- a/src/main/java/org/prebid/server/bidder/ix/IxBidder.java
+++ b/src/main/java/org/prebid/server/bidder/ix/IxBidder.java
@@ -21,6 +21,10 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.prebid.server.bidder.Bidder;
+<<<<<<< HEAD
+=======
+import org.prebid.server.bidder.ix.model.request.IxDiag;
+>>>>>>> 04d9d4a13 (Initial commit)
import org.prebid.server.bidder.ix.model.response.IxBidResponse;
import org.prebid.server.bidder.ix.model.response.IxExtBidResponse;
import org.prebid.server.bidder.ix.model.response.NativeV11Wrapper;
@@ -64,8 +68,11 @@ public class IxBidder implements Bidder {
private static final TypeReference> IX_EXT_TYPE_REFERENCE =
new TypeReference<>() {
};
+<<<<<<< HEAD
private static final String PBSP_JAVA = "java";
private static final String PBS_VERSION_UNKNOWN = "unknown";
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
private final String endpointUrl;
private final PrebidVersionProvider prebidVersionProvider;
@@ -205,11 +212,19 @@ private ExtRequest modifyRequestExt(ExtRequest extRequest, Set siteIds)
modifiedExt = ExtRequest.empty();
}
+<<<<<<< HEAD
modifiedExt.addProperty("ixdiag", makeDiagData(extRequest, siteIds));
return modifiedExt;
}
private ObjectNode makeDiagData(ExtRequest extRequest, Set siteIds) {
+=======
+ modifiedExt.addProperty("ixdiag", mapper.mapper().valueToTree(makeDiagData(extRequest, siteIds)));
+ return modifiedExt;
+ }
+
+ private IxDiag makeDiagData(ExtRequest extRequest, Set siteIds) {
+>>>>>>> 04d9d4a13 (Initial commit)
final String pbjsv = Optional.ofNullable(extRequest)
.map(ExtRequest::getPrebid)
.map(ExtRequestPrebid::getChannel)
@@ -222,6 +237,7 @@ private ObjectNode makeDiagData(ExtRequest extRequest, Set siteIds) {
? siteIds.stream().sorted().collect(Collectors.joining(", "))
: null;
+<<<<<<< HEAD
final ObjectNode ixdiag = Optional.ofNullable(extRequest)
.map(ext -> ext.getProperty("ixdiag"))
.filter(JsonNode::isObject)
@@ -239,6 +255,9 @@ private ObjectNode makeDiagData(ExtRequest extRequest, Set siteIds) {
}
return ixdiag;
+=======
+ return IxDiag.of(pbsv, pbjsv, multipleSiteIds);
+>>>>>>> 04d9d4a13 (Initial commit)
}
@Override
diff --git a/src/main/java/org/prebid/server/bidder/ix/model/request/IxDiag.java b/src/main/java/org/prebid/server/bidder/ix/model/request/IxDiag.java
new file mode 100644
index 00000000000..b3323edb849
--- /dev/null
+++ b/src/main/java/org/prebid/server/bidder/ix/model/request/IxDiag.java
@@ -0,0 +1,15 @@
+package org.prebid.server.bidder.ix.model.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Value;
+
+@Value(staticConstructor = "of")
+public class IxDiag {
+
+ String pbsv;
+
+ String pbjsv;
+
+ @JsonProperty("multipleSiteIds")
+ String multipleSiteIds;
+}
diff --git a/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java b/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java
index ec6c9718ea5..a2cba856d74 100644
--- a/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java
+++ b/src/main/java/org/prebid/server/bidder/onetag/OnetagBidder.java
@@ -22,6 +22,10 @@
import org.prebid.server.util.BidderUtil;
import org.prebid.server.util.HttpUtil;
+<<<<<<< HEAD
+=======
+import java.util.ArrayList;
+>>>>>>> 04d9d4a13 (Initial commit)
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -44,18 +48,31 @@ public OnetagBidder(String endpointUrl, JacksonMapper mapper) {
@Override
public Result>> makeHttpRequests(BidRequest request) {
+<<<<<<< HEAD
+=======
+ final List modifiedImps = new ArrayList<>();
+>>>>>>> 04d9d4a13 (Initial commit)
String requestPubId = null;
for (Imp imp : request.getImp()) {
try {
final ExtImpOnetag impExt = parseImpExt(imp);
requestPubId = resolveAndValidatePubId(impExt.getPubId(), requestPubId);
+<<<<<<< HEAD
+=======
+
+ modifiedImps.add(imp.toBuilder().ext(impExt.getExt()).build());
+>>>>>>> 04d9d4a13 (Initial commit)
} catch (PreBidException e) {
return Result.withError(BidderError.badInput(e.getMessage()));
}
}
+<<<<<<< HEAD
final String url = endpointUrl.replace(URL_PUBLISHER_ID_MACRO, StringUtils.defaultString(requestPubId));
return Result.withValue(BidderUtil.defaultRequest(request, url, mapper));
+=======
+ return Result.withValue(createRequest(request, modifiedImps, requestPubId));
+>>>>>>> 04d9d4a13 (Initial commit)
}
private ExtImpOnetag parseImpExt(Imp imp) {
@@ -66,8 +83,13 @@ private ExtImpOnetag parseImpExt(Imp imp) {
}
}
+<<<<<<< HEAD
private static String resolveAndValidatePubId(String impExtPubId, String requestPubId) {
if (StringUtils.isBlank(impExtPubId)) {
+=======
+ private String resolveAndValidatePubId(String impExtPubId, String requestPubId) {
+ if (StringUtils.isEmpty(impExtPubId)) {
+>>>>>>> 04d9d4a13 (Initial commit)
throw new PreBidException("The publisher ID must not be empty");
}
if (requestPubId != null && !impExtPubId.equals(requestPubId)) {
@@ -76,6 +98,16 @@ private static String resolveAndValidatePubId(String impExtPubId, String request
return impExtPubId;
}
+<<<<<<< HEAD
+=======
+ private HttpRequest createRequest(BidRequest request, List imps, String pubId) {
+ final String url = endpointUrl.replace(URL_PUBLISHER_ID_MACRO, pubId);
+ final BidRequest outgoingRequest = request.toBuilder().imp(imps).build();
+
+ return BidderUtil.defaultRequest(outgoingRequest, url, mapper);
+ }
+
+>>>>>>> 04d9d4a13 (Initial commit)
@Override
public final Result> makeBids(BidderCall httpCall, BidRequest bidRequest) {
try {
diff --git a/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java b/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java
index 150c37fd255..a4db210a7ed 100644
--- a/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java
+++ b/src/main/java/org/prebid/server/bidder/smartadserver/SmartadserverBidder.java
@@ -1,7 +1,10 @@
package org.prebid.server.bidder.smartadserver;
import com.fasterxml.jackson.core.type.TypeReference;
+<<<<<<< HEAD
import com.fasterxml.jackson.databind.node.ObjectNode;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
import com.iab.openrtb.request.BidRequest;
import com.iab.openrtb.request.Imp;
import com.iab.openrtb.request.Publisher;
@@ -31,7 +34,10 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+<<<<<<< HEAD
import java.util.LinkedHashMap;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
import java.util.List;
import java.util.Objects;
@@ -42,18 +48,26 @@ public class SmartadserverBidder implements Bidder {
};
private final String endpointUrl;
+<<<<<<< HEAD
private final String secondaryEndpointUrl;
private final JacksonMapper mapper;
public SmartadserverBidder(String endpointUrl, String secondaryEndpointUrl, JacksonMapper mapper) {
this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl));
this.secondaryEndpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(secondaryEndpointUrl));
+=======
+ private final JacksonMapper mapper;
+
+ public SmartadserverBidder(String endpointUrl, JacksonMapper mapper) {
+ this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl));
+>>>>>>> 04d9d4a13 (Initial commit)
this.mapper = Objects.requireNonNull(mapper);
}
@Override
public Result>> makeHttpRequests(BidRequest request) {
final List errors = new ArrayList<>();
+<<<<<<< HEAD
final List modifiedImps = new ArrayList<>();
final LinkedHashMap impToExtImpMap = new LinkedHashMap<>();
@@ -64,11 +78,21 @@ public Result>> makeHttpRequests(BidRequest request
final ExtImpSmartadserver extImp = parseImpExt(imp);
isProgrammaticGuaranteed |= extImp.isProgrammaticGuaranteed();
impToExtImpMap.put(imp, extImp);
+=======
+ final List imps = new ArrayList<>();
+ ExtImpSmartadserver extImp = null;
+
+ for (Imp imp : request.getImp()) {
+ try {
+ extImp = parseImpExt(imp);
+ imps.add(imp);
+>>>>>>> 04d9d4a13 (Initial commit)
} catch (PreBidException e) {
errors.add(BidderError.badInput(e.getMessage()));
}
}
+<<<<<<< HEAD
if (impToExtImpMap.isEmpty()) {
return Result.withErrors(errors);
}
@@ -86,6 +110,18 @@ public Result>> makeHttpRequests(BidRequest request
outgoingRequest,
makeUrl(isProgrammaticGuaranteed),
mapper);
+=======
+ if (imps.isEmpty()) {
+ return Result.withErrors(errors);
+ }
+
+ final BidRequest outgoingRequest = request.toBuilder()
+ .imp(imps)
+ .site(modifySite(request.getSite(), extImp.getNetworkId()))
+ .build();
+
+ final HttpRequest httpRequest = BidderUtil.defaultRequest(outgoingRequest, makeUrl(), mapper);
+>>>>>>> 04d9d4a13 (Initial commit)
return Result.of(Collections.singletonList(httpRequest), errors);
}
@@ -97,6 +133,7 @@ private ExtImpSmartadserver parseImpExt(Imp imp) {
}
}
+<<<<<<< HEAD
private Imp modifyImp(Imp imp, ExtImpSmartadserver extImp, String impExtKey) {
final ObjectNode impExt = imp.getExt().deepCopy();
impExt.remove("bidder");
@@ -104,6 +141,8 @@ private Imp modifyImp(Imp imp, ExtImpSmartadserver extImp, String impExtKey) {
return imp.toBuilder().ext(impExt).build();
}
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
private static Site modifySite(Site site, Integer networkId) {
final Site.SiteBuilder siteBuilder = site != null ? site.toBuilder() : Site.builder();
final Publisher sitePublisher = site != null ? site.getPublisher() : null;
@@ -119,6 +158,7 @@ private static Publisher modifyPublisher(Publisher publisher, Integer networkId)
return publisherBuilder.id(String.valueOf(networkId)).build();
}
+<<<<<<< HEAD
private String makeUrl(boolean isProgrammaticGuaranteed) {
final String url = isProgrammaticGuaranteed ? secondaryEndpointUrl : endpointUrl;
try {
@@ -135,6 +175,19 @@ private String makeUrl(boolean isProgrammaticGuaranteed) {
} catch (URISyntaxException e) {
throw new PreBidException("Malformed URL: %s.".formatted(url));
}
+=======
+ private String makeUrl() {
+ final URI uri;
+ try {
+ uri = new URI(endpointUrl);
+ } catch (URISyntaxException e) {
+ throw new PreBidException("Malformed URL: %s.".formatted(endpointUrl));
+ }
+ return new URIBuilder(uri)
+ .setPath(StringUtils.removeEnd(uri.getPath(), "/") + "/api/bid")
+ .addParameter("callerId", "5")
+ .toString();
+>>>>>>> 04d9d4a13 (Initial commit)
}
@Override
diff --git a/src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java b/src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java
index fd652ebb8ff..7a310156c90 100644
--- a/src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java
+++ b/src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java
@@ -19,6 +19,7 @@
*/
public class SettingsCacheNotificationHandler implements Handler {
+<<<<<<< HEAD
private final String endpoint;
private final CacheNotificationListener cacheNotificationListener;
private final JacksonMapper mapper;
@@ -30,6 +31,17 @@ public SettingsCacheNotificationHandler(String endpoint,
this.endpoint = Objects.requireNonNull(endpoint);
this.cacheNotificationListener = Objects.requireNonNull(cacheNotificationListener);
this.mapper = Objects.requireNonNull(mapper);
+=======
+ private final CacheNotificationListener cacheNotificationListener;
+ private final JacksonMapper mapper;
+ private final String endpoint;
+
+ public SettingsCacheNotificationHandler(CacheNotificationListener cacheNotificationListener, JacksonMapper mapper,
+ String endpoint) {
+ this.cacheNotificationListener = Objects.requireNonNull(cacheNotificationListener);
+ this.mapper = Objects.requireNonNull(mapper);
+ this.endpoint = Objects.requireNonNull(endpoint);
+>>>>>>> 04d9d4a13 (Initial commit)
}
@Override
@@ -96,18 +108,26 @@ private void doFail(RoutingContext routingContext) {
}
private void respondWithBadRequest(RoutingContext routingContext, String body) {
+<<<<<<< HEAD
HttpUtil.executeSafely(
routingContext,
endpoint,
+=======
+ HttpUtil.executeSafely(routingContext, endpoint,
+>>>>>>> 04d9d4a13 (Initial commit)
response -> response
.setStatusCode(HttpResponseStatus.BAD_REQUEST.code())
.end(body));
}
private void respondWith(RoutingContext routingContext, HttpResponseStatus status) {
+<<<<<<< HEAD
HttpUtil.executeSafely(
routingContext,
endpoint,
+=======
+ HttpUtil.executeSafely(routingContext, endpoint,
+>>>>>>> 04d9d4a13 (Initial commit)
response -> response
.setStatusCode(status.code())
.end());
diff --git a/src/main/java/org/prebid/server/metric/AccountMetrics.java b/src/main/java/org/prebid/server/metric/AccountMetrics.java
index 6bd479b7ea3..669bc1622d8 100644
--- a/src/main/java/org/prebid/server/metric/AccountMetrics.java
+++ b/src/main/java/org/prebid/server/metric/AccountMetrics.java
@@ -23,7 +23,10 @@ class AccountMetrics extends UpdatableMetrics {
private final ResponseMetrics responseMetrics;
private final HooksMetrics hooksMetrics;
private final ActivitiesMetrics activitiesMetrics;
+<<<<<<< HEAD
private final ProfileMetrics profileMetrics;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
AccountMetrics(MetricRegistry metricRegistry, CounterType counterType, String account) {
super(Objects.requireNonNull(metricRegistry), Objects.requireNonNull(counterType),
@@ -37,7 +40,10 @@ class AccountMetrics extends UpdatableMetrics {
responseMetrics = new ResponseMetrics(metricRegistry, counterType, createPrefix(account));
hooksMetrics = new HooksMetrics(metricRegistry, counterType, createPrefix(account));
activitiesMetrics = new ActivitiesMetrics(metricRegistry, counterType, createPrefix(account));
+<<<<<<< HEAD
profileMetrics = new ProfileMetrics(metricRegistry, counterType, createPrefix(account));
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
}
private static String createPrefix(String account) {
@@ -75,8 +81,11 @@ HooksMetrics hooks() {
ActivitiesMetrics activities() {
return activitiesMetrics;
}
+<<<<<<< HEAD
ProfileMetrics profiles() {
return profileMetrics;
}
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
}
diff --git a/src/main/java/org/prebid/server/metric/MetricName.java b/src/main/java/org/prebid/server/metric/MetricName.java
index 4d562aa4122..55e79ea432f 100644
--- a/src/main/java/org/prebid/server/metric/MetricName.java
+++ b/src/main/java/org/prebid/server/metric/MetricName.java
@@ -156,10 +156,14 @@ public enum MetricName {
// activity
disallowed_count("disallowed.count"),
+<<<<<<< HEAD
processed_rules_count("processedrules.count"),
// profiles
limit_exceeded;
+=======
+ processed_rules_count("processedrules.count");
+>>>>>>> 04d9d4a13 (Initial commit)
private final String name;
diff --git a/src/main/java/org/prebid/server/metric/Metrics.java b/src/main/java/org/prebid/server/metric/Metrics.java
index c10d3301391..11867c577f8 100644
--- a/src/main/java/org/prebid/server/metric/Metrics.java
+++ b/src/main/java/org/prebid/server/metric/Metrics.java
@@ -59,7 +59,10 @@ public class Metrics extends UpdatableMetrics {
private final CurrencyRatesMetrics currencyRatesMetrics;
private final Map settingsCacheMetrics;
private final HooksMetrics hooksMetrics;
+<<<<<<< HEAD
private final ProfileMetrics profileMetrics;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
public Metrics(MetricRegistry metricRegistry,
CounterType counterType,
@@ -98,7 +101,10 @@ public Metrics(MetricRegistry metricRegistry,
currencyRatesMetrics = new CurrencyRatesMetrics(metricRegistry, counterType);
settingsCacheMetrics = new HashMap<>();
hooksMetrics = new HooksMetrics(metricRegistry, counterType);
+<<<<<<< HEAD
profileMetrics = new ProfileMetrics(metricRegistry, counterType);
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
}
RequestsMetrics requests() {
@@ -729,6 +735,7 @@ public void updateAccountActivityProcessedRulesCount(String account) {
forAccount(account).activities().incCounter(MetricName.processed_rules_count);
}
+<<<<<<< HEAD
public void updateProfileMetric(MetricName metricName) {
profileMetrics.incCounter(metricName);
}
@@ -737,6 +744,8 @@ public void updateAccountProfileMetric(String account, MetricName metricName) {
forAccount(account).profiles().incCounter(metricName);
}
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
private static class HookMetricMapper {
private static final EnumMap STATUS_TO_METRIC =
diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java
index 33ac57c13c0..dd18d64f7da 100644
--- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java
+++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtImpPrebid.java
@@ -21,11 +21,14 @@ public class ExtImpPrebid {
ExtStoredRequest storedrequest;
/**
+<<<<<<< HEAD
* Defines the contract for bidrequest.imp[i].ext.prebid.profiles
*/
List profiles;
/**
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
* Defines the contract for bidrequest.imp[i].ext.prebid.storedauctionresponse
*/
@JsonProperty("storedauctionresponse")
diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java
index 25dffdc486c..c8f8a119049 100644
--- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java
+++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/ExtRequestPrebid.java
@@ -77,11 +77,14 @@ public class ExtRequestPrebid {
ExtStoredRequest storedrequest;
/**
+<<<<<<< HEAD
* Defines the contract for bidrequest.ext.prebid.profiles
*/
List profiles;
/**
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
* Defines the contract for bidrequest.ext.prebid.storedauctionresponse
*/
@JsonProperty("storedauctionresponse")
diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/alvads/AlvadsImpExt.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/alvads/AlvadsImpExt.java
new file mode 100644
index 00000000000..eb4c0c5eea9
--- /dev/null
+++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/alvads/AlvadsImpExt.java
@@ -0,0 +1,13 @@
+package org.prebid.server.proto.openrtb.ext.request.alvads;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Value;
+
+@Value(staticConstructor = "of")
+public class AlvadsImpExt {
+ @JsonProperty("publisherUniqueId")
+ String publisherUniqueId;
+
+ @JsonProperty("endPointUrl")
+ String endPointUrl;
+}
diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java b/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java
index efc8de91a5f..2bb20837075 100644
--- a/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java
+++ b/src/main/java/org/prebid/server/proto/openrtb/ext/request/smartadserver/ExtImpSmartadserver.java
@@ -3,6 +3,12 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Value;
+<<<<<<< HEAD
+=======
+/**
+ * Defines the contract for bidrequest.imp[i].ext.smartadserver
+ */
+>>>>>>> 04d9d4a13 (Initial commit)
@Value(staticConstructor = "of")
public class ExtImpSmartadserver {
@@ -17,7 +23,10 @@ public class ExtImpSmartadserver {
@JsonProperty("networkId")
Integer networkId;
+<<<<<<< HEAD
@JsonProperty(value = "programmaticGuaranteed", access = JsonProperty.Access.WRITE_ONLY)
boolean programmaticGuaranteed;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
}
diff --git a/src/main/java/org/prebid/server/settings/ApplicationSettings.java b/src/main/java/org/prebid/server/settings/ApplicationSettings.java
index 2f3ca855668..50b62173570 100644
--- a/src/main/java/org/prebid/server/settings/ApplicationSettings.java
+++ b/src/main/java/org/prebid/server/settings/ApplicationSettings.java
@@ -3,13 +3,17 @@
import io.vertx.core.Future;
import org.prebid.server.execution.timeout.Timeout;
import org.prebid.server.settings.model.Account;
+<<<<<<< HEAD
import org.prebid.server.settings.model.Profile;
+=======
+>>>>>>> 04d9d4a13 (Initial commit)
import org.prebid.server.settings.model.StoredDataResult;
import org.prebid.server.settings.model.StoredResponseDataResult;
import java.util.Map;
import java.util.Set;
+<<<<<<< HEAD
public interface ApplicationSettings {
Future getAccountById(String accountId, Timeout timeout);
@@ -36,5 +40,51 @@ Future> getProfiles(String accountId,
Future getStoredResponses(Set responseIds, Timeout timeout);
+=======
+/**
+ * Defines the contract of getting application settings (account, stored ad unit configurations and
+ * stored requests and imps) from the source.
+ *
+ * @see FileApplicationSettings
+ * @see DatabaseApplicationSettings
+ * @see HttpApplicationSettings
+ * @see CachingApplicationSettings
+ * @see CompositeApplicationSettings
+ */
+public interface ApplicationSettings {
+
+ /**
+ * Returns {@link Account} for the given account ID.
+ */
+ Future getAccountById(String accountId, Timeout timeout);
+
+ /**
+ * Fetches stored requests and imps by IDs.
+ */
+ Future getStoredData(String accountId, Set requestIds, Set impIds,
+ Timeout timeout);
+
+ /**
+ * Fetches AMP stored requests and imps by IDs.
+ */
+ Future getAmpStoredData(String accountId, Set requestIds, Set impIds,
+ Timeout timeout);
+
+ /**
+ * Fetches Video stored requests and imps by IDs.
+ */
+ Future getVideoStoredData(String accountId, Set requestIds, Set impIds,
+ Timeout timeout);
+
+ /**
+ * Fetches stored response by IDs.
+ */
+ Future getStoredResponses(Set responseIds, Timeout timeout);
+
+
+ /**
+ * Fetches video category
+ */
+>>>>>>> 04d9d4a13 (Initial commit)
Future