Skip to content

Commit d9dc165

Browse files
authored
Further conversions to ChunkedXContentBuilder (#114237)
1 parent 6f518d4 commit d9dc165

File tree

11 files changed

+203
-282
lines changed

11 files changed

+203
-282
lines changed

server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponse.java

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,18 @@
1313
import org.elasticsearch.action.support.master.IsAcknowledgedSupplier;
1414
import org.elasticsearch.cluster.ClusterState;
1515
import org.elasticsearch.cluster.routing.allocation.RoutingExplanations;
16-
import org.elasticsearch.common.collect.Iterators;
1716
import org.elasticsearch.common.io.stream.StreamInput;
1817
import org.elasticsearch.common.io.stream.StreamOutput;
1918
import org.elasticsearch.common.logging.DeprecationCategory;
2019
import org.elasticsearch.common.logging.DeprecationLogger;
21-
import org.elasticsearch.common.xcontent.ChunkedToXContentHelper;
20+
import org.elasticsearch.common.xcontent.ChunkedToXContent;
2221
import org.elasticsearch.common.xcontent.ChunkedToXContentObject;
2322
import org.elasticsearch.core.RestApiVersion;
2423
import org.elasticsearch.core.UpdateForV10;
2524
import org.elasticsearch.rest.action.search.RestSearchAction;
2625
import org.elasticsearch.xcontent.ToXContent;
2726

2827
import java.io.IOException;
29-
import java.util.Collections;
3028
import java.util.Iterator;
3129
import java.util.Objects;
3230

@@ -98,20 +96,15 @@ public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params outerP
9896
}
9997

10098
@Override
101-
public Iterator<? extends ToXContent> toXContentChunkedV7(ToXContent.Params outerParams) {
102-
return Iterators.concat(
103-
Iterators.single((builder, params) -> builder.startObject().field(ACKNOWLEDGED_KEY, isAcknowledged())),
104-
emitState(outerParams)
105-
? ChunkedToXContentHelper.wrapWithObject("state", state.toXContentChunked(outerParams))
106-
: Collections.emptyIterator(),
107-
Iterators.single((builder, params) -> {
108-
if (params.paramAsBoolean("explain", false)) {
109-
explanations.toXContent(builder, params);
110-
}
111-
112-
builder.endObject();
113-
return builder;
114-
})
115-
);
99+
public Iterator<? extends ToXContent> toXContentChunkedV7(ToXContent.Params params) {
100+
return ChunkedToXContent.builder(params).object(b -> {
101+
b.field(ACKNOWLEDGED_KEY, isAcknowledged());
102+
if (emitState(params)) {
103+
b.xContentObject("state", state);
104+
}
105+
if (params.paramAsBoolean("explain", false)) {
106+
b.append(explanations);
107+
}
108+
});
116109
}
117110
}

server/src/main/java/org/elasticsearch/cluster/ClusterState.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -759,10 +759,8 @@ public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params outerP
759759

760760
// customs
761761
metrics.contains(Metric.CUSTOMS)
762-
? Iterators.flatMap(
763-
customs.entrySet().iterator(),
764-
cursor -> ChunkedToXContentHelper.wrapWithObject(cursor.getKey(), cursor.getValue().toXContentChunked(outerParams))
765-
)
762+
? ChunkedToXContent.builder(outerParams)
763+
.forEach(customs.entrySet().iterator(), (b, e) -> b.xContentObject(e.getKey(), e.getValue()))
766764
: Collections.emptyIterator()
767765
);
768766
}

server/src/main/java/org/elasticsearch/common/xcontent/ChunkedToXContentBuilder.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ private void addChunk(ToXContent content) {
3838
builder.add(Objects.requireNonNull(content));
3939
}
4040

41+
public ToXContent.Params params() {
42+
return params;
43+
}
44+
4145
private void startObject() {
4246
addChunk((b, p) -> b.startObject());
4347
}
@@ -259,6 +263,16 @@ public <T> ChunkedToXContentBuilder array(Iterator<T> items, BiConsumer<ChunkedT
259263
return this;
260264
}
261265

