Skip to content

Commit d60dec3

Browse files
RTBHouse: refactor tag id extraction logic for simplicity and improving readability; changed order of methods
1 parent 8828c64 commit d60dec3

2 files changed

Lines changed: 145 additions & 165 deletions

File tree

src/main/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidder.java

Lines changed: 115 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,110 @@ public Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest bidRequ
9494
return Result.withValue(BidderUtil.defaultRequest(outgoingRequest, endpointUrl, mapper));
9595
}
9696

97+
private ExtImpRtbhouse parseImpExt(Imp imp) {
98+
try {
99+
return mapper.mapper().convertValue(imp.getExt(), RTBHOUSE_EXT_TYPE_REFERENCE).getBidder();
100+
} catch (IllegalArgumentException e) {
101+
throw new PreBidException(e.getMessage());
102+
}
103+
}
104+
105+
private Price resolveBidFloor(Imp imp, ExtImpRtbhouse impExt, BidRequest bidRequest) {
106+
final List<String> brCur = bidRequest.getCur();
107+
final Price initialBidFloorPrice = Price.of(imp.getBidfloorcur(), imp.getBidfloor());
108+
109+
final BigDecimal impExtBidFloor = impExt.getBidFloor();
110+
final String impExtCurrency = impExtBidFloor != null && brCur != null && !brCur.isEmpty()
111+
? brCur.getFirst() : null;
112+
final Price impExtBidFloorPrice = Price.of(impExtCurrency, impExtBidFloor);
113+
final Price resolvedPrice = initialBidFloorPrice.getValue() == null
114+
? impExtBidFloorPrice : initialBidFloorPrice;
115+
116+
return BidderUtil.isValidPrice(resolvedPrice)
117+
&& !StringUtils.equalsIgnoreCase(resolvedPrice.getCurrency(), BIDDER_CURRENCY)
118+
? convertBidFloor(resolvedPrice, imp.getId(), bidRequest)
119+
: resolvedPrice;
120+
}
121+
122+
private Price convertBidFloor(Price bidFloorPrice, String impId, BidRequest bidRequest) {
123+
final String bidFloorCur = bidFloorPrice.getCurrency();
124+
try {
125+
final BigDecimal convertedPrice = currencyConversionService
126+
.convertCurrency(bidFloorPrice.getValue(), bidRequest, bidFloorCur, BIDDER_CURRENCY);
127+
128+
return Price.of(BIDDER_CURRENCY, convertedPrice);
129+
} catch (PreBidException e) {
130+
throw new PreBidException(String.format(
131+
"Unable to convert provided bid floor currency from %s to %s for imp `%s`",
132+
bidFloorCur, BIDDER_CURRENCY, impId));
133+
}
134+
}
135+
136+
private static Imp modifyImp(Imp imp, Price bidFloorPrice) {
137+
return imp.toBuilder()
138+
.tagid(extractTagId(imp))
139+
.bidfloorcur(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getCurrency))
140+
.bidfloor(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getValue))
141+
.pmp(null)
142+
.build();
143+
}
144+
145+
private static String extractTagId(Imp imp) {
146+
return Optional.ofNullable(imp.getTagid())
147+
.filter(StringUtils::isNotBlank)
148+
.or(() -> extractGpid(imp))
149+
.or(() -> extractAdslot(imp))
150+
.or(() -> extractPbadslot(imp))
151+
.or(() -> Optional.ofNullable(imp.getId())
152+
.filter(StringUtils::isNotBlank))
153+
.orElse(null);
154+
}
155+
156+
private static Optional<String> extractGpid(Imp imp) {
157+
return Optional.ofNullable(imp.getExt())
158+
.map(ext -> ext.get("gpid"))
159+
.map(JsonNode::textValue)
160+
.filter(StringUtils::isNotBlank);
161+
}
162+
163+
private static Optional<String> extractAdslot(Imp imp) {
164+
return Optional.ofNullable(imp.getExt())
165+
.map(ext -> ext.get("data"))
166+
.map(data -> data.get("adserver"))
167+
.map(adserver -> adserver.get("adslot"))
168+
.map(JsonNode::textValue)
169+
.filter(StringUtils::isNotBlank);
170+
}
171+
172+
private static Optional<String> extractPbadslot(Imp imp) {
173+
return Optional.ofNullable(imp.getExt())
174+
.map(ext -> ext.get("data"))
175+
.map(data -> data.get("pbadslot"))
176+
.map(JsonNode::textValue)
177+
.filter(StringUtils::isNotBlank);
178+
}
179+
180+
private Site modifySite(Site site, String publisherId) {
181+
final ObjectNode prebidNode = mapper.mapper().createObjectNode();
182+
prebidNode.put("publisherId", publisherId);
183+
184+
final ExtPublisher extPublisher = ExtPublisher.empty();
185+
extPublisher.addProperty("prebid", prebidNode);
186+
187+
final Publisher publisher = Optional.ofNullable(site)
188+
.map(Site::getPublisher)
189+
.map(Publisher::toBuilder)
190+
.orElseGet(Publisher::builder)
191+
.ext(extPublisher)
192+
.build();
193+
194+
return Optional.ofNullable(site)
195+
.map(Site::toBuilder)
196+
.orElseGet(Site::builder)
197+
.publisher(publisher)
198+
.build();
199+
}
200+
97201
@Override
98202
public Result<List<BidderBid>> makeBids(BidderCall<BidRequest> httpCall, BidRequest bidRequest) {
99203
try {
@@ -144,23 +248,6 @@ private BidderBid resolveBidderBid(Bid bid,
144248
.build();
145249
}
146250

147-
private String resolveNativeAdm(String adm, List<BidderError> bidderErrors) {
148-
final JsonNode admNode;
149-
try {
150-
admNode = mapper.mapper().readTree(adm);
151-
} catch (JsonProcessingException e) {
152-
bidderErrors.add(BidderError.badServerResponse("Unable to parse native adm: %s".formatted(adm)));
153-
return null;
154-
}
155-
156-
final JsonNode nativeNode = admNode.get("native");
157-
if (nativeNode != null) {
158-
return nativeNode.toString();
159-
}
160-
161-
return adm;
162-
}
163-
164251
private static BidType getBidType(String impId, List<Imp> imps) {
165252
for (Imp imp : imps) {
166253
if (imp.getId().equals(impId)) {
@@ -176,95 +263,21 @@ private static BidType getBidType(String impId, List<Imp> imps) {
176263
return BidType.banner;
177264
}
178265

179-
private ExtImpRtbhouse parseImpExt(Imp imp) {
266+
private String resolveNativeAdm(String adm, List<BidderError> bidderErrors) {
267+
final JsonNode admNode;
180268
try {
181-
return mapper.mapper().convertValue(imp.getExt(), RTBHOUSE_EXT_TYPE_REFERENCE).getBidder();
182-
} catch (IllegalArgumentException e) {
183-
throw new PreBidException(e.getMessage());
269+
admNode = mapper.mapper().readTree(adm);
270+
} catch (JsonProcessingException e) {
271+
bidderErrors.add(BidderError.badServerResponse("Unable to parse native adm: %s".formatted(adm)));
272+
return null;
184273
}
185-
}
186-
187-
private static Imp modifyImp(Imp imp, Price bidFloorPrice) {
188-
return imp.toBuilder()
189-
.tagid(extractTagId(imp))
190-
.bidfloorcur(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getCurrency))
191-
.bidfloor(ObjectUtil.getIfNotNull(bidFloorPrice, Price::getValue))
192-
.pmp(null)
193-
.build();
194-
}
195-
196-
private static String extractTagId(Imp imp) {
197-
return Optional.ofNullable(imp.getTagid())
198-
.filter(StringUtils::isNotBlank)
199-
.orElseGet(() -> extractTagIdFromExt(imp));
200-
}
201-
202-
private static String extractTagIdFromExt(Imp imp) {
203-
return Optional.ofNullable(imp.getExt())
204-
.flatMap(ext -> extractGpid(ext))
205-
.orElseGet(() -> extractFromData(imp));
206-
}
207-
208-
private static Optional<String> extractGpid(JsonNode ext) {
209-
return Optional.ofNullable(ext.get("gpid"))
210-
.filter(JsonNode::isTextual)
211-
.map(JsonNode::asText)
212-
.filter(StringUtils::isNotBlank);
213-
}
214-
215-
private static String extractFromData(Imp imp) {
216-
return Optional.ofNullable(imp.getExt())
217-
.map(ext -> ext.get("data"))
218-
.filter(JsonNode::isObject)
219-
.flatMap(data -> extractAdslot(data).or(() -> extractPbadslot(data)))
220-
.orElseGet(() -> Optional.ofNullable(imp.getId()).filter(StringUtils::isNotBlank).orElse(null));
221-
}
222-
223-
private static Optional<String> extractAdslot(JsonNode data) {
224-
return Optional.ofNullable(data.get("adserver"))
225-
.filter(JsonNode::isObject)
226-
.map(adserver -> adserver.get("adslot"))
227-
.filter(JsonNode::isTextual)
228-
.map(JsonNode::asText)
229-
.filter(StringUtils::isNotBlank);
230-
}
231-
232-
private static Optional<String> extractPbadslot(JsonNode data) {
233-
return Optional.ofNullable(data.get("pbadslot"))
234-
.filter(JsonNode::isTextual)
235-
.map(JsonNode::asText)
236-
.filter(StringUtils::isNotBlank);
237-
}
238-
239-
private Price resolveBidFloor(Imp imp, ExtImpRtbhouse impExt, BidRequest bidRequest) {
240-
final List<String> brCur = bidRequest.getCur();
241-
final Price initialBidFloorPrice = Price.of(imp.getBidfloorcur(), imp.getBidfloor());
242274

243-
final BigDecimal impExtBidFloor = impExt.getBidFloor();
244-
final String impExtCurrency = impExtBidFloor != null && brCur != null && !brCur.isEmpty()
245-
? brCur.getFirst() : null;
246-
final Price impExtBidFloorPrice = Price.of(impExtCurrency, impExtBidFloor);
247-
final Price resolvedPrice = initialBidFloorPrice.getValue() == null
248-
? impExtBidFloorPrice : initialBidFloorPrice;
249-
250-
return BidderUtil.isValidPrice(resolvedPrice)
251-
&& !StringUtils.equalsIgnoreCase(resolvedPrice.getCurrency(), BIDDER_CURRENCY)
252-
? convertBidFloor(resolvedPrice, imp.getId(), bidRequest)
253-
: resolvedPrice;
254-
}
255-
256-
private Price convertBidFloor(Price bidFloorPrice, String impId, BidRequest bidRequest) {
257-
final String bidFloorCur = bidFloorPrice.getCurrency();
258-
try {
259-
final BigDecimal convertedPrice = currencyConversionService
260-
.convertCurrency(bidFloorPrice.getValue(), bidRequest, bidFloorCur, BIDDER_CURRENCY);
261-
262-
return Price.of(BIDDER_CURRENCY, convertedPrice);
263-
} catch (PreBidException e) {
264-
throw new PreBidException(String.format(
265-
"Unable to convert provided bid floor currency from %s to %s for imp `%s`",
266-
bidFloorCur, BIDDER_CURRENCY, impId));
275+
final JsonNode nativeNode = admNode.get("native");
276+
if (nativeNode != null) {
277+
return nativeNode.toString();
267278
}
279+
280+
return adm;
268281
}
269282

270283
private static Bid resolveMacros(Bid bid) {
@@ -276,25 +289,4 @@ private static Bid resolveMacros(Bid bid) {
276289
.adm(StringUtils.replace(bid.getAdm(), PRICE_MACRO, priceAsString))
277290
.build();
278291
}
279-
280-
private Site modifySite(Site site, String publisherId) {
281-
final ObjectNode prebidNode = mapper.mapper().createObjectNode();
282-
prebidNode.put("publisherId", publisherId);
283-
284-
final ExtPublisher extPublisher = ExtPublisher.empty();
285-
extPublisher.addProperty("prebid", prebidNode);
286-
287-
final Publisher publisher = Optional.ofNullable(site)
288-
.map(Site::getPublisher)
289-
.map(Publisher::toBuilder)
290-
.orElseGet(Publisher::builder)
291-
.ext(extPublisher)
292-
.build();
293-
294-
return Optional.ofNullable(site)
295-
.map(Site::toBuilder)
296-
.orElseGet(Site::builder)
297-
.publisher(publisher)
298-
.build();
299-
}
300292
}

src/test/java/org/prebid/server/bidder/rtbhouse/RtbhouseBidderTest.java

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434

3535
import java.math.BigDecimal;
3636
import java.util.List;
37+
import java.util.Map;
3738
import java.util.function.Function;
39+
import java.util.function.UnaryOperator;
3840

3941
import static java.util.Collections.singletonList;
4042
import static java.util.function.Function.identity;
@@ -521,13 +523,10 @@ public void makeHttpRequestsShouldAlwaysRemovePmpField() {
521523
@Test
522524
public void makeHttpRequestsShouldSetTagidFromGpid() {
523525
// given
524-
final BidRequest bidRequest = BidRequest.builder()
525-
.imp(singletonList(Imp.builder()
526-
.id("imp123")
527-
.ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value")))
528-
.build()))
529-
.id("request_id")
530-
.build();
526+
final BidRequest bidRequest = givenBidRequest(
527+
bidReq -> bidReq.id("request_id"),
528+
imp -> imp.id("imp123").ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value"))),
529+
identity());
531530

532531
// when
533532
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);
@@ -544,14 +543,13 @@ public void makeHttpRequestsShouldSetTagidFromGpid() {
544543
@Test
545544
public void makeHttpRequestsShouldSetTagidFromAdserverAdslot() {
546545
// given
547-
final BidRequest bidRequest = BidRequest.builder()
548-
.imp(singletonList(Imp.builder()
549-
.id("imp123")
550-
.ext(givenRtbhouseExt(node -> node.set("data", mapper.createObjectNode()
551-
.set("adserver", mapper.createObjectNode().put("adslot", "adslot_value")))))
552-
.build()))
553-
.id("request_id")
554-
.build();
546+
final BidRequest bidRequest = givenBidRequest(
547+
bidReq -> bidReq.id("request_id"),
548+
imp -> imp.id("imp123")
549+
.ext(givenRtbhouseExt(node ->
550+
node.set("data", mapper.valueToTree(
551+
Map.of("adserver", Map.of("adslot", "adslot_value")))))),
552+
identity());
555553

556554
// when
557555
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);
@@ -568,14 +566,12 @@ public void makeHttpRequestsShouldSetTagidFromAdserverAdslot() {
568566
@Test
569567
public void makeHttpRequestsShouldSetTagidFromPbadslot() {
570568
// given
571-
final BidRequest bidRequest = BidRequest.builder()
572-
.imp(singletonList(Imp.builder()
573-
.id("imp123")
574-
.ext(givenRtbhouseExt(node -> node.set("data", mapper.createObjectNode()
575-
.put("pbadslot", "pbadslot_value"))))
576-
.build()))
577-
.id("request_id")
578-
.build();
569+
final BidRequest bidRequest = givenBidRequest(
570+
bidReq -> bidReq.id("request_id"),
571+
imp -> imp.id("imp123")
572+
.ext(givenRtbhouseExt(node ->
573+
node.set("data", mapper.valueToTree(Map.of("pbadslot", "pbadslot_value"))))),
574+
identity());
579575

580576
// when
581577
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);
@@ -612,16 +608,10 @@ public void makeHttpRequestsShouldSetTagidFromImpIdWhenNoOtherFields() {
612608
@Test
613609
public void makeHttpRequestsShouldSetTagidToNullWhenNoFieldsAvailable() {
614610
// given
615-
final BidRequest bidRequest = BidRequest.builder()
616-
.imp(singletonList(Imp.builder()
617-
.id(null)
618-
.ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpRtbhouse.builder()
619-
.publisherId("publisherId")
620-
.region("region")
621-
.build())))
622-
.build()))
623-
.id("request_id")
624-
.build();
611+
final BidRequest bidRequest = givenBidRequest(
612+
bidReq -> bidReq.id("request_id"),
613+
imp -> imp.id(null),
614+
identity());
625615

626616
// when
627617
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);
@@ -638,14 +628,12 @@ public void makeHttpRequestsShouldSetTagidToNullWhenNoFieldsAvailable() {
638628
@Test
639629
public void makeHttpRequestsShouldPreserveExistingTagid() {
640630
// given
641-
final BidRequest bidRequest = BidRequest.builder()
642-
.imp(singletonList(Imp.builder()
643-
.id("imp123")
631+
final BidRequest bidRequest = givenBidRequest(
632+
bidReq -> bidReq.id("request_id"),
633+
imp -> imp.id("imp123")
644634
.tagid("existing_tagid")
645-
.ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value")))
646-
.build()))
647-
.id("request_id")
648-
.build();
635+
.ext(givenRtbhouseExt(node -> node.put("gpid", "gpid_value"))),
636+
identity());
649637

650638
// when
651639
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);
@@ -704,8 +692,8 @@ private static Imp givenImp(Function<Imp.ImpBuilder, Imp.ImpBuilder> impCustomiz
704692
.build();
705693
}
706694

707-
private static ObjectNode givenRtbhouseExt(Function<ObjectNode, ObjectNode> extCustomizer) {
708-
final ObjectNode extNode = (ObjectNode) mapper.valueToTree(ExtPrebid.of(null, ExtImpRtbhouse.builder()
695+
private static ObjectNode givenRtbhouseExt(UnaryOperator<ObjectNode> extCustomizer) {
696+
final ObjectNode extNode = mapper.valueToTree(ExtPrebid.of(null, ExtImpRtbhouse.builder()
709697
.publisherId("publisherId")
710698
.region("region")
711699
.build()));

0 commit comments

Comments
 (0)