Skip to content

Commit 3fc6153

Browse files
author
MananRPatel
committed
Yahoo Ads: make regs ext-to-top promotion consistent and self-describing
Restructure the regs handling so a single per-field signal decides both the promotion and the ext strip. A field is promoted only when it is absent at top-level and present and well-formed in ext; a key is removed from regs.ext if and only if that field was promoted. This removes the previous dependency on whether a sibling field triggered the rebuild (e.g. a value present at both top-level and in ext is now handled the same regardless of siblings). Rename for clarity: modifyRegs -> promoteRegsExtToTopLevel, resolveX -> xToPromote (return the value to lift or null), stripPromotedFromExt -> removePromotedKeys. Add a test for the same field present at both top-level and ext.
1 parent c765516 commit 3fc6153

2 files changed

Lines changed: 77 additions & 48 deletions

File tree

src/main/java/org/prebid/server/bidder/yahooads/YahooAdsBidder.java

Lines changed: 49 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ private BidRequest modifyRequest(BidRequest request, Imp imp, ExtImpYahooAds ext
117117
}
118118

119119
if (regs != null) {
120-
requestBuilder.regs(modifyRegs(regs));
120+
requestBuilder.regs(promoteRegsExtToTopLevel(regs));
121121
}
122122

123123
return requestBuilder
@@ -163,96 +163,97 @@ private static Banner modifyBanner(Banner banner) {
163163
}
164164