266+
/**
267+
* Creates an array with the contents set by appending together the contents of {@code items}
268+
*/
269+
public ChunkedToXContentBuilder array(Iterator<? extends ToXContent> items) {
270+
startArray();
271+
items.forEachRemaining(this::append);
272+
endArray();
273+
return this;
274+
}
275+
262276
/**
263277
* Creates an array, with the contents set by appending together
264278
* the return values of {@code create} called on each item returned by {@code items}
@@ -351,6 +365,12 @@ public ChunkedToXContentBuilder field(String name, ToXContent value) {
351365
return this;
352366
}
353367

368+
public ChunkedToXContentBuilder field(String name, ChunkedToXContent value) {
369+
addChunk((b, p) -> b.field(name));
370+
append(value);
371+
return this;
372+
}
373+
354374
public ChunkedToXContentBuilder field(String name, Object value) {
355375
addChunk((b, p) -> b.field(name, value));
356376
return this;

server/src/main/java/org/elasticsearch/common/xcontent/ChunkedToXContentHelper.java

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,26 +53,10 @@ public static Iterator<ToXContent> field(String name, String value) {
5353
return Iterators.single(((builder, params) -> builder.field(name, value)));
5454
}
5555

56-
/**
57-
* Creates an Iterator to serialize a named field where the value is represented by a {@link ChunkedToXContentObject}.
58-
* Chunked equivalent for {@code XContentBuilder field(String name, ToXContent value)}
59-
* @param name name of the field
60-
* @param value value for this field
61-
* @param params params to propagate for XContent serialization
62-
* @return Iterator composing field name and value serialization
63-
*/
64-
public static Iterator<ToXContent> field(String name, ChunkedToXContentObject value, ToXContent.Params params) {
65-
return Iterators.concat(Iterators.single((builder, innerParam) -> builder.field(name)), value.toXContentChunked(params));
66-
}
67-
6856
public static Iterator<ToXContent> array(String name, Iterator<? extends ToXContent> contents) {
6957
return Iterators.concat(ChunkedToXContentHelper.startArray(name), contents, ChunkedToXContentHelper.endArray());
7058
}
7159

