Skip to content

Commit aec416d

Browse files
adjust code after review
1 parent a64deb1 commit aec416d

2 files changed

Lines changed: 84 additions & 128 deletions

File tree

src/main/java/org/prebid/server/bidder/showheroes/ShowheroesBidder.java

Lines changed: 84 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22

33
import com.fasterxml.jackson.core.type.TypeReference;
44
import com.fasterxml.jackson.databind.JsonNode;
5-
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
65
import com.fasterxml.jackson.databind.node.ObjectNode;
6+
import com.iab.openrtb.request.App;
77
import com.iab.openrtb.request.BidRequest;
88
import com.iab.openrtb.request.Imp;
9+
import com.iab.openrtb.request.Site;
910
import com.iab.openrtb.request.Source;
1011
import com.iab.openrtb.response.Bid;
1112
import com.iab.openrtb.response.BidResponse;
1213
import com.iab.openrtb.response.SeatBid;
1314
import org.apache.commons.collections4.CollectionUtils;
15+
import org.apache.commons.lang3.ObjectUtils;
16+
import org.apache.commons.lang3.StringUtils;
1417
import org.prebid.server.bidder.Bidder;
1518
import org.prebid.server.bidder.model.BidderBid;
1619
import org.prebid.server.bidder.model.BidderCall;
@@ -43,7 +46,6 @@
4346
public class ShowheroesBidder implements Bidder<BidRequest> {
4447

4548
private static final String BID_CURRENCY = "EUR";
46-
private static final String DEFAULT_ORTB_CURRENCY = "USD";
4749
private static final String PBSP_JAVA = "java";
4850
private static final TypeReference<ExtPrebid<?, ExtImpShowheroes>> SHOWHEROES_EXT_TYPE_REFERENCE =
4951
new TypeReference<>() {
@@ -55,9 +57,9 @@ public class ShowheroesBidder implements Bidder<BidRequest> {
5557
private final String pbsVersion;
5658

5759
public ShowheroesBidder(String endpointUrl,
58-
CurrencyConversionService currencyConversionService,
59-
PrebidVersionProvider prebidVersionProvider,
60-
JacksonMapper mapper) {
60+
CurrencyConversionService currencyConversionService,
61+
PrebidVersionProvider prebidVersionProvider,
62+
JacksonMapper mapper) {
6163

6264
this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl));
6365
this.currencyConversionService = Objects.requireNonNull(currencyConversionService);
@@ -66,151 +68,123 @@ public ShowheroesBidder(String endpointUrl,
6668
this.pbsVersion = prebidVersionProvider.getNameVersionRecord();
6769
}
6870

69-
private BidderError validate(BidRequest bidRequest) {
70-
// request must contain site object with page or app object with bundle
71-
if (bidRequest.getSite() == null && bidRequest.getApp() == null) {
71+
@Override
72+
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) {
73+
final BidderError validationError = validate(request.getSite(), request.getApp());
74+
if (validationError != null) {
75+
return Result.withError(validationError);
76+
}
77+
78+
final List<BidderError> errors = new ArrayList<>();
79+
80+
final ExtRequestPrebidChannel prebidChannel = getPrebidChannel(request);
81+
final List<Imp> modifiedImps = new ArrayList<>(request.getImp().size());
82+
83+
for (Imp impression : request.getImp()) {
84+
try {
85+
modifiedImps.add(modifyImp(request, impression, prebidChannel));
86+
} catch (Exception e) {
87+
errors.add(BidderError.badInput(e.getMessage()));
88+
}
89+
}
90+
91+
if (modifiedImps.isEmpty()) {
92+
return Result.withErrors(errors);
93+
}
94+
95+
final Source source = modifySource(request);
96+
final BidRequest modifiedRequest = request.toBuilder().imp(modifiedImps).source(source).build();
97+
final HttpRequest<BidRequest> httpRequest = BidderUtil.defaultRequest(modifiedRequest, endpointUrl, mapper);
98+
99+
return Result.of(Collections.singletonList(httpRequest), errors);
100+
}
101+
102+
private static BidderError validate(Site site, App app) {
103+
if (site == null && app == null) {
72104
return BidderError.badInput("BidRequest must contain one of site or app");
73105
}
74-
if (bidRequest.getSite() != null && bidRequest.getSite().getPage() == null) {
106+
if (site != null && site.getPage() == null) {
75107
return BidderError.badInput("BidRequest.site.page is required");
76108
}
77-
if (bidRequest.getApp() != null && bidRequest.getApp().getBundle() == null) {
109+
if (app != null && app.getBundle() == null) {
78110
return BidderError.badInput("BidRequest.app.bundle is required");
79111
}
80112
return null;
81113
}
82114

83-
private ExtRequestPrebidChannel getPrebidChannel(BidRequest bidRequest) {
115+
private static ExtRequestPrebidChannel getPrebidChannel(BidRequest bidRequest) {
84116
return Optional.ofNullable(bidRequest.getExt())
85117
.map(ExtRequest::getPrebid)
86118
.map(ExtRequestPrebid::getChannel)
87119
.orElse(null);
88120
}
89121

90-
private Imp processImpression(BidRequest bidRequest, Imp imp, ExtRequestPrebidChannel prebidChannel) {
91-
if (imp.getBanner() == null && imp.getVideo() == null) {
92-
throw new PreBidException("Impression must contain one of banner or video");
93-
}
94-
95-
final ExtImpShowheroes extImpShowheroes = mapper.mapper()
96-
.convertValue(imp.getExt(), SHOWHEROES_EXT_TYPE_REFERENCE).getBidder();
97-
if (extImpShowheroes == null || extImpShowheroes.getUnitId() == null
98-
|| extImpShowheroes.getUnitId().isBlank()) {
99-
throw new PreBidException("unitId is required");
100-
}
101-
102-
String channelName = null;
103-
String channelVersion = null;
104-
if (prebidChannel != null) {
105-
channelName = prebidChannel.getName();
106-
channelVersion = prebidChannel.getVersion();
107-
}
108-
109-
final ObjectNode impExt = imp.getExt();
122+
private Imp modifyImp(BidRequest bidRequest, Imp imp, ExtRequestPrebidChannel prebidChannel) {
123+
final ExtImpShowheroes extImpShowheroes = parseImpExt(imp);
110124

111125
final Imp.ImpBuilder impBuilder = imp.toBuilder();
112126

113-
// copy unitId from ext.bidder to ext.params
114-
impExt.set("params", JsonNodeFactory.instance.objectNode()
115-
.put("unitId", extImpShowheroes.getUnitId()));
116-
117-
impBuilder.ext(impExt);
118-
if (imp.getDisplaymanager() == null && channelName != null) {
119-
impBuilder.displaymanager(channelName);
120-
impBuilder.displaymanagerver(channelVersion);
127+
if (prebidChannel != null && imp.getDisplaymanager() == null) {
128+
impBuilder.displaymanager(prebidChannel.getName());
129+
impBuilder.displaymanagerver(prebidChannel.getVersion());
121130
}
122131

123-
String currency = imp.getBidfloorcur();
124-
// if floor price is 0, or currency is EUR - no need to convert
125-
if (imp.getBidfloor() == null || imp.getBidfloor().compareTo(BigDecimal.ZERO) == 0
126-
|| currency == BID_CURRENCY) {
132+
impBuilder.ext(modifyImpExt(imp, extImpShowheroes));
133+
134+
if (!shouldConvertFloor(imp)) {
127135
return impBuilder.build();
128136
}
129-
if (currency != null && !currency.isBlank()) {
130-
// if not provided default currency is USD
131-
currency = DEFAULT_ORTB_CURRENCY;
132-
}
133137

134-
final BigDecimal eurFloor = currencyConversionService.convertCurrency(
135-
imp.getBidfloor(), bidRequest, currency, BID_CURRENCY);
136138
return impBuilder
137139
.bidfloorcur(BID_CURRENCY)
138-
.bidfloor(eurFloor)
140+
.bidfloor(resolveBidFloor(bidRequest, imp))
139141
.build();
140142
}
141143

142-
private Source getPBSSource(BidRequest bidRequest) {
143-
Source source = bidRequest.getSource();
144-
if (source == null) {
145-
source = Source.builder().build();
146-
}
147-
148-
ExtSource extSource = source.getExt();
149-
if (extSource == null) {
150-
extSource = ExtSource.of(null);
151-
}
152-
153-
JsonNode prebidExt = extSource.getProperty("pbs");
154-
if (prebidExt == null || !prebidExt.isObject()) {
155-
prebidExt = mapper.mapper().createObjectNode();
144+
private ExtImpShowheroes parseImpExt(Imp imp) {
145+
try {
146+
return mapper.mapper().convertValue(imp.getExt(), SHOWHEROES_EXT_TYPE_REFERENCE).getBidder();
147+
} catch (IllegalArgumentException e) {
148+
throw new PreBidException(e.getMessage());
156149
}
157-
158-
((ObjectNode) prebidExt).put("pbsv", pbsVersion).put("pbsp", PBSP_JAVA);
159-
160-
extSource.addProperty("pbs", prebidExt);
161-
162-
return source.toBuilder().ext(extSource).build();
163150
}
164151

165-
@Override
166-
public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest request) {
167-
final BidderError validationError = validate(request);
168-
if (validationError != null) {
169-
return Result.of(Collections.emptyList(), List.of(validationError));
170-
}
171-
172-
final List<BidderError> errors = new ArrayList<>();
173-
final List<HttpRequest<BidRequest>> httpRequests = new ArrayList<>();
152+
private ObjectNode modifyImpExt(Imp imp, ExtImpShowheroes shImpExt) {
153+
final ObjectNode impExt = ObjectUtils.defaultIfNull(imp.getExt(), mapper.mapper().createObjectNode());
154+
impExt.set("params", mapper.mapper().createObjectNode().put("unitId", shImpExt.getUnitId()));
155+
return impExt;
156+
}
174157

175-
final ExtRequestPrebidChannel prebidChannel = getPrebidChannel(request);
176-
final List<Imp> modifiedImps = new ArrayList<>(request.getImp().size());
158+
private static boolean shouldConvertFloor(Imp imp) {
159+
return BidderUtil.isValidPrice(imp.getBidfloor())
160+
&& !StringUtils.equalsIgnoreCase(imp.getBidfloorcur(), BID_CURRENCY);
161+
}
177162

178-
for (Imp impression : request.getImp()) {
179-
try {
180-
modifiedImps.add(processImpression(request, impression, prebidChannel));
181-
} catch (Exception e) {
182-
errors.add(BidderError.badInput(e.getMessage()));
183-
continue;
184-
}
185-
}
163+
private BigDecimal resolveBidFloor(BidRequest bidRequest, Imp imp) {
164+
return currencyConversionService.convertCurrency(
165+
imp.getBidfloor(), bidRequest, imp.getBidfloorcur(), BID_CURRENCY);
166+
}
186167

187-
if (modifiedImps.isEmpty()) {
188-
return Result.of(httpRequests, errors);
168+
private Source modifySource(BidRequest bidRequest) {
169+
if (pbsVersion == null) {
170+
return bidRequest.getSource();
189171
}
190-
Source source = request.getSource();
191-
if (pbsVersion != null) {
192-
source = getPBSSource(request);
193-
}
194-
195-
httpRequests.add(makeHttpRequest(request.toBuilder().imp(modifiedImps).source(source).build()));
196-
return Result.of(httpRequests, errors);
197-
}
172+
final Source source = ObjectUtils.defaultIfNull(bidRequest.getSource(), Source.builder().build());
173+
final ExtSource extSource = ObjectUtils.defaultIfNull(source.getExt(), ExtSource.of(null));
174+
final ObjectNode prebidExtSource = Optional.ofNullable(extSource.getProperty("pbs"))
175+
.filter(JsonNode::isObject)
176+
.map(ObjectNode.class::cast)
177+
.orElseGet(() -> mapper.mapper().createObjectNode())
178+
.put("pbsv", pbsVersion)
179+
.put("pbsp", PBSP_JAVA);
198180

199-
private HttpRequest<BidRequest> makeHttpRequest(BidRequest request) {
200-
return BidderUtil.defaultRequest(request, endpointUrl, mapper);
181+
extSource.addProperty("pbs", prebidExtSource);
182+
return source.toBuilder().ext(extSource).build();
201183
}
202184

203185
@Override
204186
public Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) {
205187
final BidResponse bidResponse;
206-
final int statusCode = httpCall.getResponse().getStatusCode();
207-
if (statusCode == 204) {
208-
return Result.of(Collections.emptyList(), Collections.emptyList());
209-
}
210-
if (statusCode != 200) {
211-
return Result.withError(BidderError.badServerResponse(
212-
"Unexpected status code: " + statusCode));
213-
}
214188

215189
try {
216190
bidResponse = mapper.decodeValue(httpCall.getResponse().getBody(), BidResponse.class);
@@ -241,7 +215,7 @@ private BidType getBidType(Bid bid) {
241215
return switch (bid.getMtype()) {
242216
case 1 -> BidType.banner;
243217
case 2 -> BidType.video;
244-
case null, default -> BidType.video; // if not provided video is assumed
218+
case null, default -> BidType.video;
245219
};
246220
}
247221
}

src/test/java/org/prebid/server/bidder/showheroes/ShowheroesBidderTest.java

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import org.prebid.server.VertxTest;
2020
import org.prebid.server.bidder.model.BidderBid;
2121
import org.prebid.server.bidder.model.BidderCall;
22-
import org.prebid.server.bidder.model.BidderError;
2322
import org.prebid.server.bidder.model.HttpRequest;
2423
import org.prebid.server.bidder.model.HttpResponse;
2524
import org.prebid.server.bidder.model.Result;
@@ -90,23 +89,6 @@ public void makeHttpRequestsShouldReturnErrorIfImpExtCouldNotBeParsed() {
9089
assertThat(result.getValue()).isEmpty();
9190
}
9291

93-
@Test
94-
public void makeHttpRequestsShouldReturnErrorWhenUnitIdIsEmpty() {
95-
// given
96-
final BidRequest bidRequest = givenBidRequest(
97-
impBuilder -> impBuilder
98-
.ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpShowheroes.of("")))));
99-
100-
// when
101-
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);
102-
103-
// then
104-
assertThat(result.getErrors()).hasSize(1)
105-
.extracting(BidderError::getMessage)
106-
.containsExactly("unitId is required");
107-
assertThat(result.getValue()).isEmpty();
108-
}
109-
11092
@Test
11193
public void makeHttpRequestsShouldReturnErrorWhenSitePageIsEmpty() {
11294
// given

0 commit comments

Comments
 (0)