165165
// Promote legacy 2.5 regs.ext gpp/gpp_sid/coppa to their 2.6 top-level slots.
166-
private static Regs modifyRegs(Regs regs) {
167-
final ExtRegs originalExt = regs.getExt();
168-
if (originalExt == null
169-
|| originalExt.getProperties() == null
170-
|| originalExt.getProperties().isEmpty()) {
166+
// A field is promoted only when it is absent at top-level and present and well-formed
167+
// in ext; each promoted key is then removed from ext. Anything not promoted (already
168+
// top-level, missing, or malformed) is left untouched, in ext.
169+
private static Regs promoteRegsExtToTopLevel(Regs regs) {
170+
final ExtRegs ext = regs.getExt();
171+
if (ext == null || ext.getProperties().isEmpty()) {
171172
return regs;
172173
}
173174

174-
final String resolvedGpp = resolveGpp(regs, originalExt);
175-
final List<Integer> resolvedGppSid = resolveGppSid(regs, originalExt);
176-
final Integer resolvedCoppa = resolveCoppa(regs, originalExt);
175+
final String promotedGpp = gppToPromote(regs, ext);
176+
final List<Integer> promotedGppSid = gppSidToPromote(regs, ext);
177+
final Integer promotedCoppa = coppaToPromote(regs, ext);
177178

178-
final boolean changed = !Objects.equals(resolvedGpp, regs.getGpp())
179-
|| !Objects.equals(resolvedGppSid, regs.getGppSid())
180-
|| !Objects.equals(resolvedCoppa, regs.getCoppa());
181-
182-
if (!changed) {
179+
if (promotedGpp == null && promotedGppSid == null && promotedCoppa == null) {
183180
return regs;
184181
}
185182

186-
return regs.toBuilder()
187-
.gpp(resolvedGpp)
188-
.gppSid(resolvedGppSid)
189-
.coppa(resolvedCoppa)
190-
.ext(stripPromotedFromExt(originalExt, resolvedGpp, resolvedGppSid, resolvedCoppa))
183+
final Regs.RegsBuilder builder = regs.toBuilder();
184+
if (promotedGpp != null) {
185+
builder.gpp(promotedGpp);
186+
}
187+
if (promotedGppSid != null) {
188+
builder.gppSid(promotedGppSid);
189+
}
190+
if (promotedCoppa != null) {
191+
builder.coppa(promotedCoppa);
192+
}
193+
return builder
194+
.ext(removePromotedKeys(ext, promotedGpp != null, promotedGppSid != null, promotedCoppa != null))
191195
.build();
192196
}
193197

194-
private static String resolveGpp(Regs regs, ExtRegs ext) {
198+
// Value to lift from ext, or null when top-level already has it or ext lacks a valid value.
199+
private static String gppToPromote(Regs regs, ExtRegs ext) {
195200
if (regs.getGpp() != null) {
196-
return regs.getGpp();
201+
return null;
197202
}
198203
final JsonNode node = ext.getProperties().get(GPP_PROPERTY);
199204
return node != null && node.isTextual() ? node.asText() : null;
200205
}
201206

202-
private static List<Integer> resolveGppSid(Regs regs, ExtRegs ext) {
207+
private static List<Integer> gppSidToPromote(Regs regs, ExtRegs ext) {
203208
if (!CollectionUtils.isEmpty(regs.getGppSid())) {
204-
return regs.getGppSid();
209+
return null;
205210
}
206211
final JsonNode node = ext.getProperties().get(GPP_SID_PROPERTY);
207-
if (node == null || !node.isArray()) {
208-
return regs.getGppSid();
212+
if (node == null || !node.isArray() || node.isEmpty()) {
213+
return null;
209214
}
210215
final List<Integer> sids = new ArrayList<>(node.size());
211216
for (final JsonNode elem : node) {
212217
if (!elem.isIntegralNumber()) {
213-
return regs.getGppSid();
218+
return null;
214219
}
215220
sids.add(elem.asInt());
216221
}
217-
return sids.isEmpty() ? regs.getGppSid() : sids;
222+
return sids;
218223
}
219224

220-
private static Integer resolveCoppa(Regs regs, ExtRegs ext) {
225+
private static Integer coppaToPromote(Regs regs, ExtRegs ext) {
221226
if (regs.getCoppa() != null) {
222-
return regs.getCoppa();
227+
return null;
223228
}
224229
final JsonNode node = ext.getProperties().get(COPPA_PROPERTY);
225230
return node != null && node.isIntegralNumber() ? node.asInt() : null;
226231
}
227232

228-
// Drop a key from ext only if it was promoted; keep gpc/dsa, unknown, and non-promoted values.
229-
private static ExtRegs stripPromotedFromExt(ExtRegs original,
230-
String resolvedGpp,
231-
List<Integer> resolvedGppSid,
232-
Integer resolvedCoppa) {
233-
final ExtRegs stripped = ExtRegs.of(
234-
original.getGdpr(),
235-
original.getUsPrivacy(),
236-
original.getGpc(),
237-
original.getDsa());
238-
original.getProperties().forEach((key, value) -> {
239-
final boolean promoted =
240-
(GPP_PROPERTY.equals(key) && resolvedGpp != null)
241-
|| (GPP_SID_PROPERTY.equals(key) && !CollectionUtils.isEmpty(resolvedGppSid))
242-
|| (COPPA_PROPERTY.equals(key) && resolvedCoppa != null);
243-
if (!promoted) {
244-
stripped.addProperty(key, value);
233+
// Rebuild regs.ext keeping the typed fields and every property except the promoted ones.
234+
private static ExtRegs removePromotedKeys(ExtRegs ext,
235+
boolean gppPromoted,
236+
boolean gppSidPromoted,
237+
boolean coppaPromoted) {
238+
final ExtRegs result = ExtRegs.of(
239+
ext.getGdpr(), ext.getUsPrivacy(), ext.getGpc(), ext.getDsa());
240+
ext.getProperties().forEach((key, value) -> {
241+
final boolean isPromotedKey = (gppPromoted && GPP_PROPERTY.equals(key))
242+
|| (gppSidPromoted && GPP_SID_PROPERTY.equals(key))
243+
|| (coppaPromoted && COPPA_PROPERTY.equals(key));
244+
if (!isPromotedKey) {
245+
result.addProperty(key, value);
245246
}
246247
});
247-
return isExtEmpty(stripped) ? null : stripped;
248+
return isExtEmpty(result) ? null : result;
248249
}
249250

250251
private static boolean isExtEmpty(ExtRegs ext) {
251252
return ext.getGdpr() == null
252253
&& ext.getUsPrivacy() == null
253254
&& ext.getGpc() == null
254255
&& ext.getDsa() == null
255-
&& (ext.getProperties() == null || ext.getProperties().isEmpty());
256+
&& ext.getProperties().isEmpty();
256257
}
257258

258259
private HttpRequest<BidRequest> makeHttpRequest(BidRequest outgoingRequest) {

src/test/java/org/prebid/server/bidder/yahooads/YahooAdsBidderTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,34 @@ public void makeHttpRequestsShouldNotPromoteGppSidWhenArrayHasNonIntegerElement(
584584
assertThat(keptSid.get(2).asInt()).isEqualTo(8);
585585
}
586586

587+
@Test
588+
public void makeHttpRequestsShouldKeepExtGppWhenTopLevelGppAlreadySetEvenIfSiblingIsPromoted() {
589+
// gpp is present at BOTH top-level and in ext; a sibling (coppa) is promoted from ext.
590+
// gpp is not promoted (top-level wins), so its ext copy must be left untouched -
591+
// the strip decision does not depend on the sibling rebuild.
592+
final BidRequest bidRequest = givenBidRequest(identity(),
593+
requestBuilder -> requestBuilder.regs(Regs.builder()
594+
.gpp("top-level-gpp")
595+
.ext(ExtRegs.of(null, null, null, null))
596+
.build()).device(Device.builder().ua("UA").build()));
597+
bidRequest.getRegs().getExt().addProperty("gpp", TextNode.valueOf("ext-gpp"));
598+
bidRequest.getRegs().getExt().addProperty("coppa", IntNode.valueOf(1));
599+
600+
// when
601+
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);
602+
603+
// then
604+
assertThat(result.getErrors()).isEmpty();
605+
final Regs regs = result.getValue().getFirst().getPayload().getRegs();
606+
// coppa promoted and removed from ext
607+
assertThat(regs.getCoppa()).isEqualTo(1);
608+
// gpp top-level untouched; ext gpp left in place (not promoted, not stripped)
609+
assertThat(regs.getGpp()).isEqualTo("top-level-gpp");
610+
assertThat(regs.getExt()).isNotNull();
611+
assertThat(regs.getExt().getProperty("coppa")).isNull();
612+
assertThat(regs.getExt().getProperty("gpp").asText()).isEqualTo("ext-gpp");
613+
}
614+
587615
@Test
588616
public void makeHttpRequestsShouldShortCircuitWhenRegsHasNoExt() {
589617
final BidRequest bidRequest = givenBidRequest(identity(),

0 commit comments

Comments
 (0)