72-
public static <T extends ToXContent> Iterator<ToXContent> wrapWithObject(String name, Iterator<T> iterator) {
73-
return Iterators.concat(startObject(name), iterator, endObject());
74-
}
75-
7660
/**
7761
* Creates an Iterator of a single ToXContent object that serializes the given object as a single chunk. Just wraps {@link
7862
* Iterators#single}, but still useful because it avoids any type ambiguity.

server/src/main/java/org/elasticsearch/script/ScriptCacheStats.java

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,8 @@
2121
import java.util.Iterator;
2222
import java.util.Map;
2323
import java.util.Objects;
24+
import java.util.function.Function;
2425

25-
import static org.elasticsearch.common.collect.Iterators.concat;
26-
import static org.elasticsearch.common.collect.Iterators.flatMap;
27-
import static org.elasticsearch.common.collect.Iterators.single;
28-
import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.endArray;
29-
import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.endObject;
30-
import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.field;
31-
import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.startArray;
32-
import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.startObject;
3326
import static org.elasticsearch.script.ScriptCacheStats.Fields.SCRIPT_CACHE_STATS;
3427

3528
// This class is deprecated in favor of ScriptStats and ScriptContextStats
@@ -76,35 +69,25 @@ public void writeTo(StreamOutput out) throws IOException {
7669

7770
@Override
7871
public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params outerParams) {
79-
return concat(
80-
startObject(SCRIPT_CACHE_STATS),
81-
startObject(Fields.SUM),
82-
general != null
83-
? concat(
84-
field(ScriptStats.Fields.COMPILATIONS, general.getCompilations()),
85-
field(ScriptStats.Fields.CACHE_EVICTIONS, general.getCacheEvictions()),
86-
field(ScriptStats.Fields.COMPILATION_LIMIT_TRIGGERED, general.getCompilationLimitTriggered()),
87-
endObject(),
88-
endObject()
89-
)
90-
: concat(single((builder, params) -> {
91-
var sum = sum();
92-
return builder.field(ScriptStats.Fields.COMPILATIONS, sum.getCompilations())
93-
.field(ScriptStats.Fields.CACHE_EVICTIONS, sum.getCacheEvictions())
94-
.field(ScriptStats.Fields.COMPILATION_LIMIT_TRIGGERED, sum.getCompilationLimitTriggered())
95-
.endObject();
96-
}), startArray(Fields.CONTEXTS), flatMap(context.keySet().stream().sorted().iterator(), ctx -> {
97-
var stats = context.get(ctx);
98-
return concat(
99-
startObject(),
100-
field(Fields.CONTEXT, ctx),
101-
field(ScriptStats.Fields.COMPILATIONS, stats.getCompilations()),
102-
field(ScriptStats.Fields.CACHE_EVICTIONS, stats.getCacheEvictions()),
103-
field(ScriptStats.Fields.COMPILATION_LIMIT_TRIGGERED, stats.getCompilationLimitTriggered()),
104-
endObject()
105-
);
106-
}), endArray(), endObject())
107-
);
72+
Function<ScriptStats, ToXContent> statsFields = s -> (b, p) -> b.field(ScriptStats.Fields.COMPILATIONS, s.getCompilations())
73+
.field(ScriptStats.Fields.CACHE_EVICTIONS, s.getCacheEvictions())
74+
.field(ScriptStats.Fields.COMPILATION_LIMIT_TRIGGERED, s.getCompilationLimitTriggered());
75+
76+
return ChunkedToXContent.builder(outerParams).object(SCRIPT_CACHE_STATS, sb -> {
77+
if (general != null) {
78+
sb.xContentObject(Fields.SUM, statsFields.apply(general));
79+
} else {
80+
sb.xContentObject(Fields.SUM, statsFields.apply(sum()));
81+
sb.array(
82+
Fields.CONTEXTS,
83+
context.entrySet().stream().sorted(Map.Entry.comparingByKey()).iterator(),
84+
(eb, e) -> eb.object(ebo -> {
85+
ebo.field(Fields.CONTEXT, e.getKey());
86+
ebo.append(statsFields.apply(e.getValue()));
87+
})
88+
);
89+
}
90+
});
10891
}
10992

11093
/**

server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,15 @@ private void assertXContent(
313313
fail(e);
314314
}
315315

316-
final var expectedChunks = Objects.equals(params.param("metric"), "none")
317-
? 2
318-
: 4 + ClusterStateTests.expectedChunkCount(params, response.getState());
316+
int[] expectedChunks = new int[] { 3 };
317+
if (Objects.equals(params.param("metric"), "none") == false) {
318+
expectedChunks[0] += 2 + ClusterStateTests.expectedChunkCount(params, response.getState());
319+
}
320+
if (params.paramAsBoolean("explain", false)) {
321+
expectedChunks[0]++;
322+
}
319323

320-
AbstractChunkedSerializingTestCase.assertChunkCount(response, params, ignored -> expectedChunks);
324+
AbstractChunkedSerializingTestCase.assertChunkCount(response, params, o -> expectedChunks[0]);
321325
assertCriticalWarnings(criticalDeprecationWarnings);
322326

323327
// check the v7 API too
@@ -331,7 +335,7 @@ public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params outerP
331335
public boolean isFragment() {
332336
return response.isFragment();
333337
}
334-
}, params, ignored -> expectedChunks);
338+
}, params, o -> expectedChunks[0]++);
335339
// the v7 API should not emit any deprecation warnings
336340
assertCriticalWarnings();
337341
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.common.xcontent;
11+
12+
import org.elasticsearch.common.Strings;
13+
import org.elasticsearch.common.collect.Iterators;
14+
import org.elasticsearch.test.ESTestCase;
15+
import org.elasticsearch.xcontent.ToXContent;
16+
17+
import java.util.function.IntFunction;
18+
import java.util.stream.IntStream;
19+
20+
import static org.hamcrest.Matchers.equalTo;
21+
22+
public class ChunkedToXContentBuilderTests extends ESTestCase {
23+
24+
public void testFieldWithInnerChunkedObject() {
25+
26+
ToXContent innerXContent = (b, p) -> {
27+
b.startObject();
28+
b.field("field1", 10);
29+
b.field("field2", "aaa");
30+
b.endObject();
31+
return b;
32+
};
33+
34+
ToXContent outerXContent = (b, p) -> b.field("field3", 10).field("field4", innerXContent);
35+
36+
String expectedContent = Strings.toString(outerXContent);
37+
38+
ChunkedToXContentObject innerChunkedContent = params -> new ChunkedToXContentBuilder(params).object(
39+
o -> o.field("field1", 10).field("field2", "aaa")
40+
);
41+
42+
ChunkedToXContent outerChunkedContent = params -> new ChunkedToXContentBuilder(params).field("field3", 10)
43+
.field("field4", innerChunkedContent);
44+
45+
assertThat(Strings.toString(outerChunkedContent), equalTo(expectedContent));
46+
}
47+
48+
public void testFieldWithInnerChunkedArray() {
49+
50+
ToXContent innerXContent = (b, p) -> {
51+
b.startArray();
52+
b.value(10);
53+
b.value(20);
54+
b.endArray();
55+
return b;
56+
};
57+
58+
ToXContent outerXContent = (b, p) -> b.field("field3", 10).field("field4", innerXContent);
59+
60+
String expectedContent = Strings.toString(outerXContent);
61+
62+
IntFunction<ToXContent> value = v -> (b, p) -> b.value(v);
63+
64+
ChunkedToXContentObject innerChunkedContent = params -> new ChunkedToXContentBuilder(params).array(
65+
IntStream.of(10, 20).mapToObj(value).iterator()
66+
);
67+
68+
ChunkedToXContent outerChunkedContent = params -> new ChunkedToXContentBuilder(params).field("field3", 10)
69+
.field("field4", innerChunkedContent);
70+
71+
assertThat(Strings.toString(outerChunkedContent), equalTo(expectedContent));
72+
}
73+
74+
public void testFieldWithInnerChunkedField() {
75+
76+
ToXContent innerXContent = (b, p) -> b.value(10);
77+
ToXContent outerXContent = (b, p) -> b.field("field3", 10).field("field4", innerXContent);
78+
79+
String expectedContent = Strings.toString(outerXContent);
80+
81+
ChunkedToXContentObject innerChunkedContent = params -> Iterators.single((b, p) -> b.value(10));
82+
83+
ChunkedToXContent outerChunkedContent = params -> new ChunkedToXContentBuilder(params).field("field3", 10)
84+
.field("field4", innerChunkedContent);
85+
86+
assertThat(Strings.toString(outerChunkedContent), equalTo(expectedContent));
87+
}
88+
}

0 commit comments

Comments
 (0)