diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/analyze/DetailAnalyzeResponse.java b/core/src/main/java/org/elasticsearch/action/admin/indices/analyze/DetailAnalyzeResponse.java
index c67c0360230..2d1ba22b989 100644
--- a/core/src/main/java/org/elasticsearch/action/admin/indices/analyze/DetailAnalyzeResponse.java
+++ b/core/src/main/java/org/elasticsearch/action/admin/indices/analyze/DetailAnalyzeResponse.java
@@ -292,7 +292,7 @@ public class DetailAnalyzeResponse implements Streamable, ToXContent {
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(Fields.NAME, name);
- builder.field(Fields.FILTERED_TEXT, texts);
+ builder.array(Fields.FILTERED_TEXT, texts);
builder.endObject();
return builder;
}
diff --git a/core/src/main/java/org/elasticsearch/common/xcontent/XContent.java b/core/src/main/java/org/elasticsearch/common/xcontent/XContent.java
index 83facb00f00..c73f5f19d25 100644
--- a/core/src/main/java/org/elasticsearch/common/xcontent/XContent.java
+++ b/core/src/main/java/org/elasticsearch/common/xcontent/XContent.java
@@ -19,7 +19,6 @@
package org.elasticsearch.common.xcontent;
-import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import java.io.IOException;
diff --git a/core/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java b/core/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java
index 5274773b994..32317d8e9d5 100644
--- a/core/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java
+++ b/core/src/main/java/org/elasticsearch/common/xcontent/XContentBuilder.java
@@ -20,7 +20,6 @@
package org.elasticsearch.common.xcontent;
import org.apache.lucene.util.BytesRef;
-import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.io.BytesStream;
@@ -34,11 +33,10 @@ import org.joda.time.ReadableInstant;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
+import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
import java.nio.file.Path;
import java.util.Calendar;
import java.util.Collections;
@@ -46,32 +44,96 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* A utility to build XContent (ie json).
*/
-public final class XContentBuilder implements BytesStream, Releasable {
-
- public static final DateTimeFormatter defaultDatePrinter = ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC);
+public final class XContentBuilder implements BytesStream, Releasable, Flushable {
+ /**
+ * Create a new {@link XContentBuilder} using the given {@link XContent} content.
+ *
+ * The builder uses an internal {@link BytesStreamOutput} output stream to build the content.
+ *
+ *
+ * @param xContent the {@link XContent}
+ * @return a new {@link XContentBuilder}
+ * @throws IOException if an {@link IOException} occurs while building the content
+ */
public static XContentBuilder builder(XContent xContent) throws IOException {
return new XContentBuilder(xContent, new BytesStreamOutput());
}
+ /**
+ * Create a new {@link XContentBuilder} using the given {@link XContent} content and some inclusive and/or exclusive filters.
+ *
+ * The builder uses an internal {@link BytesStreamOutput} output stream to build the content. When both exclusive and
+ * inclusive filters are provided, the underlying builder will first use exclusion filters to remove fields and then will check the
+ * remaining fields against the inclusive filters.
+ *
+ *
+ * @param xContent the {@link XContent}
+ * @param includes the inclusive filters: only fields and objects that match the inclusive filters will be written to the output.
+ * @param excludes the exclusive filters: only fields and objects that don't match the exclusive filters will be written to the output.
+ * @throws IOException if an {@link IOException} occurs while building the content
+ */
public static XContentBuilder builder(XContent xContent, Set includes, Set excludes) throws IOException {
return new XContentBuilder(xContent, new BytesStreamOutput(), includes, excludes);
}
- private XContentGenerator generator;
+ public static final DateTimeFormatter DEFAULT_DATE_PRINTER = ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC);
+ private static final Map, Writer> WRITERS;
+ static {
+ Map, Writer> writers = new HashMap<>();
+ writers.put(Boolean.class, (b, v) -> b.value((Boolean) v));
+ writers.put(Byte.class, (b, v) -> b.value((Byte) v));
+ writers.put(byte[].class, (b, v) -> b.value((byte[]) v));
+ writers.put(BytesRef.class, (b, v) -> b.binaryValue((BytesRef) v));
+ writers.put(Date.class, (b, v) -> b.value((Date) v));
+ writers.put(Double.class, (b, v) -> b.value((Double) v));
+ writers.put(double[].class, (b, v) -> b.values((double[]) v));
+ writers.put(Float.class, (b, v) -> b.value((Float) v));
+ writers.put(float[].class, (b, v) -> b.values((float[]) v));
+ writers.put(GeoPoint.class, (b, v) -> b.value((GeoPoint) v));
+ writers.put(Integer.class, (b, v) -> b.value((Integer) v));
+ writers.put(int[].class, (b, v) -> b.values((int[]) v));
+ writers.put(Long.class, (b, v) -> b.value((Long) v));
+ writers.put(long[].class, (b, v) -> b.values((long[]) v));
+ writers.put(Short.class, (b, v) -> b.value((Short) v));
+ writers.put(short[].class, (b, v) -> b.values((short[]) v));
+ writers.put(String.class, (b, v) -> b.value((String) v));
+ writers.put(String[].class, (b, v) -> b.values((String[]) v));
+ writers.put(Text.class, (b, v) -> b.value((Text) v));
+
+ WRITERS = Collections.unmodifiableMap(writers);
+ }
+
+ @FunctionalInterface
+ private interface Writer {
+ void write(XContentBuilder builder, Object value) throws IOException;
+ }
+
+ /**
+ * XContentGenerator used to build the XContent object
+ */
+ private final XContentGenerator generator;
+
+ /**
+ * Output stream to which the built object is written
+ */
private final OutputStream bos;
+ /**
+ * When this flag is set to true, some types of values are written in a format easier to read for a human.
+ */
private boolean humanReadable = false;
/**
- * Constructs a new builder using the provided xcontent and an OutputStream. Make sure
+ * Constructs a new builder using the provided XContent and an OutputStream. Make sure
* to call {@link #close()} when the builder is done with.
*/
public XContentBuilder(XContent xContent, OutputStream bos) throws IOException {
@@ -79,7 +141,7 @@ public final class XContentBuilder implements BytesStream, Releasable {
}
/**
- * Constructs a new builder using the provided xcontent, an OutputStream and
+ * Constructs a new builder using the provided XContent, an OutputStream and
* some filters. If filters are specified, only those values matching a
* filter will be written to the output stream. Make sure to call
* {@link #close()} when the builder is done with.
@@ -117,377 +179,74 @@ public final class XContentBuilder implements BytesStream, Releasable {
return generator.isPrettyPrint();
}
+ /**
+ * Indicate that the current {@link XContentBuilder} must write a line feed ("\n")
+ * at the end of the built object.
+ *
+ * This only applies for JSON XContent type. It has no effect for other types.
+ */
public XContentBuilder lfAtEnd() {
generator.usePrintLineFeedAtEnd();
return this;
}
+ /**
+ * Set the "human readable" flag. Once set, some types of values are written in a
+ * format easier to read for a human.
+ */
public XContentBuilder humanReadable(boolean humanReadable) {
this.humanReadable = humanReadable;
return this;
}
+ /**
+ * @return the value of the "human readable" flag. When the value is equal to true,
+ * some types of values are written in a format easier to read for a human.
+ */
public boolean humanReadable() {
return this.humanReadable;
}
- public XContentBuilder field(String name, ToXContent xContent) throws IOException {
- field(name);
- xContent.toXContent(this, ToXContent.EMPTY_PARAMS);
- return this;
- }
-
- public XContentBuilder field(String name, ToXContent xContent, ToXContent.Params params) throws IOException {
- field(name);
- xContent.toXContent(this, params);
- return this;
- }
-
- public XContentBuilder startObject(String name) throws IOException {
- field(name);
- startObject();
- return this;
- }
+ ////////////////////////////////////////////////////////////////////////////
+ // Structure (object, array, field, null values...)
+ //////////////////////////////////
public XContentBuilder startObject() throws IOException {
generator.writeStartObject();
return this;
}
+ public XContentBuilder startObject(String name) throws IOException {
+ return field(name).startObject();
+ }
+
public XContentBuilder endObject() throws IOException {
generator.writeEndObject();
return this;
}
- public XContentBuilder array(String name, String... values) throws IOException {
- startArray(name);
- for (String value : values) {
- value(value);
- }
- endArray();
- return this;
- }
-
- public XContentBuilder array(String name, Object... values) throws IOException {
- startArray(name);
- for (Object value : values) {
- value(value);
- }
- endArray();
- return this;
- }
-
- public XContentBuilder startArray(String name) throws IOException {
- field(name);
- startArray();
- return this;
- }
-
public XContentBuilder startArray() throws IOException {
generator.writeStartArray();
return this;
}
+ public XContentBuilder startArray(String name) throws IOException {
+ return field(name).startArray();
+ }
+
public XContentBuilder endArray() throws IOException {
generator.writeEndArray();
return this;
}
public XContentBuilder field(String name) throws IOException {
- if (name == null) {
- throw new IllegalArgumentException("field name cannot be null");
- }
+ ensureNameNotNull(name);
generator.writeFieldName(name);
return this;
}
- public XContentBuilder field(String name, char[] value, int offset, int length) throws IOException {
- field(name);
- if (value == null) {
- generator.writeNull();
- } else {
- generator.writeString(value, offset, length);
- }
- return this;
- }
-
- public XContentBuilder field(String name, String value) throws IOException {
- field(name);
- if (value == null) {
- generator.writeNull();
- } else {
- generator.writeString(value);
- }
- return this;
- }
-
- public XContentBuilder field(String name, Integer value) throws IOException {
- field(name);
- if (value == null) {
- generator.writeNull();
- } else {
- generator.writeNumber(value.intValue());
- }
- return this;
- }
-
- public XContentBuilder field(String name, int value) throws IOException {
- field(name);
- generator.writeNumber(value);
- return this;
- }
-
- public XContentBuilder field(String name, Long value) throws IOException {
- field(name);
- if (value == null) {
- generator.writeNull();
- } else {
- generator.writeNumber(value.longValue());
- }
- return this;
- }
-
- public XContentBuilder field(String name, long value) throws IOException {
- field(name);
- generator.writeNumber(value);
- return this;
- }
-
- public XContentBuilder field(String name, Float value) throws IOException {
- field(name);
- if (value == null) {
- generator.writeNull();
- } else {
- generator.writeNumber(value.floatValue());
- }
- return this;
- }
-
- public XContentBuilder field(String name, float value) throws IOException {
- field(name);
- generator.writeNumber(value);
- return this;
- }
-
- public XContentBuilder field(String name, Double value) throws IOException {
- field(name);
- if (value == null) {
- generator.writeNull();
- } else {
- generator.writeNumber(value);
- }
- return this;
- }
-
- public XContentBuilder field(String name, double value) throws IOException {
- field(name);
- generator.writeNumber(value);
- return this;
- }
-
- public XContentBuilder field(String name, BigDecimal value) throws IOException {
- return field(name, value, value.scale(), RoundingMode.HALF_UP, true);
- }
-
- public XContentBuilder field(String name, BigDecimal value, int scale, RoundingMode rounding, boolean toDouble) throws IOException {
- field(name);
- if (value == null) {
- generator.writeNull();
- } else {
- if (toDouble) {
- try {
- generator.writeNumber(value.setScale(scale, rounding).doubleValue());
- } catch (ArithmeticException e) {
- generator.writeString(value.toEngineeringString());
- }
- } else {
- generator.writeString(value.toEngineeringString());
- }
- }
- return this;
- }
-
- /**
- * Writes the binary content of the given BytesRef
- * Use {@link org.elasticsearch.common.xcontent.XContentParser#binaryValue()} to read the value back
- */
- public XContentBuilder field(String name, BytesRef value) throws IOException {
- field(name);
- generator.writeBinary(value.bytes, value.offset, value.length);
- return this;
- }
-
- /**
- * Writes the binary content of the given BytesReference
- * Use {@link org.elasticsearch.common.xcontent.XContentParser#binaryValue()} to read the value back
- */
- public XContentBuilder field(String name, BytesReference value) throws IOException {
- field(name);
- final BytesRef ref = value.toBytesRef();
- generator.writeBinary(ref.bytes, ref.offset, ref.length);
- return this;
- }
-
- /**
- * Writes the binary content of the given BytesRef as UTF-8 bytes
- * Use {@link XContentParser#utf8Bytes()} to read the value back
- */
- public XContentBuilder utf8Field(String name, BytesRef value) throws IOException {
- field(name);
- generator.writeUTF8String(value.bytes, value.offset, value.length);
- return this;
- }
-
- public XContentBuilder field(String name, Text value) throws IOException {
- field(name);
- if (value.hasString()) {
- generator.writeString(value.string());
- } else {
- // TODO: TextBytesOptimization we can use a buffer here to convert it? maybe add a request to jackson to support InputStream as well?
- final BytesRef ref = value.bytes().toBytesRef();
- generator.writeUTF8String(ref.bytes, ref.offset, ref.length);
- }
- return this;
- }
-
- public XContentBuilder field(String name, byte[] value, int offset, int length) throws IOException {
- field(name);
- generator.writeBinary(value, offset, length);
- return this;
- }
-
- public XContentBuilder field(String name, Map value) throws IOException {
- field(name);
- value(value);
- return this;
- }
-
- public XContentBuilder field(String name, Iterable> value) throws IOException {
- if (value instanceof Path) {
- //treat Paths as single value
- field(name);
- value(value);
- } else {
- startArray(name);
- for (Object o : value) {
- value(o);
- }
- endArray();
- }
- return this;
- }
-
- public XContentBuilder field(String name, boolean... value) throws IOException {
- startArray(name);
- for (boolean o : value) {
- value(o);
- }
- endArray();
- return this;
- }
-
- public XContentBuilder field(String name, String... value) throws IOException {
- startArray(name);
- for (String o : value) {
- value(o);
- }
- endArray();
- return this;
- }
-
- public XContentBuilder field(String name, Object... value) throws IOException {
- startArray(name);
- for (Object o : value) {
- value(o);
- }
- endArray();
- return this;
- }
-
- public XContentBuilder field(String name, int... value) throws IOException {
- startArray(name);
- for (Object o : value) {
- value(o);
- }
- endArray();
- return this;
- }
-
- public XContentBuilder field(String name, long... value) throws IOException {
- startArray(name);
- for (Object o : value) {
- value(o);
- }
- endArray();
- return this;
- }
-
- public XContentBuilder field(String name, float... value) throws IOException {
- startArray(name);
- for (Object o : value) {
- value(o);
- }
- endArray();
- return this;
- }
-
- public XContentBuilder field(String name, double... value) throws IOException {
- startArray(name);
- for (Object o : value) {
- value(o);
- }
- endArray();
- return this;
- }
-
- public XContentBuilder field(String name, Object value) throws IOException {
- field(name);
- writeValue(value);
- return this;
- }
-
- public XContentBuilder value(Object value) throws IOException {
- writeValue(value);
- return this;
- }
-
- public XContentBuilder field(String name, boolean value) throws IOException {
- field(name);
- generator.writeBoolean(value);
- return this;
- }
-
- public XContentBuilder field(String name, byte[] value) throws IOException {
- field(name);
- if (value == null) {
- generator.writeNull();
- } else {
- generator.writeBinary(value);
- }
- return this;
- }
-
- public XContentBuilder field(String name, ReadableInstant date) throws IOException {
- field(name);
- return value(date);
- }
-
- public XContentBuilder field(String name, ReadableInstant date, DateTimeFormatter formatter) throws IOException {
- field(name);
- return value(date, formatter);
- }
-
- public XContentBuilder field(String name, Date date) throws IOException {
- field(name);
- return value(date);
- }
-
- public XContentBuilder field(String name, Date date, DateTimeFormatter formatter) throws IOException {
- field(name);
- return value(date, formatter);
- }
-
public XContentBuilder nullField(String name) throws IOException {
+ ensureNameNotNull(name);
generator.writeNullField(name);
return this;
}
@@ -497,21 +256,644 @@ public final class XContentBuilder implements BytesStream, Releasable {
return this;
}
- public XContentBuilder rawField(String fieldName, InputStream content) throws IOException {
- generator.writeRawField(fieldName, content);
+ ////////////////////////////////////////////////////////////////////////////
+ // Boolean
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, Boolean value) throws IOException {
+ return (value == null) ? nullField(name) : field(name, value.booleanValue());
+ }
+
+ public XContentBuilder field(String name, boolean value) throws IOException {
+ ensureNameNotNull(name);
+ generator.writeBooleanField(name, value);
return this;
}
- public XContentBuilder rawField(String fieldName, BytesReference content) throws IOException {
- generator.writeRawField(fieldName, content);
+ public XContentBuilder array(String name, boolean[] values) throws IOException {
+ return field(name).values(values);
+ }
+
+ private XContentBuilder values(boolean[] values) throws IOException {
+ if (values == null) {
+ return nullValue();
+ }
+ startArray();
+ for (boolean b : values) {
+ value(b);
+ }
+ endArray();
return this;
}
- public XContentBuilder rawValue(BytesReference content) throws IOException {
- generator.writeRawValue(content);
+ public XContentBuilder value(Boolean value) throws IOException {
+ return (value == null) ? nullValue() : value(value.booleanValue());
+ }
+
+ public XContentBuilder value(boolean value) throws IOException {
+ generator.writeBoolean(value);
return this;
}
+ ////////////////////////////////////////////////////////////////////////////
+ // Byte
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, Byte value) throws IOException {
+ return (value == null) ? nullField(name) : field(name, value.byteValue());
+ }
+
+ public XContentBuilder field(String name, byte value) throws IOException {
+ return field(name).value(value);
+ }
+
+ public XContentBuilder value(Byte value) throws IOException {
+ return (value == null) ? nullValue() : value(value.byteValue());
+ }
+
+ public XContentBuilder value(byte value) throws IOException {
+ generator.writeNumber(value);
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Double
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, Double value) throws IOException {
+ return (value == null) ? nullField(name) : field(name, value.doubleValue());
+ }
+
+ public XContentBuilder field(String name, double value) throws IOException {
+ ensureNameNotNull(name);
+ generator.writeNumberField(name, value);
+ return this;
+ }
+
+ public XContentBuilder array(String name, double[] values) throws IOException {
+ return field(name).values(values);
+ }
+
+ private XContentBuilder values(double[] values) throws IOException {
+ if (values == null) {
+ return nullValue();
+ }
+ startArray();
+ for (double b : values) {
+ value(b);
+ }
+ endArray();
+ return this;
+ }
+
+ public XContentBuilder value(Double value) throws IOException {
+ return (value == null) ? nullValue() : value(value.doubleValue());
+ }
+
+ public XContentBuilder value(double value) throws IOException {
+ generator.writeNumber(value);
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Float
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, Float value) throws IOException {
+ return (value == null) ? nullField(name) : field(name, value.floatValue());
+ }
+
+ public XContentBuilder field(String name, float value) throws IOException {
+ ensureNameNotNull(name);
+ generator.writeNumberField(name, value);
+ return this;
+ }
+
+ public XContentBuilder array(String name, float[] values) throws IOException {
+ return field(name).values(values);
+ }
+
+ private XContentBuilder values(float[] values) throws IOException {
+ if (values == null) {
+ return nullValue();
+ }
+ startArray();
+ for (float f : values) {
+ value(f);
+ }
+ endArray();
+ return this;
+ }
+
+ public XContentBuilder value(Float value) throws IOException {
+ return (value == null) ? nullValue() : value(value.floatValue());
+ }
+
+ public XContentBuilder value(float value) throws IOException {
+ generator.writeNumber(value);
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Integer
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, Integer value) throws IOException {
+ return (value == null) ? nullField(name) : field(name, value.intValue());
+ }
+
+ public XContentBuilder field(String name, int value) throws IOException {
+ ensureNameNotNull(name);
+ generator.writeNumberField(name, value);
+ return this;
+ }
+
+ public XContentBuilder array(String name, int[] values) throws IOException {
+ return field(name).values(values);
+ }
+
+ private XContentBuilder values(int[] values) throws IOException {
+ if (values == null) {
+ return nullValue();
+ }
+ startArray();
+ for (int i : values) {
+ value(i);
+ }
+ endArray();
+ return this;
+ }
+
+ public XContentBuilder value(Integer value) throws IOException {
+ return (value == null) ? nullValue() : value(value.intValue());
+ }
+
+ public XContentBuilder value(int value) throws IOException {
+ generator.writeNumber(value);
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Long
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, Long value) throws IOException {
+ return (value == null) ? nullField(name) : field(name, value.longValue());
+ }
+
+ public XContentBuilder field(String name, long value) throws IOException {
+ ensureNameNotNull(name);
+ generator.writeNumberField(name, value);
+ return this;
+ }
+
+ public XContentBuilder array(String name, long[] values) throws IOException {
+ return field(name).values(values);
+ }
+
+ private XContentBuilder values(long[] values) throws IOException {
+ if (values == null) {
+ return nullValue();
+ }
+ startArray();
+ for (long l : values) {
+ value(l);
+ }
+ endArray();
+ return this;
+ }
+
+ public XContentBuilder value(Long value) throws IOException {
+ return (value == null) ? nullValue() : value(value.longValue());
+ }
+
+ public XContentBuilder value(long value) throws IOException {
+ generator.writeNumber(value);
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Short
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, Short value) throws IOException {
+ return (value == null) ? nullField(name) : field(name, value.shortValue());
+ }
+
+ public XContentBuilder field(String name, short value) throws IOException {
+ return field(name).value(value);
+ }
+
+ public XContentBuilder array(String name, short[] values) throws IOException {
+ return field(name).values(values);
+ }
+
+ private XContentBuilder values(short[] values) throws IOException {
+ if (values == null) {
+ return nullValue();
+ }
+ startArray();
+ for (short s : values) {
+ value(s);
+ }
+ endArray();
+ return this;
+ }
+
+ public XContentBuilder value(Short value) throws IOException {
+ return (value == null) ? nullValue() : value(value.shortValue());
+ }
+
+ public XContentBuilder value(short value) throws IOException {
+ generator.writeNumber(value);
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // String
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, String value) throws IOException {
+ if (value == null) {
+ return nullField(name);
+ }
+ ensureNameNotNull(name);
+ generator.writeStringField(name, value);
+ return this;
+ }
+
+ public XContentBuilder array(String name, String... values) throws IOException {
+ return field(name).values(values);
+ }
+
+ private XContentBuilder values(String[] values) throws IOException {
+ if (values == null) {
+ return nullValue();
+ }
+ startArray();
+ for (String s : values) {
+ value(s);
+ }
+ endArray();
+ return this;
+ }
+
+ public XContentBuilder value(String value) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ generator.writeString(value);
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Binary
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, byte[] value) throws IOException {
+ if (value == null) {
+ return nullField(name);
+ }
+ ensureNameNotNull(name);
+ generator.writeBinaryField(name, value);
+ return this;
+ }
+
+ public XContentBuilder value(byte[] value) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ generator.writeBinary(value);
+ return this;
+ }
+
+ public XContentBuilder field(String name, byte[] value, int offset, int length) throws IOException {
+ return field(name).value(value, offset, length);
+ }
+
+ public XContentBuilder value(byte[] value, int offset, int length) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ generator.writeBinary(value, offset, length);
+ return this;
+ }
+
+ /**
+ * Writes the binary content of the given {@link BytesRef}.
+ *
+ * Use {@link org.elasticsearch.common.xcontent.XContentParser#binaryValue()} to read the value back
+ */
+ public XContentBuilder field(String name, BytesRef value) throws IOException {
+ return field(name).binaryValue(value);
+ }
+
+ /**
+ * Writes the binary content of the given {@link BytesRef} as UTF-8 bytes.
+ *
+ * Use {@link XContentParser#utf8Bytes()} to read the value back
+ */
+ public XContentBuilder utf8Field(String name, BytesRef value) throws IOException {
+ return field(name).utf8Value(value);
+ }
+
+ /**
+ * Writes the binary content of the given {@link BytesRef}.
+ *
+ * Use {@link org.elasticsearch.common.xcontent.XContentParser#binaryValue()} to read the value back
+ */
+ public XContentBuilder binaryValue(BytesRef value) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ value(value.bytes, value.offset, value.length);
+ return this;
+ }
+
+ /**
+ * Writes the binary content of the given {@link BytesRef} as UTF-8 bytes.
+ *
+ * Use {@link XContentParser#utf8Bytes()} to read the value back
+ */
+ public XContentBuilder utf8Value(BytesRef value) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ generator.writeUTF8String(value.bytes, value.offset, value.length);
+ return this;
+ }
+
+ /**
+ * Writes the binary content of the given {@link BytesReference}.
+ *
+ * Use {@link org.elasticsearch.common.xcontent.XContentParser#binaryValue()} to read the value back
+ */
+ public XContentBuilder field(String name, BytesReference value) throws IOException {
+ return field(name).value(value);
+ }
+
+ /**
+ * Writes the binary content of the given {@link BytesReference}.
+ *
+ * Use {@link org.elasticsearch.common.xcontent.XContentParser#binaryValue()} to read the value back
+ */
+ public XContentBuilder value(BytesReference value) throws IOException {
+ return (value == null) ? nullValue() : binaryValue(value.toBytesRef());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Text
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, Text value) throws IOException {
+ return field(name).value(value);
+ }
+
+ public XContentBuilder value(Text value) throws IOException {
+ if (value == null) {
+ return nullValue();
+ } else if (value.hasString()) {
+ return value(value.string());
+ } else {
+ // TODO: TextBytesOptimization we can use a buffer here to convert it? maybe add a
+ // request to jackson to support InputStream as well?
+ return utf8Value(value.bytes().toBytesRef());
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Date
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, ReadableInstant value) throws IOException {
+ return field(name).value(value);
+ }
+
+ public XContentBuilder field(String name, ReadableInstant value, DateTimeFormatter formatter) throws IOException {
+ return field(name).value(value, formatter);
+ }
+
+ public XContentBuilder value(ReadableInstant value) throws IOException {
+ return value(value, DEFAULT_DATE_PRINTER);
+ }
+
+ public XContentBuilder value(ReadableInstant value, DateTimeFormatter formatter) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ ensureFormatterNotNull(formatter);
+ return value(formatter.print(value));
+ }
+
+ public XContentBuilder field(String name, Date value) throws IOException {
+ return field(name).value(value);
+ }
+
+ public XContentBuilder field(String name, Date value, DateTimeFormatter formatter) throws IOException {
+ return field(name).value(value, formatter);
+ }
+
+ public XContentBuilder value(Date value) throws IOException {
+ return value(value, DEFAULT_DATE_PRINTER);
+ }
+
+ public XContentBuilder value(Date value, DateTimeFormatter formatter) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ return value(formatter, value.getTime());
+ }
+
+ public XContentBuilder dateField(String name, String readableName, long value) throws IOException {
+ if (humanReadable) {
+ field(readableName).value(DEFAULT_DATE_PRINTER, value);
+ }
+ field(name, value);
+ return this;
+ }
+
+ XContentBuilder value(Calendar value) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ return value(DEFAULT_DATE_PRINTER, value.getTimeInMillis());
+ }
+
+ XContentBuilder value(DateTimeFormatter formatter, long value) throws IOException {
+ ensureFormatterNotNull(formatter);
+ return value(formatter.print(value));
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // GeoPoint & LatLon
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, GeoPoint value) throws IOException {
+ return field(name).value(value);
+ }
+
+ public XContentBuilder value(GeoPoint value) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ return latlon(value.getLat(), value.getLon());
+ }
+
+ public XContentBuilder latlon(String name, double lat, double lon) throws IOException {
+ return field(name).latlon(lat, lon);
+ }
+
+ public XContentBuilder latlon(double lat, double lon) throws IOException {
+ return startObject().field("lat", lat).field("lon", lon).endObject();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Path
+ //////////////////////////////////
+
+ public XContentBuilder value(Path value) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ return value(value.toString());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Objects
+ //
+ // These methods are used when the type of value is unknown. It tries to fallback
+ // on typed methods and use Object.toString() as a last resort. Always prefer using
+ // typed methods over this.
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, Object value) throws IOException {
+ return field(name).value(value);
+ }
+
+ public XContentBuilder array(String name, Object... values) throws IOException {
+ return field(name).values(values);
+ }
+
+ XContentBuilder values(Object[] values) throws IOException {
+ if (values == null) {
+ return nullValue();
+ }
+ startArray();
+ for (Object o : values) {
+ value(o);
+ }
+ endArray();
+ return this;
+ }
+
+ public XContentBuilder value(Object value) throws IOException {
+ unknownValue(value);
+ return this;
+ }
+
+ private void unknownValue(Object value) throws IOException {
+ if (value == null) {
+ nullValue();
+ return;
+ }
+ Writer writer = WRITERS.get(value.getClass());
+ if (writer != null) {
+ writer.write(this, value);
+ } else if (value instanceof Path) {
+ //Path implements Iterable and causes endless recursion and a StackOverFlow if treated as an Iterable here
+ value((Path) value);
+ } else if (value instanceof Map) {
+ map((Map) value);
+ } else if (value instanceof Iterable) {
+ value((Iterable>) value);
+ } else if (value instanceof Object[]) {
+ values((Object[]) value);
+ } else if (value instanceof Calendar) {
+ value((Calendar) value);
+ } else if (value instanceof ReadableInstant) {
+ value((ReadableInstant) value);
+ } else if (value instanceof BytesReference) {
+ value((BytesReference) value);
+ } else if (value instanceof ToXContent) {
+ value((ToXContent) value);
+ } else {
+ // This is a "value" object (like enum, DistanceUnit, etc) just toString() it
+ // (yes, it can be misleading when toString a Java class, but really, jackson should be used in that case)
+ value(Objects.toString(value));
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // ToXContent
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, ToXContent value) throws IOException {
+ return field(name).value(value);
+ }
+
+ public XContentBuilder field(String name, ToXContent value, ToXContent.Params params) throws IOException {
+ return field(name).value(value, params);
+ }
+
+ private XContentBuilder value(ToXContent value) throws IOException {
+ return value(value, ToXContent.EMPTY_PARAMS);
+ }
+
+ private XContentBuilder value(ToXContent value, ToXContent.Params params) throws IOException {
+ if (value == null) {
+ return nullValue();
+ }
+ value.toXContent(this, params);
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Maps & Iterable
+ //////////////////////////////////
+
+ public XContentBuilder field(String name, Map values) throws IOException {
+ return field(name).map(values);
+ }
+
+ public XContentBuilder map(Map values) throws IOException {
+ if (values == null) {
+ return nullValue();
+ }
+ startObject();
+ for (Map.Entry value : values.entrySet()) {
+ field(value.getKey());
+ unknownValue(value.getValue());
+ }
+ endObject();
+ return this;
+ }
+
+ public XContentBuilder field(String name, Iterable> values) throws IOException {
+ return field(name).value(values);
+ }
+
+ private XContentBuilder value(Iterable> values) throws IOException {
+ if (values == null) {
+ return nullValue();
+ }
+
+ if (values instanceof Path) {
+ //treat as single value
+ value((Path) values);
+ } else {
+ startArray();
+ for (Object value : values) {
+ unknownValue(value);
+ }
+ endArray();
+ }
+ return this;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Misc.
+ //////////////////////////////////
+
public XContentBuilder timeValueField(String rawFieldName, String readableFieldName, TimeValue timeValue) throws IOException {
if (humanReadable) {
field(readableFieldName, timeValue.toString());
@@ -529,7 +911,7 @@ public final class XContentBuilder implements BytesStream, Releasable {
}
public XContentBuilder timeValueField(String rawFieldName, String readableFieldName, long rawTime, TimeUnit timeUnit) throws
- IOException {
+ IOException {
if (humanReadable) {
field(readableFieldName, new TimeValue(rawTime, timeUnit).toString());
}
@@ -537,11 +919,12 @@ public final class XContentBuilder implements BytesStream, Releasable {
return this;
}
- public XContentBuilder dateValueField(String rawFieldName, String readableFieldName, long rawTimestamp) throws IOException {
+
+ public XContentBuilder percentageField(String rawFieldName, String readableFieldName, double percentage) throws IOException {
if (humanReadable) {
- field(readableFieldName, defaultDatePrinter.print(rawTimestamp));
+ field(readableFieldName, String.format(Locale.ROOT, "%1.1f%%", percentage));
}
- field(rawFieldName, rawTimestamp);
+ field(rawFieldName, percentage);
return this;
}
@@ -561,206 +944,33 @@ public final class XContentBuilder implements BytesStream, Releasable {
return this;
}
- public XContentBuilder percentageField(String rawFieldName, String readableFieldName, double percentage) throws IOException {
- if (humanReadable) {
- field(readableFieldName, String.format(Locale.ROOT, "%1.1f%%", percentage));
- }
- field(rawFieldName, percentage);
+ ////////////////////////////////////////////////////////////////////////////
+ // Raw fields
+ //////////////////////////////////
+
+ public XContentBuilder rawField(String name, InputStream value) throws IOException {
+ generator.writeRawField(name, value);
return this;
}
- public XContentBuilder value(Boolean value) throws IOException {
- if (value == null) {
- return nullValue();
- }
- return value(value.booleanValue());
- }
-
- public XContentBuilder value(boolean value) throws IOException {
- generator.writeBoolean(value);
+ public XContentBuilder rawField(String name, BytesReference value) throws IOException {
+ generator.writeRawField(name, value);
return this;
}
- public XContentBuilder value(ReadableInstant date) throws IOException {
- return value(date, defaultDatePrinter);
- }
-
- public XContentBuilder value(ReadableInstant date, DateTimeFormatter dateTimeFormatter) throws IOException {
- if (date == null) {
- return nullValue();
- }
- return value(dateTimeFormatter.print(date));
- }
-
- public XContentBuilder value(Date date) throws IOException {
- return value(date, defaultDatePrinter);
- }
-
- public XContentBuilder value(Date date, DateTimeFormatter dateTimeFormatter) throws IOException {
- if (date == null) {
- return nullValue();
- }
- return value(dateTimeFormatter.print(date.getTime()));
- }
-
- public XContentBuilder value(Integer value) throws IOException {
- if (value == null) {
- return nullValue();
- }
- return value(value.intValue());
- }
-
- public XContentBuilder value(int value) throws IOException {
- generator.writeNumber(value);
+ public XContentBuilder rawValue(BytesReference value) throws IOException {
+ generator.writeRawValue(value);
return this;
}
- public XContentBuilder value(Long value) throws IOException {
- if (value == null) {
- return nullValue();
- }
- return value(value.longValue());
- }
-
- public XContentBuilder value(long value) throws IOException {
- generator.writeNumber(value);
- return this;
- }
-
- public XContentBuilder value(Float value) throws IOException {
- if (value == null) {
- return nullValue();
- }
- return value(value.floatValue());
- }
-
- public XContentBuilder value(float value) throws IOException {
- generator.writeNumber(value);
- return this;
- }
-
- public XContentBuilder value(Double value) throws IOException {
- if (value == null) {
- return nullValue();
- }
- return value(value.doubleValue());
- }
-
- public XContentBuilder value(double value) throws IOException {
- generator.writeNumber(value);
- return this;
- }
-
- public XContentBuilder value(String value) throws IOException {
- if (value == null) {
- return nullValue();
- }
- generator.writeString(value);
- return this;
- }
-
- public XContentBuilder value(byte[] value) throws IOException {
- if (value == null) {
- return nullValue();
- }
- generator.writeBinary(value);
- return this;
- }
-
- public XContentBuilder value(byte[] value, int offset, int length) throws IOException {
- if (value == null) {
- return nullValue();
- }
- generator.writeBinary(value, offset, length);
- return this;
- }
-
- /**
- * Writes the binary content of the given BytesRef
- * Use {@link org.elasticsearch.common.xcontent.XContentParser#binaryValue()} to read the value back
- */
- public XContentBuilder value(BytesRef value) throws IOException {
- if (value == null) {
- return nullValue();
- }
- generator.writeBinary(value.bytes, value.offset, value.length);
- return this;
- }
-
- /**
- * Writes the binary content of the given BytesReference
- * Use {@link org.elasticsearch.common.xcontent.XContentParser#binaryValue()} to read the value back
- */
- public XContentBuilder value(BytesReference value) throws IOException {
- if (value == null) {
- return nullValue();
- }
- BytesRef ref = value.toBytesRef();
- generator.writeBinary(ref.bytes, ref.offset, ref.length);
- return this;
- }
-
- public XContentBuilder value(Text value) throws IOException {
- if (value == null) {
- return nullValue();
- } else if (value.hasString()) {
- generator.writeString(value.string());
- } else {
- BytesRef bytesRef = value.bytes().toBytesRef();
- generator.writeUTF8String(bytesRef.bytes, bytesRef.offset, bytesRef.length);
- }
- return this;
- }
-
- public XContentBuilder map(Map map) throws IOException {
- if (map == null) {
- return nullValue();
- }
- writeMap(map);
- return this;
- }
-
- public XContentBuilder value(Map map) throws IOException {
- if (map == null) {
- return nullValue();
- }
- writeMap(map);
- return this;
- }
-
- public XContentBuilder value(Iterable> value) throws IOException {
- if (value == null) {
- return nullValue();
- }
- if (value instanceof Path) {
- //treat as single value
- writeValue(value);
- } else {
- startArray();
- for (Object o : value) {
- value(o);
- }
- endArray();
- }
- return this;
- }
-
- public XContentBuilder latlon(String name, double lat, double lon) throws IOException {
- return startObject(name).field("lat", lat).field("lon", lon).endObject();
- }
-
- public XContentBuilder latlon(double lat, double lon) throws IOException {
- return startObject().field("lat", lat).field("lon", lon).endObject();
- }
-
public XContentBuilder copyCurrentStructure(XContentParser parser) throws IOException {
generator.copyCurrentStructure(parser);
return this;
}
- public XContentBuilder flush() throws IOException {
+ @Override
+ public void flush() throws IOException {
generator.flush();
- return this;
}
@Override
@@ -768,7 +978,7 @@ public final class XContentBuilder implements BytesStream, Releasable {
try {
generator.close();
} catch (IOException e) {
- throw new IllegalStateException("failed to close the XContentBuilder", e);
+ throw new IllegalStateException("Failed to close the XContentBuilder", e);
}
}
@@ -786,156 +996,20 @@ public final class XContentBuilder implements BytesStream, Releasable {
* Returns a string representation of the builder (only applicable for text based xcontent).
*/
public String string() throws IOException {
- close();
return bytes().utf8ToString();
}
-
- private void writeMap(Map map) throws IOException {
- generator.writeStartObject();
-
- for (Map.Entry entry : map.entrySet()) {
- field(entry.getKey());
- Object value = entry.getValue();
- if (value == null) {
- generator.writeNull();
- } else {
- writeValue(value);
- }
- }
- generator.writeEndObject();
+ static void ensureNameNotNull(String name) {
+ ensureNotNull(name, "Field name cannot be null");
}
- @FunctionalInterface
- interface Writer {
- void write(XContentGenerator g, Object v) throws IOException;
+ static void ensureFormatterNotNull(DateTimeFormatter formatter) {
+ ensureNotNull(formatter, "DateTimeFormatter cannot be null");
}
- private static final Map, Writer> MAP;
-
- static {
- Map, Writer> map = new HashMap<>();
- map.put(String.class, (g, v) -> g.writeString((String) v));
- map.put(Integer.class, (g, v) -> g.writeNumber((Integer) v));
- map.put(Long.class, (g, v) -> g.writeNumber((Long) v));
- map.put(Float.class, (g, v) -> g.writeNumber((Float) v));
- map.put(Double.class, (g, v) -> g.writeNumber((Double) v));
- map.put(Byte.class, (g, v) -> g.writeNumber((Byte) v));
- map.put(Short.class, (g, v) -> g.writeNumber((Short) v));
- map.put(Boolean.class, (g, v) -> g.writeBoolean((Boolean) v));
- map.put(GeoPoint.class, (g, v) -> {
- g.writeStartObject();
- g.writeNumberField("lat", ((GeoPoint) v).lat());
- g.writeNumberField("lon", ((GeoPoint) v).lon());
- g.writeEndObject();
- });
- map.put(int[].class, (g, v) -> {
- g.writeStartArray();
- for (int item : (int[]) v) {
- g.writeNumber(item);
- }
- g.writeEndArray();
- });
- map.put(long[].class, (g, v) -> {
- g.writeStartArray();
- for (long item : (long[]) v) {
- g.writeNumber(item);
- }
- g.writeEndArray();
- });
- map.put(float[].class, (g, v) -> {
- g.writeStartArray();
- for (float item : (float[]) v) {
- g.writeNumber(item);
- }
- g.writeEndArray();
- });
- map.put(double[].class, (g, v) -> {
- g.writeStartArray();
- for (double item : (double[])v) {
- g.writeNumber(item);
- }
- g.writeEndArray();
- });
- map.put(byte[].class, (g, v) -> g.writeBinary((byte[]) v));
- map.put(short[].class, (g, v) -> {
- g.writeStartArray();
- for (short item : (short[])v) {
- g.writeNumber(item);
- }
- g.writeEndArray();
- });
- map.put(BytesRef.class, (g, v) -> {
- BytesRef bytes = (BytesRef) v;
- g.writeBinary(bytes.bytes, bytes.offset, bytes.length);
- });
- map.put(Text.class, (g, v) -> {
- Text text = (Text) v;
- if (text.hasString()) {
- g.writeString(text.string());
- } else {
- BytesRef ref = text.bytes().toBytesRef();
- g.writeUTF8String(ref.bytes, ref.offset, ref.length);
- }
- });
- MAP = Collections.unmodifiableMap(map);
- }
-
- private void writeValue(Object value) throws IOException {
+ static void ensureNotNull(Object value, String message) {
if (value == null) {
- generator.writeNull();
- return;
- }
- Class> type = value.getClass();
- Writer writer = MAP.get(type);
- if (writer != null) {
- writer.write(generator, value);
- } else if (value instanceof Map) {
- writeMap((Map) value);
- } else if (value instanceof Path) {
- //Path implements Iterable and causes endless recursion and a StackOverFlow if treated as an Iterable here
- generator.writeString(value.toString());
- } else if (value instanceof Iterable) {
- writeIterable((Iterable>) value);
- } else if (value instanceof Object[]) {
- writeObjectArray((Object[]) value);
- } else if (value instanceof Date) {
- generator.writeString(XContentBuilder.defaultDatePrinter.print(((Date) value).getTime()));
- } else if (value instanceof Calendar) {
- generator.writeString(XContentBuilder.defaultDatePrinter.print((((Calendar) value)).getTimeInMillis()));
- } else if (value instanceof ReadableInstant) {
- generator.writeString(XContentBuilder.defaultDatePrinter.print((((ReadableInstant) value)).getMillis()));
- } else if (value instanceof BytesReference) {
- writeBytesReference((BytesReference) value);
- } else if (value instanceof ToXContent) {
- ((ToXContent) value).toXContent(this, ToXContent.EMPTY_PARAMS);
- } else {
- // if this is a "value" object, like enum, DistanceUnit, ..., just toString it
- // yea, it can be misleading when toString a Java class, but really, jackson should be used in that case
- generator.writeString(value.toString());
- //throw new ElasticsearchIllegalArgumentException("type not supported for generic value conversion: " + type);
+ throw new IllegalArgumentException(message);
}
}
-
- private void writeBytesReference(BytesReference value) throws IOException {
- BytesRef ref = value.toBytesRef();
- generator.writeBinary(ref.bytes, ref.offset, ref.length);
- }
-
- private void writeIterable(Iterable> value) throws IOException {
- generator.writeStartArray();
- for (Object v : value) {
- writeValue(v);
- }
- generator.writeEndArray();
- }
-
- private void writeObjectArray(Object[] value) throws IOException {
- generator.writeStartArray();
- for (Object v : value) {
- writeValue(v);
- }
- generator.writeEndArray();
- }
-
}
diff --git a/core/src/main/java/org/elasticsearch/common/xcontent/XContentGenerator.java b/core/src/main/java/org/elasticsearch/common/xcontent/XContentGenerator.java
index a2cceae8367..8d1b8efef51 100644
--- a/core/src/main/java/org/elasticsearch/common/xcontent/XContentGenerator.java
+++ b/core/src/main/java/org/elasticsearch/common/xcontent/XContentGenerator.java
@@ -20,14 +20,13 @@
package org.elasticsearch.common.xcontent;
import org.elasticsearch.common.bytes.BytesReference;
+
import java.io.Closeable;
+import java.io.Flushable;
import java.io.IOException;
import java.io.InputStream;
-/**
- *
- */
-public interface XContentGenerator extends Closeable {
+public interface XContentGenerator extends Closeable, Flushable {
XContentType contentType();
@@ -37,68 +36,62 @@ public interface XContentGenerator extends Closeable {
void usePrintLineFeedAtEnd();
- void writeStartArray() throws IOException;
-
- void writeEndArray() throws IOException;
-
void writeStartObject() throws IOException;
void writeEndObject() throws IOException;
+ void writeStartArray() throws IOException;
+
+ void writeEndArray() throws IOException;
+
void writeFieldName(String name) throws IOException;
- void writeString(String text) throws IOException;
-
- void writeString(char[] text, int offset, int len) throws IOException;
-
- void writeUTF8String(byte[] text, int offset, int length) throws IOException;
-
- void writeBinary(byte[] data, int offset, int len) throws IOException;
-
- void writeBinary(byte[] data) throws IOException;
-
- void writeNumber(int v) throws IOException;
-
- void writeNumber(long v) throws IOException;
-
- void writeNumber(double d) throws IOException;
-
- void writeNumber(float f) throws IOException;
-
- void writeBoolean(boolean state) throws IOException;
-
void writeNull() throws IOException;
- void writeStringField(String fieldName, String value) throws IOException;
+ void writeNullField(String name) throws IOException;
- void writeBooleanField(String fieldName, boolean value) throws IOException;
+ void writeBooleanField(String name, boolean value) throws IOException;
- void writeNullField(String fieldName) throws IOException;
+ void writeBoolean(boolean value) throws IOException;
- void writeNumberField(String fieldName, int value) throws IOException;
+ void writeNumberField(String name, double value) throws IOException;
- void writeNumberField(String fieldName, long value) throws IOException;
+ void writeNumber(double value) throws IOException;
- void writeNumberField(String fieldName, double value) throws IOException;
+ void writeNumberField(String name, float value) throws IOException;
- void writeNumberField(String fieldName, float value) throws IOException;
+ void writeNumber(float value) throws IOException;
- void writeBinaryField(String fieldName, byte[] data) throws IOException;
+ void writeNumberField(String name, int value) throws IOException;
- void writeArrayFieldStart(String fieldName) throws IOException;
+ void writeNumber(int value) throws IOException;
- void writeObjectFieldStart(String fieldName) throws IOException;
+ void writeNumberField(String name, long value) throws IOException;
- void writeRawField(String fieldName, InputStream content) throws IOException;
+ void writeNumber(long value) throws IOException;
- void writeRawField(String fieldName, BytesReference content) throws IOException;
+ void writeNumber(short value) throws IOException;
- void writeRawValue(BytesReference content) throws IOException;
+ void writeStringField(String name, String value) throws IOException;
+
+ void writeString(String value) throws IOException;
+
+ void writeString(char[] text, int offset, int len) throws IOException;
+
+ void writeUTF8String(byte[] value, int offset, int length) throws IOException;
+
+ void writeBinaryField(String name, byte[] value) throws IOException;
+
+ void writeBinary(byte[] value) throws IOException;
+
+ void writeBinary(byte[] value, int offset, int length) throws IOException;
+
+ void writeRawField(String name, InputStream value) throws IOException;
+
+ void writeRawField(String name, BytesReference value) throws IOException;
+
+ void writeRawValue(BytesReference value) throws IOException;
void copyCurrentStructure(XContentParser parser) throws IOException;
- void flush() throws IOException;
-
- @Override
- void close() throws IOException;
}
diff --git a/core/src/main/java/org/elasticsearch/common/xcontent/json/JsonXContentGenerator.java b/core/src/main/java/org/elasticsearch/common/xcontent/json/JsonXContentGenerator.java
index 4a393b9dd10..74e1cb5e58f 100644
--- a/core/src/main/java/org/elasticsearch/common/xcontent/json/JsonXContentGenerator.java
+++ b/core/src/main/java/org/elasticsearch/common/xcontent/json/JsonXContentGenerator.java
@@ -47,9 +47,6 @@ import java.util.Collections;
import java.util.Objects;
import java.util.Set;
-/**
- *
- */
public class JsonXContentGenerator implements XContentGenerator {
/** Generator used to write content **/
@@ -130,16 +127,6 @@ public class JsonXContentGenerator implements XContentGenerator {
writeLineFeedAtEnd = true;
}
- @Override
- public void writeStartArray() throws IOException {
- generator.writeStartArray();
- }
-
- @Override
- public void writeEndArray() throws IOException {
- generator.writeEndArray();
- }
-
private boolean isFiltered() {
return filter != null;
}
@@ -184,118 +171,124 @@ public class JsonXContentGenerator implements XContentGenerator {
generator.writeEndObject();
}
+
+ @Override
+ public void writeStartArray() throws IOException {
+ generator.writeStartArray();
+ }
+
+ @Override
+ public void writeEndArray() throws IOException {
+ generator.writeEndArray();
+ }
+
@Override
public void writeFieldName(String name) throws IOException {
generator.writeFieldName(name);
}
- @Override
- public void writeString(String text) throws IOException {
- generator.writeString(text);
- }
-
- @Override
- public void writeString(char[] text, int offset, int len) throws IOException {
- generator.writeString(text, offset, len);
- }
-
- @Override
- public void writeUTF8String(byte[] text, int offset, int length) throws IOException {
- generator.writeUTF8String(text, offset, length);
- }
-
- @Override
- public void writeBinary(byte[] data, int offset, int len) throws IOException {
- generator.writeBinary(data, offset, len);
- }
-
- @Override
- public void writeBinary(byte[] data) throws IOException {
- generator.writeBinary(data);
- }
-
- @Override
- public void writeNumber(int v) throws IOException {
- generator.writeNumber(v);
- }
-
- @Override
- public void writeNumber(long v) throws IOException {
- generator.writeNumber(v);
- }
-
- @Override
- public void writeNumber(double d) throws IOException {
- generator.writeNumber(d);
- }
-
- @Override
- public void writeNumber(float f) throws IOException {
- generator.writeNumber(f);
- }
-
- @Override
- public void writeBoolean(boolean state) throws IOException {
- generator.writeBoolean(state);
- }
-
@Override
public void writeNull() throws IOException {
generator.writeNull();
}
@Override
- public void writeStringField(String fieldName, String value) throws IOException {
- generator.writeStringField(fieldName, value);
+ public void writeNullField(String name) throws IOException {
+ generator.writeNullField(name);
}
@Override
- public void writeBooleanField(String fieldName, boolean value) throws IOException {
- generator.writeBooleanField(fieldName, value);
+ public void writeBooleanField(String name, boolean value) throws IOException {
+ generator.writeBooleanField(name, value);
}
@Override
- public void writeNullField(String fieldName) throws IOException {
- generator.writeNullField(fieldName);
+ public void writeBoolean(boolean value) throws IOException {
+ generator.writeBoolean(value);
}
@Override
- public void writeNumberField(String fieldName, int value) throws IOException {
- generator.writeNumberField(fieldName, value);
+ public void writeNumberField(String name, double value) throws IOException {
+ generator.writeNumberField(name, value);
}
@Override
- public void writeNumberField(String fieldName, long value) throws IOException {
- generator.writeNumberField(fieldName, value);
+ public void writeNumber(double value) throws IOException {
+ generator.writeNumber(value);
}
@Override
- public void writeNumberField(String fieldName, double value) throws IOException {
- generator.writeNumberField(fieldName, value);
+ public void writeNumberField(String name, float value) throws IOException {
+ generator.writeNumberField(name, value);
}
@Override
- public void writeNumberField(String fieldName, float value) throws IOException {
- generator.writeNumberField(fieldName, value);
+ public void writeNumber(float value) throws IOException {
+ generator.writeNumber(value);
}
@Override
- public void writeBinaryField(String fieldName, byte[] data) throws IOException {
- generator.writeBinaryField(fieldName, data);
+ public void writeNumberField(String name, int value) throws IOException {
+ generator.writeNumberField(name, value);
}
@Override
- public void writeArrayFieldStart(String fieldName) throws IOException {
- generator.writeArrayFieldStart(fieldName);
+ public void writeNumber(int value) throws IOException {
+ generator.writeNumber(value);
}
@Override
- public void writeObjectFieldStart(String fieldName) throws IOException {
- generator.writeObjectFieldStart(fieldName);
+ public void writeNumberField(String name, long value) throws IOException {
+ generator.writeNumberField(name, value);
}
- private void writeStartRaw(String fieldName) throws IOException {
- writeFieldName(fieldName);
+ @Override
+ public void writeNumber(long value) throws IOException {
+ generator.writeNumber(value);
+ }
+
+ @Override
+ public void writeNumber(short value) throws IOException {
+ generator.writeNumber(value);
+ }
+
+ @Override
+ public void writeStringField(String name, String value) throws IOException {
+ generator.writeStringField(name, value);
+ }
+
+ @Override
+ public void writeString(String value) throws IOException {
+ generator.writeString(value);
+ }
+
+ @Override
+ public void writeString(char[] value, int offset, int len) throws IOException {
+ generator.writeString(value, offset, len);
+ }
+
+ @Override
+ public void writeUTF8String(byte[] value, int offset, int length) throws IOException {
+ generator.writeUTF8String(value, offset, length);
+ }
+
+ @Override
+ public void writeBinaryField(String name, byte[] value) throws IOException {
+ generator.writeBinaryField(name, value);
+ }
+
+ @Override
+ public void writeBinary(byte[] value) throws IOException {
+ generator.writeBinary(value);
+ }
+
+ @Override
+ public void writeBinary(byte[] value, int offset, int len) throws IOException {
+ generator.writeBinary(value, offset, len);
+ }
+
+ private void writeStartRaw(String name) throws IOException {
+ writeFieldName(name);
generator.writeRaw(':');
}
@@ -309,7 +302,7 @@ public class JsonXContentGenerator implements XContentGenerator {
}
@Override
- public void writeRawField(String fieldName, InputStream content) throws IOException {
+ public void writeRawField(String name, InputStream content) throws IOException {
if (content.markSupported() == false) {
// needed for the XContentFactory.xContentType call
content = new BufferedInputStream(content);
@@ -321,11 +314,11 @@ public class JsonXContentGenerator implements XContentGenerator {
if (mayWriteRawData(contentType) == false) {
try (XContentParser parser = XContentFactory.xContent(contentType).createParser(content)) {
parser.nextToken();
- writeFieldName(fieldName);
+ writeFieldName(name);
copyCurrentStructure(parser);
}
} else {
- writeStartRaw(fieldName);
+ writeStartRaw(name);
flush();
Streams.copy(content, os);
writeEndRaw();
@@ -333,16 +326,16 @@ public class JsonXContentGenerator implements XContentGenerator {
}
@Override
- public final void writeRawField(String fieldName, BytesReference content) throws IOException {
+ public final void writeRawField(String name, BytesReference content) throws IOException {
XContentType contentType = XContentFactory.xContentType(content);
if (contentType == null) {
throw new IllegalArgumentException("Can't write raw bytes whose xcontent-type can't be guessed");
}
if (mayWriteRawData(contentType) == false) {
- writeFieldName(fieldName);
+ writeFieldName(name);
copyRawValue(content, contentType.xContent());
} else {
- writeStartRaw(fieldName);
+ writeStartRaw(name);
flush();
content.writeTo(os);
writeEndRaw();
@@ -416,7 +409,7 @@ public class JsonXContentGenerator implements XContentGenerator {
}
JsonStreamContext context = generator.getOutputContext();
if ((context != null) && (context.inRoot() == false)) {
- throw new IOException("unclosed object or array found");
+ throw new IOException("Unclosed object or array found");
}
if (writeLineFeedAtEnd) {
flush();
diff --git a/core/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java
index 4854eb57752..63d4d958b36 100644
--- a/core/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java
+++ b/core/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java
@@ -275,15 +275,15 @@ public class SourceFieldMapper extends MetadataFieldMapper {
}
if (includes != null) {
- builder.field("includes", includes);
+ builder.array("includes", includes);
} else if (includeDefaults) {
- builder.field("includes", Strings.EMPTY_ARRAY);
+ builder.array("includes", Strings.EMPTY_ARRAY);
}
if (excludes != null) {
- builder.field("excludes", excludes);
+ builder.array("excludes", excludes);
} else if (includeDefaults) {
- builder.field("excludes", Strings.EMPTY_ARRAY);
+ builder.array("excludes", Strings.EMPTY_ARRAY);
}
builder.endObject();
diff --git a/core/src/main/java/org/elasticsearch/index/query/IndicesQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/IndicesQueryBuilder.java
index 736387a0d24..734d4cda922 100644
--- a/core/src/main/java/org/elasticsearch/index/query/IndicesQueryBuilder.java
+++ b/core/src/main/java/org/elasticsearch/index/query/IndicesQueryBuilder.java
@@ -132,7 +132,7 @@ public class IndicesQueryBuilder extends AbstractQueryBuilder 0) {
- builder.dateValueField(Fields.STOP_TIME_IN_MILLIS, Fields.STOP_TIME, timer.stopTime);
+ builder.dateField(Fields.STOP_TIME_IN_MILLIS, Fields.STOP_TIME, timer.stopTime);
}
builder.timeValueField(Fields.TOTAL_TIME_IN_MILLIS, Fields.TOTAL_TIME, timer.time());
diff --git a/core/src/main/java/org/elasticsearch/monitor/jvm/JvmInfo.java b/core/src/main/java/org/elasticsearch/monitor/jvm/JvmInfo.java
index ca0bb4f3e80..36179fb06ea 100644
--- a/core/src/main/java/org/elasticsearch/monitor/jvm/JvmInfo.java
+++ b/core/src/main/java/org/elasticsearch/monitor/jvm/JvmInfo.java
@@ -431,7 +431,7 @@ public class JvmInfo implements Writeable, ToXContent {
builder.field(Fields.VM_NAME, vmName);
builder.field(Fields.VM_VERSION, vmVersion);
builder.field(Fields.VM_VENDOR, vmVendor);
- builder.dateValueField(Fields.START_TIME_IN_MILLIS, Fields.START_TIME, startTime);
+ builder.dateField(Fields.START_TIME_IN_MILLIS, Fields.START_TIME, startTime);
builder.startObject(Fields.MEM);
builder.byteSizeField(Fields.HEAP_INIT_IN_BYTES, Fields.HEAP_INIT, mem.heapInit);
@@ -441,8 +441,8 @@ public class JvmInfo implements Writeable, ToXContent {
builder.byteSizeField(Fields.DIRECT_MAX_IN_BYTES, Fields.DIRECT_MAX, mem.directMemoryMax);
builder.endObject();
- builder.field(Fields.GC_COLLECTORS, gcCollectors);
- builder.field(Fields.MEMORY_POOLS, memoryPools);
+ builder.array(Fields.GC_COLLECTORS, gcCollectors);
+ builder.array(Fields.MEMORY_POOLS, memoryPools);
builder.field(Fields.USING_COMPRESSED_OOPS, useCompressedOops);
diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregationBuilder.java b/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregationBuilder.java
index 8320774da0f..e4811902f89 100644
--- a/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregationBuilder.java
+++ b/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregationBuilder.java
@@ -180,7 +180,7 @@ public class PercentileRanksAggregationBuilder extends LeafOnly 1 || randomBoolean()) {
- b.field("indices", indices);
+ b.array("indices", indices);
} else {
b.field("index", indices[0]);
}
if (aliases.length > 1 || randomBoolean()) {
- b.field("aliases", aliases);
+ b.array("aliases", aliases);
} else {
b.field("alias", aliases[0]);
}
@@ -196,12 +196,12 @@ public class AliasActionsTests extends ESTestCase {
b.startObject(); {
b.startObject("remove"); {
if (indices.length > 1 || randomBoolean()) {
- b.field("indices", indices);
+ b.array("indices", indices);
} else {
b.field("index", indices[0]);
}
if (aliases.length > 1 || randomBoolean()) {
- b.field("aliases", aliases);
+ b.array("aliases", aliases);
} else {
b.field("alias", aliases[0]);
}
@@ -224,7 +224,7 @@ public class AliasActionsTests extends ESTestCase {
b.startObject(); {
b.startObject("remove_index"); {
if (indices.length > 1 || randomBoolean()) {
- b.field("indices", indices);
+ b.array("indices", indices);
} else {
b.field("index", indices[0]);
}
@@ -246,7 +246,7 @@ public class AliasActionsTests extends ESTestCase {
b.startObject(); {
b.startObject(randomFrom("add", "remove")); {
b.field("index", randomAsciiOfLength(5));
- b.field("indices", generateRandomStringArray(10, 5, false, false));
+ b.array("indices", generateRandomStringArray(10, 5, false, false));
b.field("alias", randomAsciiOfLength(5));
}
b.endObject();
@@ -265,7 +265,7 @@ public class AliasActionsTests extends ESTestCase {
b.startObject(randomFrom("add", "remove")); {
b.field("index", randomAsciiOfLength(5));
b.field("alias", randomAsciiOfLength(5));
- b.field("aliases", generateRandomStringArray(10, 5, false, false));
+ b.array("aliases", generateRandomStringArray(10, 5, false, false));
}
b.endObject();
}
diff --git a/core/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java b/core/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java
index a602e81b854..2223163c367 100644
--- a/core/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java
+++ b/core/src/test/java/org/elasticsearch/common/xcontent/BaseXContentTestCase.java
@@ -19,23 +19,657 @@
package org.elasticsearch.common.xcontent;
+import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
-
+import org.apache.lucene.util.BytesRef;
+import org.elasticsearch.cluster.metadata.IndexMetaData;
+import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.geo.GeoPoint;
+import org.elasticsearch.common.io.PathUtils;
+import org.elasticsearch.common.text.Text;
+import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import org.elasticsearch.test.ESTestCase;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.Instant;
+import org.joda.time.ReadableInstant;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.math.BigDecimal;
import java.math.BigInteger;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import static java.util.Collections.singletonMap;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.notNullValue;
public abstract class BaseXContentTestCase extends ESTestCase {
- public abstract XContentType xcontentType();
+ protected abstract XContentType xcontentType();
+
+ private XContentBuilder builder() throws IOException {
+ return XContentBuilder.builder(xcontentType().xContent());
+ }
+
+ public void testContentType() throws IOException {
+ assertThat(builder().contentType(), equalTo(xcontentType()));
+ }
+
+ public void testStartEndObject() throws IOException {
+ expectUnclosedException(() -> builder().startObject().bytes());
+ expectUnclosedException(() -> builder().startObject().close());
+ expectUnclosedException(() -> builder().startObject().string());
+
+ expectObjectException(() -> builder().endObject().bytes());
+ expectObjectException(() -> builder().endObject().close());
+ expectObjectException(() -> builder().endObject().string());
+
+ expectValueException(() -> builder().startObject("foo").endObject());
+ expectNonNullFieldException(() -> builder().startObject().startObject(null));
+
+ assertResult("{}", () -> builder().startObject().endObject());
+ assertResult("{'foo':{}}", () -> builder().startObject().startObject("foo").endObject().endObject());
+
+ assertResult("{'foo':{'bar':{}}}", () -> builder()
+ .startObject()
+ .startObject("foo")
+ .startObject("bar")
+ .endObject()
+ .endObject()
+ .endObject());
+ }
+
+ public void testStartEndArray() throws IOException {
+ expectUnclosedException(() -> builder().startArray().bytes());
+ expectUnclosedException(() -> builder().startArray().close());
+ expectUnclosedException(() -> builder().startArray().string());
+
+ expectArrayException(() -> builder().endArray().bytes());
+ expectArrayException(() -> builder().endArray().close());
+ expectArrayException(() -> builder().endArray().string());
+
+ expectValueException(() -> builder().startArray("foo").endObject());
+ expectFieldException(() -> builder().startObject().startArray().endArray().endObject());
+ expectNonNullFieldException(() -> builder().startObject().startArray(null).endArray().endObject());
+
+ assertResult("{'foo':[]}", () -> builder().startObject().startArray("foo").endArray().endObject());
+ assertResult("{'foo':[1,2,3]}", () -> builder()
+ .startObject()
+ .startArray("foo")
+ .value(1)
+ .value(2)
+ .value(3)
+ .endArray()
+ .endObject());
+ }
+
+ public void testField() throws IOException {
+ expectValueException(() -> builder().field("foo").bytes());
+ expectNonNullFieldException(() -> builder().field(null).bytes());
+ expectUnclosedException(() -> builder().startObject().field("foo").bytes());
+
+ assertResult("{'foo':'bar'}", () -> builder().startObject().field("foo").value("bar").endObject());
+ }
+
+ public void testNullField() throws IOException {
+ expectValueException(() -> builder().nullField("foo").bytes());
+ expectNonNullFieldException(() -> builder().nullField(null).bytes());
+ expectUnclosedException(() -> builder().startObject().nullField("foo").bytes());
+
+ assertResult("{'foo':null}", () -> builder().startObject().nullField("foo").endObject());
+ }
+
+ public void testNullValue() throws IOException {
+ assertResult("{'foo':null}", () -> builder().startObject().field("foo").nullValue().endObject());
+ }
+
+ public void testBooleans() throws IOException {
+ assertResult("{'boolean':null}", () -> builder().startObject().field("boolean", (Boolean) null).endObject());
+ assertResult("{'boolean':true}", () -> builder().startObject().field("boolean", Boolean.TRUE).endObject());
+ assertResult("{'boolean':false}", () -> builder().startObject().field("boolean", Boolean.FALSE).endObject());
+ assertResult("{'boolean':[true,false,true]}", () -> builder().startObject().array("boolean", true, false, true).endObject());
+ assertResult("{'boolean':[false,true]}", () -> builder().startObject().array("boolean", new boolean[]{false, true}).endObject());
+ assertResult("{'boolean':null}", () -> builder().startObject().array("boolean", (boolean[]) null).endObject());
+ assertResult("{'boolean':[]}", () -> builder().startObject().array("boolean", new boolean[]{}).endObject());
+ assertResult("{'boolean':null}", () -> builder().startObject().field("boolean").value((Boolean) null).endObject());
+ assertResult("{'boolean':true}", () -> builder().startObject().field("boolean").value(Boolean.TRUE).endObject());
+ assertResult("{'boolean':false}", () -> builder().startObject().field("boolean").value(Boolean.FALSE).endObject());
+ }
+
+ public void testBytes() throws IOException {
+ assertResult("{'byte':null}", () -> builder().startObject().field("byte", (Byte) null).endObject());
+ assertResult("{'byte':0}", () -> builder().startObject().field("byte", (byte) 0).endObject());
+ assertResult("{'byte':1}", () -> builder().startObject().field("byte", (byte) 1).endObject());
+ assertResult("{'byte':null}", () -> builder().startObject().field("byte").value((Byte) null).endObject());
+ assertResult("{'byte':0}", () -> builder().startObject().field("byte").value((byte) 0).endObject());
+ assertResult("{'byte':1}", () -> builder().startObject().field("byte").value((byte) 1).endObject());
+ }
+
+ public void testDoubles() throws IOException {
+ assertResult("{'double':null}", () -> builder().startObject().field("double", (Double) null).endObject());
+ assertResult("{'double':42.5}", () -> builder().startObject().field("double", Double.valueOf(42.5)).endObject());
+ assertResult("{'double':1.2}", () -> builder().startObject().field("double", 1.2).endObject());
+ assertResult("{'double':[42.0,43.0,45]}", () -> builder().startObject().array("double", 42.0, 43.0, 45).endObject());
+ assertResult("{'double':null}", () -> builder().startObject().array("double", (double[]) null).endObject());
+ assertResult("{'double':[]}", () -> builder().startObject().array("double", new double[]{}).endObject());
+ assertResult("{'double':null}", () -> builder().startObject().field("double").value((Double) null).endObject());
+ assertResult("{'double':0.001}", () -> builder().startObject().field("double").value(0.001).endObject());
+ assertResult("{'double':[1.7976931348623157E308,4.9E-324]}", () -> builder()
+ .startObject()
+ .array("double", new double[]{Double.MAX_VALUE, Double.MIN_VALUE})
+ .endObject());
+ }
+
+ public void testFloats() throws IOException {
+ assertResult("{'float':null}", () -> builder().startObject().field("float", (Float) null).endObject());
+ assertResult("{'float':42.5}", () -> builder().startObject().field("float", Float.valueOf(42.5f)).endObject());
+ assertResult("{'float':1.2}", () -> builder().startObject().field("float", 1.2f).endObject());
+ assertResult("{'float':null}", () -> builder().startObject().array("float", (float[]) null).endObject());
+ assertResult("{'float':[]}", () -> builder().startObject().array("float", new float[]{}).endObject());
+ assertResult("{'float':null}", () -> builder().startObject().field("float").value((Float) null).endObject());
+ assertResult("{'float':9.9E-7}", () -> builder().startObject().field("float").value(0.00000099f).endObject());
+ assertResult("{'float':[42.0,43.0,45.666668]}", () -> builder()
+ .startObject()
+ .array("float", 42.0f, 43.0f, 45.66666667f)
+ .endObject());
+ assertResult("{'float':[3.4028235E38,1.4E-45]}", () -> builder()
+ .startObject()
+ .array("float", new float[]{Float.MAX_VALUE, Float.MIN_VALUE})
+ .endObject());
+ }
+
+ public void testIntegers() throws IOException {
+ assertResult("{'integer':null}", () -> builder().startObject().field("integer", (Integer) null).endObject());
+ assertResult("{'integer':42}", () -> builder().startObject().field("integer", Integer.valueOf(42)).endObject());
+ assertResult("{'integer':3}", () -> builder().startObject().field("integer", 3).endObject());
+ assertResult("{'integer':[1,3,5,7,11]}", () -> builder().startObject().array("integer", 1, 3, 5, 7, 11).endObject());
+ assertResult("{'integer':null}", () -> builder().startObject().array("integer", (int[]) null).endObject());
+ assertResult("{'integer':[]}", () -> builder().startObject().array("integer", new int[]{}).endObject());
+ assertResult("{'integer':null}", () -> builder().startObject().field("integer").value((Integer) null).endObject());
+ assertResult("{'integer':42}", () -> builder().startObject().field("integer").value(42).endObject());
+ assertResult("{'integer':[2147483647,-2147483648]}", () -> builder()
+ .startObject()
+ .array("integer", new int[]{Integer.MAX_VALUE, Integer.MIN_VALUE})
+ .endObject());
+ }
+
+ public void testLongs() throws IOException {
+ assertResult("{'long':null}", () -> builder().startObject().field("long", (Long) null).endObject());
+ assertResult("{'long':42}", () -> builder().startObject().field("long", Long.valueOf(42L)).endObject());
+ assertResult("{'long':9223372036854775807}", () -> builder().startObject().field("long", 9_223_372_036_854_775_807L).endObject());
+ assertResult("{'long':[1,3,5,7,11]}", () -> builder().startObject().array("long", 1L, 3L, 5L, 7L, 11L).endObject());
+ assertResult("{'long':null}", () -> builder().startObject().array("long", (long[]) null).endObject());
+ assertResult("{'long':[]}", () -> builder().startObject().array("long", new long[]{}).endObject());
+ assertResult("{'long':null}", () -> builder().startObject().field("long").value((Long) null).endObject());
+ assertResult("{'long':42}", () -> builder().startObject().field("long").value(42).endObject());
+ assertResult("{'long':[2147483647,-2147483648]}", () -> builder()
+ .startObject()
+ .array("long", new long[]{Integer.MAX_VALUE, Integer.MIN_VALUE})
+ .endObject());
+ }
+
+ public void testShorts() throws IOException {
+ assertResult("{'short':null}", () -> builder().startObject().field("short", (Short) null).endObject());
+ assertResult("{'short':5000}", () -> builder().startObject().field("short", Short.valueOf((short) 5000)).endObject());
+ assertResult("{'short':null}", () -> builder().startObject().array("short", (short[]) null).endObject());
+ assertResult("{'short':[]}", () -> builder().startObject().array("short", new short[]{}).endObject());
+ assertResult("{'short':null}", () -> builder().startObject().field("short").value((Short) null).endObject());
+ assertResult("{'short':42}", () -> builder().startObject().field("short").value((short) 42).endObject());
+ assertResult("{'short':[1,3,5,7,11]}", () -> builder()
+ .startObject()
+ .array("short", (short) 1, (short) 3, (short) 5, (short) 7, (short) 11)
+ .endObject());
+ assertResult("{'short':[32767,-32768]}", () -> builder()
+ .startObject()
+ .array("short", new short[]{Short.MAX_VALUE, Short.MIN_VALUE})
+ .endObject());
+ }
+
+ public void testStrings() throws IOException {
+ assertResult("{'string':null}", () -> builder().startObject().field("string", (String) null).endObject());
+ assertResult("{'string':'value'}", () -> builder().startObject().field("string", "value").endObject());
+ assertResult("{'string':''}", () -> builder().startObject().field("string", "").endObject());
+ assertResult("{'string':null}", () -> builder().startObject().array("string", (String[]) null).endObject());
+ assertResult("{'string':[]}", () -> builder().startObject().array("string", Strings.EMPTY_ARRAY).endObject());
+ assertResult("{'string':null}", () -> builder().startObject().field("string").value((String) null).endObject());
+ assertResult("{'string':'42'}", () -> builder().startObject().field("string").value("42").endObject());
+ assertResult("{'string':['a','b','c','d']}", () -> builder()
+ .startObject()
+ .array("string", "a", "b", "c", "d")
+ .endObject());
+ }
+
+ public void testBinaryField() throws Exception {
+ assertResult("{'binary':null}", () -> builder().startObject().field("binary", (byte[]) null).endObject());
+
+ final byte[] randomBytes = randomBytes();
+ BytesReference bytes = builder().startObject().field("binary", randomBytes).endObject().bytes();
+
+ XContentParser parser = xcontentType().xContent().createParser(bytes);
+ assertSame(parser.nextToken(), Token.START_OBJECT);
+ assertSame(parser.nextToken(), Token.FIELD_NAME);
+ assertEquals(parser.currentName(), "binary");
+ assertTrue(parser.nextToken().isValue());
+ assertArrayEquals(randomBytes, parser.binaryValue());
+ assertSame(parser.nextToken(), Token.END_OBJECT);
+ assertNull(parser.nextToken());
+ }
+
+ public void testBinaryValue() throws Exception {
+ assertResult("{'binary':null}", () -> builder().startObject().field("binary").value((byte[]) null).endObject());
+
+ final byte[] randomBytes = randomBytes();
+ BytesReference bytes = builder().startObject().field("binary").value(randomBytes).endObject().bytes();
+
+ XContentParser parser = xcontentType().xContent().createParser(bytes);
+ assertSame(parser.nextToken(), Token.START_OBJECT);
+ assertSame(parser.nextToken(), Token.FIELD_NAME);
+ assertEquals(parser.currentName(), "binary");
+ assertTrue(parser.nextToken().isValue());
+ assertArrayEquals(randomBytes, parser.binaryValue());
+ assertSame(parser.nextToken(), Token.END_OBJECT);
+ assertNull(parser.nextToken());
+ }
+
+ public void testBinaryValueWithOffsetLength() throws Exception {
+ assertResult("{'binary':null}", () -> builder().startObject().field("binary").value(null, 0, 0).endObject());
+
+ final byte[] randomBytes = randomBytes();
+ final int offset = randomIntBetween(0, randomBytes.length);
+ final int length = randomIntBetween(1, Math.max(1, randomBytes.length - offset));
+
+ XContentBuilder builder = builder().startObject();
+ if (randomBoolean()) {
+ builder.field("bin", randomBytes, offset, length);
+ } else {
+ builder.field("bin").value(randomBytes, offset, length);
+ }
+ builder.endObject();
+
+ XContentParser parser = xcontentType().xContent().createParser(builder.bytes());
+ assertSame(parser.nextToken(), Token.START_OBJECT);
+ assertSame(parser.nextToken(), Token.FIELD_NAME);
+ assertEquals(parser.currentName(), "bin");
+ assertTrue(parser.nextToken().isValue());
+ assertArrayEquals(Arrays.copyOfRange(randomBytes, offset, offset + length), parser.binaryValue());
+ assertSame(parser.nextToken(), Token.END_OBJECT);
+ assertNull(parser.nextToken());
+ }
+
+ public void testBinaryUTF8() throws Exception {
+ assertResult("{'utf8':null}", () -> builder().startObject().utf8Field("utf8", null).endObject());
+
+ final BytesRef randomBytesRef = new BytesRef(randomBytes());
+ XContentBuilder builder = builder().startObject();
+ if (randomBoolean()) {
+ builder.utf8Field("utf8", randomBytesRef);
+ } else {
+ builder.field("utf8").utf8Value(randomBytesRef);
+ }
+ builder.endObject();
+
+ XContentParser parser = xcontentType().xContent().createParser(builder.bytes());
+ assertSame(parser.nextToken(), Token.START_OBJECT);
+ assertSame(parser.nextToken(), Token.FIELD_NAME);
+ assertEquals(parser.currentName(), "utf8");
+ assertTrue(parser.nextToken().isValue());
+ assertThat(parser.utf8Bytes().utf8ToString(), equalTo(randomBytesRef.utf8ToString()));
+ assertSame(parser.nextToken(), Token.END_OBJECT);
+ assertNull(parser.nextToken());
+ }
+
+ public void testText() throws Exception {
+ assertResult("{'text':null}", () -> builder().startObject().field("text", (Text) null).endObject());
+ assertResult("{'text':''}", () -> builder().startObject().field("text", new Text("")).endObject());
+ assertResult("{'text':'foo bar'}", () -> builder().startObject().field("text", new Text("foo bar")).endObject());
+
+ final BytesReference random = new BytesArray(randomBytes());
+ XContentBuilder builder = builder().startObject().field("text", new Text(random)).endObject();
+
+ XContentParser parser = xcontentType().xContent().createParser(builder.bytes());
+ assertSame(parser.nextToken(), Token.START_OBJECT);
+ assertSame(parser.nextToken(), Token.FIELD_NAME);
+ assertEquals(parser.currentName(), "text");
+ assertTrue(parser.nextToken().isValue());
+ assertThat(parser.utf8Bytes().utf8ToString(), equalTo(random.utf8ToString()));
+ assertSame(parser.nextToken(), Token.END_OBJECT);
+ assertNull(parser.nextToken());
+ }
+
+ public void testReadableInstant() throws Exception {
+ assertResult("{'instant':null}", () -> builder().startObject().field("instant", (ReadableInstant) null).endObject());
+ assertResult("{'instant':null}", () -> builder().startObject().field("instant").value((ReadableInstant) null).endObject());
+
+ final DateTime t1 = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC);
+
+ String expected = "{'t1':'2016-01-01T00:00:00.000Z'}";
+ assertResult(expected, () -> builder().startObject().field("t1", t1).endObject());
+ assertResult(expected, () -> builder().startObject().field("t1").value(t1).endObject());
+
+ final DateTime t2 = new DateTime(2016, 12, 25, 7, 59, 42, 213, DateTimeZone.UTC);
+
+ expected = "{'t2':'2016-12-25T07:59:42.213Z'}";
+ assertResult(expected, () -> builder().startObject().field("t2", t2).endObject());
+ assertResult(expected, () -> builder().startObject().field("t2").value(t2).endObject());
+
+ final DateTimeFormatter formatter = randomFrom(ISODateTimeFormat.basicDate(), ISODateTimeFormat.dateTimeNoMillis());
+ final DateTime t3 = DateTime.now();
+
+ expected = "{'t3':'" + formatter.print(t3) + "'}";
+ assertResult(expected, () -> builder().startObject().field("t3", t3, formatter).endObject());
+ assertResult(expected, () -> builder().startObject().field("t3").value(t3, formatter).endObject());
+
+ final DateTime t4 = new DateTime(randomDateTimeZone());
+
+ expected = "{'t4':'" + formatter.print(t4) + "'}";
+ assertResult(expected, () -> builder().startObject().field("t4", t4, formatter).endObject());
+ assertResult(expected, () -> builder().startObject().field("t4").value(t4, formatter).endObject());
+
+ long date = Math.abs(randomLong() % (2 * (long) 10e11)); // 1970-01-01T00:00:00Z - 2033-05-18T05:33:20.000+02:00
+ final DateTime t5 = new DateTime(date, randomDateTimeZone());
+
+ expected = "{'t5':'" + XContentBuilder.DEFAULT_DATE_PRINTER.print(t5) + "'}";
+ assertResult(expected, () -> builder().startObject().field("t5", t5).endObject());
+ assertResult(expected, () -> builder().startObject().field("t5").value(t5).endObject());
+
+ expected = "{'t5':'" + formatter.print(t5) + "'}";
+ assertResult(expected, () -> builder().startObject().field("t5", t5, formatter).endObject());
+ assertResult(expected, () -> builder().startObject().field("t5").value(t5, formatter).endObject());
+
+ Instant i1 = new Instant(1451606400000L); // 2016-01-01T00:00:00.000Z
+ expected = "{'i1':'2016-01-01T00:00:00.000Z'}";
+ assertResult(expected, () -> builder().startObject().field("i1", i1).endObject());
+ assertResult(expected, () -> builder().startObject().field("i1").value(i1).endObject());
+
+ Instant i2 = new Instant(1482652782213L); // 2016-12-25T07:59:42.213Z
+ expected = "{'i2':'" + formatter.print(i2) + "'}";
+ assertResult(expected, () -> builder().startObject().field("i2", i2, formatter).endObject());
+ assertResult(expected, () -> builder().startObject().field("i2").value(i2, formatter).endObject());
+
+ expectNonNullFormatterException(() -> builder().startObject().field("t3", t3, null).endObject());
+ expectNonNullFormatterException(() -> builder().startObject().field("t3").value(t3, null).endObject());
+ }
+
+ public void testDate() throws Exception {
+ assertResult("{'date':null}", () -> builder().startObject().field("date", (Date) null).endObject());
+ assertResult("{'date':null}", () -> builder().startObject().field("date").value((Date) null).endObject());
+
+ final Date d1 = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC).toDate();
+ assertResult("{'d1':'2016-01-01T00:00:00.000Z'}", () -> builder().startObject().field("d1", d1).endObject());
+ assertResult("{'d1':'2016-01-01T00:00:00.000Z'}", () -> builder().startObject().field("d1").value(d1).endObject());
+
+ final Date d2 = new DateTime(2016, 12, 25, 7, 59, 42, 213, DateTimeZone.UTC).toDate();
+ assertResult("{'d2':'2016-12-25T07:59:42.213Z'}", () -> builder().startObject().field("d2", d2).endObject());
+ assertResult("{'d2':'2016-12-25T07:59:42.213Z'}", () -> builder().startObject().field("d2").value(d2).endObject());
+
+ final DateTimeFormatter formatter = randomFrom(ISODateTimeFormat.basicDate(), ISODateTimeFormat.dateTimeNoMillis());
+ final Date d3 = DateTime.now().toDate();
+
+ String expected = "{'d3':'" + formatter.print(d3.getTime()) + "'}";
+ assertResult(expected, () -> builder().startObject().field("d3", d3, formatter).endObject());
+ assertResult(expected, () -> builder().startObject().field("d3").value(d3, formatter).endObject());
+
+ expectNonNullFormatterException(() -> builder().startObject().field("d3", d3, null).endObject());
+ expectNonNullFormatterException(() -> builder().startObject().field("d3").value(d3, null).endObject());
+ expectNonNullFormatterException(() -> builder().value(null, 1L));
+ }
+
+ public void testDateField() throws Exception {
+ final Date d = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC).toDate();
+
+ assertResult("{'date_in_millis':1451606400000}", () -> builder()
+ .startObject()
+ .dateField("date_in_millis", "date", d.getTime())
+ .endObject());
+ assertResult("{'date':'2016-01-01T00:00:00.000Z','date_in_millis':1451606400000}", () -> builder()
+ .humanReadable(true)
+ .startObject
+ ().dateField("date_in_millis", "date", d.getTime())
+ .endObject());
+ }
+
+ public void testCalendar() throws Exception {
+ Calendar calendar = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC).toCalendar(Locale.ROOT);
+ assertResult("{'calendar':'2016-01-01T00:00:00.000Z'}", () -> builder()
+ .startObject()
+ .field("calendar")
+ .value(calendar)
+ .endObject());
+ }
+
+ public void testGeoPoint() throws Exception {
+ assertResult("{'geo':null}", () -> builder().startObject().field("geo", (GeoPoint) null).endObject());
+ assertResult("{'geo':{'lat':52.4267578125,'lon':13.271484375}}", () -> builder()
+ .startObject()
+ . field("geo", GeoPoint.fromGeohash("u336q"))
+ .endObject());
+ assertResult("{'geo':{'lat':52.5201416015625,'lon':13.4033203125}}", () -> builder()
+ .startObject()
+ .field("geo")
+ .value(GeoPoint.fromGeohash("u33dc1"))
+ .endObject());
+ }
+
+ public void testLatLon() throws Exception {
+ final String expected = "{'latlon':{'lat':13.271484375,'lon':52.4267578125}}";
+ assertResult(expected, () -> builder().startObject().latlon("latlon", 13.271484375, 52.4267578125).endObject());
+ assertResult(expected, () -> builder().startObject().field("latlon").latlon(13.271484375, 52.4267578125).endObject());
+ }
+
+ public void testPath() throws Exception {
+ assertResult("{'path':null}", () -> builder().startObject().field("path", (Path) null).endObject());
+
+ Path path = PathUtils.get("first", "second", "third");
+ assertResult("{'path':'first/second/third'}", () -> builder().startObject().field("path", path).endObject());
+ }
+
+ public void testObjects() throws Exception {
+ Map objects = new HashMap<>();
+ objects.put("{'objects':[false,true,false]}", new Object[]{false, true, false});
+ objects.put("{'objects':[1,1,2,3,5,8,13]}", new Object[]{(byte) 1, (byte) 1, (byte) 2, (byte) 3, (byte) 5, (byte) 8, (byte) 13});
+ objects.put("{'objects':[1.0,1.0,2.0,3.0,5.0,8.0,13.0]}", new Object[]{1.0d, 1.0d, 2.0d, 3.0d, 5.0d, 8.0d, 13.0d});
+ objects.put("{'objects':[1.0,1.0,2.0,3.0,5.0,8.0,13.0]}", new Object[]{1.0f, 1.0f, 2.0f, 3.0f, 5.0f, 8.0f, 13.0f});
+ objects.put("{'objects':[{'lat':45.759429931640625,'lon':4.8394775390625}]}", new Object[]{GeoPoint.fromGeohash("u05kq4k")});
+ objects.put("{'objects':[1,1,2,3,5,8,13]}", new Object[]{1, 1, 2, 3, 5, 8, 13});
+ objects.put("{'objects':[1,1,2,3,5,8,13]}", new Object[]{1L, 1L, 2L, 3L, 5L, 8L, 13L});
+ objects.put("{'objects':[1,1,2,3,5,8]}", new Object[]{(short) 1, (short) 1, (short) 2, (short) 3, (short) 5, (short) 8});
+ objects.put("{'objects':['a','b','c']}", new Object[]{"a", "b", "c"});
+ objects.put("{'objects':['a','b','c']}", new Object[]{new Text("a"), new Text(new BytesArray("b")), new Text("c")});
+ objects.put("{'objects':['a/b/c','d/e']}", new Object[]{PathUtils.get("a", "b", "c"), PathUtils.get("d", "e")});
+ objects.put("{'objects':null}", null);
+ objects.put("{'objects':[null,null,null]}", new Object[]{null, null, null});
+ objects.put("{'objects':['OPEN','CLOSE']}", IndexMetaData.State.values());
+ objects.put("{'objects':[{'f1':'v1'},{'f2':'v2'}]}", new Object[]{singletonMap("f1", "v1"), singletonMap("f2", "v2")});
+ objects.put("{'objects':[[1,2,3],[4,5]]}", new Object[]{Arrays.asList(1, 2, 3), Arrays.asList(4, 5)});
+
+ final DateTimeFormatter formatter = XContentBuilder.DEFAULT_DATE_PRINTER;
+ final Date d1 = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC).toDate();
+ final Date d2 = new DateTime(2015, 1, 1, 0, 0, DateTimeZone.UTC).toDate();
+ objects.put("{'objects':['" + formatter.print(d1.getTime()) + "','" + formatter.print(d2.getTime()) + "']}", new Object[]{d1, d2});
+
+ final DateTime dt1 = DateTime.now();
+ final DateTime dt2 = new DateTime(2016, 12, 25, 7, 59, 42, 213, DateTimeZone.UTC);
+ objects.put("{'objects':['" + formatter.print(dt1) + "','2016-12-25T07:59:42.213Z']}", new Object[]{dt1, dt2});
+
+ final Calendar c1 = new DateTime(2012, 7, 7, 10, 23, DateTimeZone.UTC).toCalendar(Locale.ROOT);
+ final Calendar c2 = new DateTime(2014, 11, 16, 19, 36, DateTimeZone.UTC).toCalendar(Locale.ROOT);
+ objects.put("{'objects':['2012-07-07T10:23:00.000Z','2014-11-16T19:36:00.000Z']}", new Object[]{c1, c2});
+
+ final ToXContent x1 = (builder, params) -> builder.startObject().field("f1", "v1").field("f2", 2).array("f3", 3, 4, 5).endObject();
+ final ToXContent x2 = (builder, params) -> builder.startObject().field("f1", "v1").field("f2", x1).endObject();
+ objects.put("{'objects':[{'f1':'v1','f2':2,'f3':[3,4,5]},{'f1':'v1','f2':{'f1':'v1','f2':2,'f3':[3,4,5]}}]}", new Object[]{x1, x2});
+
+ for (Map.Entry o : objects.entrySet()) {
+ final String expected = o.getKey();
+ assertResult(expected, () -> builder().startObject().field("objects", o.getValue()).endObject());
+ assertResult(expected, () -> builder().startObject().field("objects").value(o.getValue()).endObject());
+ assertResult(expected, () -> builder().startObject().field("objects").values(o.getValue()).endObject());
+ assertResult(expected, () -> builder().startObject().array("objects", o.getValue()).endObject());
+ }
+ }
+
+ public void testObject() throws Exception {
+ Map object = new HashMap<>();
+ object.put("{'object':false}", Boolean.FALSE);
+ object.put("{'object':13}", (byte) 13);
+ object.put("{'object':5.0}", 5.0d);
+ object.put("{'object':8.0}", 8.0f);
+ object.put("{'object':{'lat':45.759429931640625,'lon':4.8394775390625}}", GeoPoint.fromGeohash("u05kq4k"));
+ object.put("{'object':3}", 3);
+ object.put("{'object':2}", 2L);
+ object.put("{'object':1}", (short) 1);
+ object.put("{'object':'string'}", "string");
+ object.put("{'object':'a'}", new Text("a"));
+ object.put("{'object':'b'}", new Text(new BytesArray("b")));
+ object.put("{'object':'a/b/c'}", PathUtils.get("a", "b", "c"));
+ object.put("{'object':null}", null);
+ object.put("{'object':'OPEN'}", IndexMetaData.State.OPEN);
+ object.put("{'object':'NM'}", DistanceUnit.NAUTICALMILES);
+ object.put("{'object':{'f1':'v1'}}", singletonMap("f1", "v1"));
+ object.put("{'object':{'f1':{'f2':'v2'}}}", singletonMap("f1", singletonMap("f2", "v2")));
+ object.put("{'object':[1,2,3]}", Arrays.asList(1, 2, 3));
+
+ final DateTimeFormatter formatter = XContentBuilder.DEFAULT_DATE_PRINTER;
+ final Date d1 = new DateTime(2016, 1, 1, 0, 0, DateTimeZone.UTC).toDate();
+ object.put("{'object':'" + formatter.print(d1.getTime()) + "'}", d1);
+
+ final DateTime d2 = DateTime.now();
+ object.put("{'object':'" + formatter.print(d2) + "'}", d2);
+
+ final Calendar c1 = new DateTime(2010, 1, 1, 0, 0, DateTimeZone.UTC).toCalendar(Locale.ROOT);
+ object.put("{'object':'2010-01-01T00:00:00.000Z'}", c1);
+
+ final ToXContent x1 = (builder, params) -> builder.startObject().field("f1", "v1").field("f2", 2).array("f3", 3, 4, 5).endObject();
+ final ToXContent x2 = (builder, params) -> builder.startObject().field("f1", "v1").field("f2", x1).endObject();
+ object.put("{'object':{'f1':'v1','f2':{'f1':'v1','f2':2,'f3':[3,4,5]}}}", x2);
+
+ for (Map.Entry o : object.entrySet()) {
+ final String expected = o.getKey();
+ assertResult(expected, () -> builder().humanReadable(true).startObject().field("object", o.getValue()).endObject());
+ assertResult(expected, () -> builder().humanReadable(true).startObject().field("object").value(o.getValue()).endObject());
+ }
+
+ assertResult("{'objects':[null,null,null]}", () -> builder().startObject().array("objects", null, null, null).endObject());
+ }
+
+ public void testToXContent() throws Exception {
+ assertResult("{'xcontent':null}", () -> builder().startObject().field("xcontent", (ToXContent) null).endObject());
+ assertResult("{'xcontent':null}", () -> builder().startObject().field("xcontent").value((ToXContent) null).endObject());
+
+ ToXContent xcontent0 = (builder, params) -> {
+ builder.startObject();
+ builder.field("field", "value");
+ builder.array("array", "1", "2", "3");
+ builder.startObject("foo");
+ builder.field("bar", "baz");
+ builder.endObject();
+ builder.endObject();
+ return builder;
+ };
+
+ assertResult("{'field':'value','array':['1','2','3'],'foo':{'bar':'baz'}}", () -> builder().value(xcontent0));
+ assertResult("{'xcontent':{'field':'value','array':['1','2','3'],'foo':{'bar':'baz'}}}", () -> builder()
+ .startObject()
+ .field("xcontent", xcontent0)
+ .endObject());
+
+ ToXContent xcontent1 = (builder, params) -> {
+ builder.startObject();
+ builder.field("field", "value");
+ builder.startObject("foo");
+ builder.field("bar", "baz");
+ builder.endObject();
+ builder.endObject();
+ return builder;
+ };
+
+ ToXContent xcontent2 = (builder, params) -> {
+ builder.startObject();
+ builder.field("root", xcontent0);
+ builder.array("childs", xcontent0, xcontent1);
+ builder.endObject();
+ return builder;
+ };
+ assertResult("{'root':{" +
+ "'field':'value'," +
+ "'array':['1','2','3']," +
+ "'foo':{'bar':'baz'}" +
+ "}," +
+ "'childs':[" +
+ "{'field':'value','array':['1','2','3'],'foo':{'bar':'baz'}}," +
+ "{'field':'value','foo':{'bar':'baz'}}" +
+ "]}", () -> builder().value(xcontent2));
+ }
+
+ public void testMap() throws Exception {
+ Map> maps = new HashMap<>();
+ maps.put("{'map':null}", (Map) null);
+ maps.put("{'map':{}}", Collections.emptyMap());
+ maps.put("{'map':{'key':'value'}}", singletonMap("key", "value"));
+
+ Map innerMap = new HashMap<>();
+ innerMap.put("string", "value");
+ innerMap.put("int", 42);
+ innerMap.put("long", 42L);
+ innerMap.put("long[]", new long[]{1L, 3L});
+ innerMap.put("path", PathUtils.get("path", "to", "file"));
+ innerMap.put("object", singletonMap("key", "value"));
+ maps.put("{'map':{'path':'path/to/file','string':'value','long[]':[1,3],'int':42,'long':42,'object':{'key':'value'}}}", innerMap);
+
+ for (Map.Entry> m : maps.entrySet()) {
+ final String expected = m.getKey();
+ assertResult(expected, () -> builder().startObject().field("map", m.getValue()).endObject());
+ assertResult(expected, () -> builder().startObject().field("map").value(m.getValue()).endObject());
+ assertResult(expected, () -> builder().startObject().field("map").map(m.getValue()).endObject());
+ }
+ }
+
+ public void testIterable() throws Exception {
+ Map> iterables = new HashMap<>();
+ iterables.put("{'iter':null}", (Iterable) null);
+ iterables.put("{'iter':[]}", Collections.emptyList());
+ iterables.put("{'iter':['a','b']}", Arrays.asList("a", "b"));
+ iterables.put("{'iter':'path/to/file'}", PathUtils.get("path", "to", "file"));
+ iterables.put("{'iter':['a/b/c','c/d']}", Arrays.asList(PathUtils.get("a", "b", "c"), PathUtils.get("c", "d")));
+
+ for (Map.Entry> i : iterables.entrySet()) {
+ final String expected = i.getKey();
+ assertResult(expected, () -> builder().startObject().field("iter", i.getValue()).endObject());
+ assertResult(expected, () -> builder().startObject().field("iter").value(i.getValue()).endObject());
+ }
+ }
+
+ public void testUnknownObject() throws Exception {
+ Map objects = new HashMap<>();
+ objects.put("{'obj':50.63}", DistanceUnit.METERS.fromMeters(50.63));
+ objects.put("{'obj':'MINUTES'}", TimeUnit.MINUTES);
+ objects.put("{'obj':'class org.elasticsearch.common.xcontent.BaseXContentTestCase'}", BaseXContentTestCase.class);
+
+ for (Map.Entry o : objects.entrySet()) {
+ final String expected = o.getKey();
+ assertResult(expected, () -> builder().startObject().field("obj", o.getValue()).endObject());
+ assertResult(expected, () -> builder().startObject().field("obj").value(o.getValue()).endObject());
+ }
+ }
public void testBasics() throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
@@ -56,7 +690,7 @@ public abstract class BaseXContentTestCase extends ESTestCase {
generator.writeNumber(2L);
}
});
- assertEquals(e.getMessage(), "unclosed object or array found");
+ assertEquals(e.getMessage(), "Unclosed object or array found");
}
public void testMissingEndArray() throws IOException {
@@ -67,11 +701,11 @@ public abstract class BaseXContentTestCase extends ESTestCase {
generator.writeNumber(2L);
}
});
- assertEquals(e.getMessage(), "unclosed object or array found");
+ assertEquals(e.getMessage(), "Unclosed object or array found");
}
public void testRawField() throws Exception {
- for (boolean useStream : new boolean[] {false, true}) {
+ for (boolean useStream : new boolean[]{false, true}) {
for (XContentType xcontentType : XContentType.values()) {
doTestRawField(xcontentType.xContent(), useStream);
}
@@ -182,4 +816,76 @@ public abstract class BaseXContentTestCase extends ESTestCase {
assertEquals("bar", map.get("foo"));
assertEquals(bigInteger, map.get("bigint"));
}
+
+ public void testEnsureNameNotNull() {
+ IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> XContentBuilder.ensureNameNotNull(null));
+ assertThat(e.getMessage(), containsString("Field name cannot be null"));
+ }
+
+ public void testFormatterNameNotNull() {
+ IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> XContentBuilder.ensureFormatterNotNull(null));
+ assertThat(e.getMessage(), containsString("DateTimeFormatter cannot be null"));
+ }
+
+ public void testEnsureNotNull() {
+ IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> XContentBuilder.ensureNotNull(null, "message"));
+ assertThat(e.getMessage(), containsString("message"));
+
+ XContentBuilder.ensureNotNull("foo", "No exception must be thrown");
+ }
+
+ private static void expectUnclosedException(ThrowingRunnable runnable) {
+ IllegalStateException e = expectThrows(IllegalStateException.class, runnable);
+ assertThat(e.getMessage(), containsString("Failed to close the XContentBuilder"));
+ assertThat(e.getCause(), allOf(notNullValue(), instanceOf(IOException.class)));
+ assertThat(e.getCause().getMessage(), containsString("Unclosed object or array found"));
+ }
+
+ private static void expectValueException(ThrowingRunnable runnable) {
+ JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
+ assertThat(e.getMessage(), containsString("expecting a value"));
+ }
+
+ private static void expectFieldException(ThrowingRunnable runnable) {
+ JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
+ assertThat(e.getMessage(), containsString("expecting field name"));
+ }
+
+ private static void expectNonNullFieldException(ThrowingRunnable runnable) {
+ IllegalArgumentException e = expectThrows(IllegalArgumentException.class, runnable);
+ assertThat(e.getMessage(), containsString("Field name cannot be null"));
+ }
+
+ private static void expectNonNullFormatterException(ThrowingRunnable runnable) {
+ IllegalArgumentException e = expectThrows(IllegalArgumentException.class, runnable);
+ assertThat(e.getMessage(), containsString("DateTimeFormatter cannot be null"));
+ }
+
+ private static void expectObjectException(ThrowingRunnable runnable) {
+ JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
+ assertThat(e.getMessage(), containsString("Current context not Object"));
+ }
+
+ private static void expectArrayException(ThrowingRunnable runnable) {
+ JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
+ assertThat(e.getMessage(), containsString("Current context not Array"));
+ }
+
+ public static Matcher equalToJson(String json) {
+ return Matchers.equalTo(json.replace("'", "\""));
+ }
+
+ private static void assertResult(String expected, Builder builder) throws IOException {
+ // Build the XContentBuilder, convert its bytes to JSON and check it matches
+ assertThat(XContentHelper.convertToJson(builder.build().bytes(), randomBoolean()), equalToJson(expected));
+ }
+
+ private static byte[] randomBytes() throws Exception {
+ return randomUnicodeOfLength(scaledRandomIntBetween(10, 1000)).getBytes("UTF-8");
+ }
+
+ @FunctionalInterface
+ private interface Builder {
+ XContentBuilder build() throws IOException;
+ }
}
diff --git a/core/src/test/java/org/elasticsearch/common/xcontent/builder/XContentBuilderTests.java b/core/src/test/java/org/elasticsearch/common/xcontent/builder/XContentBuilderTests.java
index d0e095e8c65..f0b1b7f5e1b 100644
--- a/core/src/test/java/org/elasticsearch/common/xcontent/builder/XContentBuilderTests.java
+++ b/core/src/test/java/org/elasticsearch/common/xcontent/builder/XContentBuilderTests.java
@@ -173,9 +173,9 @@ public class XContentBuilderTests extends ESTestCase {
public void testDateTypesConversion() throws Exception {
Date date = new Date();
- String expectedDate = XContentBuilder.defaultDatePrinter.print(date.getTime());
+ String expectedDate = XContentBuilder.DEFAULT_DATE_PRINTER.print(date.getTime());
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.ROOT);
- String expectedCalendar = XContentBuilder.defaultDatePrinter.print(calendar.getTimeInMillis());
+ String expectedCalendar = XContentBuilder.DEFAULT_DATE_PRINTER.print(calendar.getTimeInMillis());
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON);
builder.startObject().field("date", date).endObject();
assertThat(builder.string(), equalTo("{\"date\":\"" + expectedDate + "\"}"));
@@ -339,17 +339,17 @@ public class XContentBuilderTests extends ESTestCase {
builder.map(Collections.singletonMap(null, "test"));
fail("write map should have failed");
} catch(IllegalArgumentException e) {
- assertThat(e.getMessage(), equalTo("field name cannot be null"));
+ assertThat(e.getMessage(), equalTo("Field name cannot be null"));
}
}
public void testWriteMapValueWithNullKeys() throws IOException {
XContentBuilder builder = XContentFactory.contentBuilder(randomFrom(XContentType.values()));
try {
- builder.value(Collections.singletonMap(null, "test"));
+ builder.map(Collections.singletonMap(null, "test"));
fail("write map should have failed");
} catch(IllegalArgumentException e) {
- assertThat(e.getMessage(), equalTo("field name cannot be null"));
+ assertThat(e.getMessage(), equalTo("Field name cannot be null"));
}
}
@@ -360,7 +360,7 @@ public class XContentBuilderTests extends ESTestCase {
builder.field("map", Collections.singletonMap(null, "test"));
fail("write map should have failed");
} catch(IllegalArgumentException e) {
- assertThat(e.getMessage(), equalTo("field name cannot be null"));
+ assertThat(e.getMessage(), equalTo("Field name cannot be null"));
}
}
@@ -371,8 +371,8 @@ public class XContentBuilderTests extends ESTestCase {
builder.field("foo", true);
}
});
- assertThat(e.getMessage(), equalTo("failed to close the XContentBuilder"));
- assertThat(e.getCause().getMessage(), equalTo("unclosed object or array found"));
+ assertThat(e.getMessage(), equalTo("Failed to close the XContentBuilder"));
+ assertThat(e.getCause().getMessage(), equalTo("Unclosed object or array found"));
}
public void testMissingEndArray() throws IOException {
@@ -384,7 +384,7 @@ public class XContentBuilderTests extends ESTestCase {
builder.value(1);
}
});
- assertThat(e.getMessage(), equalTo("failed to close the XContentBuilder"));
- assertThat(e.getCause().getMessage(), equalTo("unclosed object or array found"));
+ assertThat(e.getMessage(), equalTo("Failed to close the XContentBuilder"));
+ assertThat(e.getCause().getMessage(), equalTo("Unclosed object or array found"));
}
}
diff --git a/core/src/test/java/org/elasticsearch/common/xcontent/cbor/JsonVsCborTests.java b/core/src/test/java/org/elasticsearch/common/xcontent/cbor/JsonVsCborTests.java
index efbca114aac..fb726b97e3e 100644
--- a/core/src/test/java/org/elasticsearch/common/xcontent/cbor/JsonVsCborTests.java
+++ b/core/src/test/java/org/elasticsearch/common/xcontent/cbor/JsonVsCborTests.java
@@ -48,8 +48,10 @@ public class JsonVsCborTests extends ESTestCase {
xsonGen.writeStringField("test", "value");
jsonGen.writeStringField("test", "value");
- xsonGen.writeArrayFieldStart("arr");
- jsonGen.writeArrayFieldStart("arr");
+ xsonGen.writeFieldName("arr");
+ xsonGen.writeStartArray();
+ jsonGen.writeFieldName("arr");
+ jsonGen.writeStartArray();
xsonGen.writeNumber(1);
jsonGen.writeNumber(1);
xsonGen.writeNull();
diff --git a/core/src/test/java/org/elasticsearch/common/xcontent/smile/JsonVsSmileTests.java b/core/src/test/java/org/elasticsearch/common/xcontent/smile/JsonVsSmileTests.java
index 63b19a63822..ecf49be6629 100644
--- a/core/src/test/java/org/elasticsearch/common/xcontent/smile/JsonVsSmileTests.java
+++ b/core/src/test/java/org/elasticsearch/common/xcontent/smile/JsonVsSmileTests.java
@@ -48,8 +48,10 @@ public class JsonVsSmileTests extends ESTestCase {
xsonGen.writeStringField("test", "value");
jsonGen.writeStringField("test", "value");
- xsonGen.writeArrayFieldStart("arr");
- jsonGen.writeArrayFieldStart("arr");
+ xsonGen.writeFieldName("arr");
+ xsonGen.writeStartArray();
+ jsonGen.writeFieldName("arr");
+ jsonGen.writeStartArray();
xsonGen.writeNumber(1);
jsonGen.writeNumber(1);
xsonGen.writeNull();
diff --git a/core/src/test/java/org/elasticsearch/common/xcontent/support/XContentMapValuesTests.java b/core/src/test/java/org/elasticsearch/common/xcontent/support/XContentMapValuesTests.java
index 1c4ff9874a5..ba2043bbe20 100644
--- a/core/src/test/java/org/elasticsearch/common/xcontent/support/XContentMapValuesTests.java
+++ b/core/src/test/java/org/elasticsearch/common/xcontent/support/XContentMapValuesTests.java
@@ -139,7 +139,7 @@ public class XContentMapValuesTests extends ESTestCase {
// lists
builder = XContentFactory.jsonBuilder().startObject()
- .startObject("path1").field("test", "value1", "value2").endObject()
+ .startObject("path1").array("test", "value1", "value2").endObject()
.endObject();
try (XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(builder.string())) {
diff --git a/core/src/test/java/org/elasticsearch/get/GetActionIT.java b/core/src/test/java/org/elasticsearch/get/GetActionIT.java
index 57de501d93d..25c0e616090 100644
--- a/core/src/test/java/org/elasticsearch/get/GetActionIT.java
+++ b/core/src/test/java/org/elasticsearch/get/GetActionIT.java
@@ -264,10 +264,10 @@ public class GetActionIT extends ESIntegTestCase {
assertThat(response.isExists(), equalTo(false));
client().prepareIndex("test", "type1", "1")
- .setSource(jsonBuilder().startObject().field("field", "1", "2").endObject()).get();
+ .setSource(jsonBuilder().startObject().array("field", "1", "2").endObject()).get();
client().prepareIndex("test", "type2", "1")
- .setSource(jsonBuilder().startObject().field("field", "1", "2").endObject()).get();
+ .setSource(jsonBuilder().startObject().array("field", "1", "2").endObject()).get();
response = client().prepareGet("test", "type1", "1").setFields("field").get();
assertThat(response.isExists(), equalTo(true));
diff --git a/core/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java
index 902b9f2f406..78f9f355b0c 100644
--- a/core/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java
+++ b/core/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java
@@ -37,13 +37,6 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.analysis.NamedAnalyzer;
-import org.elasticsearch.index.mapper.CompletionFieldMapper;
-import org.elasticsearch.index.mapper.DocumentMapper;
-import org.elasticsearch.index.mapper.DocumentMapperParser;
-import org.elasticsearch.index.mapper.FieldMapper;
-import org.elasticsearch.index.mapper.MappedFieldType;
-import org.elasticsearch.index.mapper.MapperParsingException;
-import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.test.ESSingleNodeTestCase;
import java.io.IOException;
@@ -285,7 +278,7 @@ public class CompletionFieldMapperTests extends ESSingleNodeTestCase {
.field("weight", 4)
.endObject()
.startObject()
- .field("input", "suggestion4", "suggestion5", "suggestion6")
+ .array("input", "suggestion4", "suggestion5", "suggestion6")
.field("weight", 5)
.endObject()
.endArray()
diff --git a/core/src/test/java/org/elasticsearch/index/mapper/CopyToMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/CopyToMapperTests.java
index e71ac5b492c..cd08ba98a88 100644
--- a/core/src/test/java/org/elasticsearch/index/mapper/CopyToMapperTests.java
+++ b/core/src/test/java/org/elasticsearch/index/mapper/CopyToMapperTests.java
@@ -28,16 +28,7 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.IndexService;
-import org.elasticsearch.index.mapper.DocumentMapper;
-import org.elasticsearch.index.mapper.DocumentMapperParser;
-import org.elasticsearch.index.mapper.FieldMapper;
-import org.elasticsearch.index.mapper.LegacyLongFieldMapper;
-import org.elasticsearch.index.mapper.MapperParsingException;
-import org.elasticsearch.index.mapper.MapperService;
-import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.ParseContext.Document;
-import org.elasticsearch.index.mapper.ParsedDocument;
-import org.elasticsearch.index.mapper.TextFieldMapper;
import org.elasticsearch.test.ESSingleNodeTestCase;
import java.util.Arrays;
@@ -46,7 +37,6 @@ import java.util.Map;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;
diff --git a/core/src/test/java/org/elasticsearch/index/mapper/SourceFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/SourceFieldMapperTests.java
index 169a7e1d90a..c6f9615623c 100644
--- a/core/src/test/java/org/elasticsearch/index/mapper/SourceFieldMapperTests.java
+++ b/core/src/test/java/org/elasticsearch/index/mapper/SourceFieldMapperTests.java
@@ -28,11 +28,6 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
-import org.elasticsearch.index.mapper.DocumentMapper;
-import org.elasticsearch.index.mapper.DocumentMapperParser;
-import org.elasticsearch.index.mapper.MapperParsingException;
-import org.elasticsearch.index.mapper.MapperService;
-import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESSingleNodeTestCase;
import org.elasticsearch.test.InternalSettingsPlugin;
@@ -87,7 +82,7 @@ public class SourceFieldMapperTests extends ESSingleNodeTestCase {
public void testIncludes() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
- .startObject("_source").field("includes", new String[]{"path1*"}).endObject()
+ .startObject("_source").array("includes", new String[]{"path1*"}).endObject()
.endObject().endObject().string();
DocumentMapper documentMapper = createIndex("test").mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping));
@@ -108,7 +103,7 @@ public class SourceFieldMapperTests extends ESSingleNodeTestCase {
public void testExcludes() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
- .startObject("_source").field("excludes", new String[]{"path1*"}).endObject()
+ .startObject("_source").array("excludes", new String[]{"path1*"}).endObject()
.endObject().endObject().string();
DocumentMapper documentMapper = createIndex("test").mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping));
diff --git a/core/src/test/java/org/elasticsearch/index/mapper/TextFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/TextFieldMapperTests.java
index af24e16b54b..846d2c56669 100644
--- a/core/src/test/java/org/elasticsearch/index/mapper/TextFieldMapperTests.java
+++ b/core/src/test/java/org/elasticsearch/index/mapper/TextFieldMapperTests.java
@@ -208,7 +208,7 @@ public class TextFieldMapperTests extends ESSingleNodeTestCase {
ParsedDocument doc = mapper.parse("test", "type", "1", XContentFactory.jsonBuilder()
.startObject()
- .field("field", new String[] {"a", "b"})
+ .array("field", new String[] {"a", "b"})
.endObject()
.bytes());
@@ -247,7 +247,7 @@ public class TextFieldMapperTests extends ESSingleNodeTestCase {
ParsedDocument doc = mapper.parse("test", "type", "1", XContentFactory.jsonBuilder()
.startObject()
- .field("field", new String[] {"a", "b"})
+ .array("field", new String[] {"a", "b"})
.endObject()
.bytes());
diff --git a/core/src/test/java/org/elasticsearch/mget/SimpleMgetIT.java b/core/src/test/java/org/elasticsearch/mget/SimpleMgetIT.java
index 15fac5ab4c2..e022bd75213 100644
--- a/core/src/test/java/org/elasticsearch/mget/SimpleMgetIT.java
+++ b/core/src/test/java/org/elasticsearch/mget/SimpleMgetIT.java
@@ -108,7 +108,7 @@ public class SimpleMgetIT extends ESIntegTestCase {
public void testThatSourceFilteringIsSupported() throws Exception {
assertAcked(prepareCreate("test").addAlias(new Alias("alias")));
BytesReference sourceBytesRef = jsonBuilder().startObject()
- .field("field", "1", "2")
+ .array("field", "1", "2")
.startObject("included").field("field", "should be seen").field("hidden_field", "should not be seen").endObject()
.field("excluded", "should not be seen")
.endObject().bytes();
diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/BooleanTermsIT.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/BooleanTermsIT.java
index e38f33cfa2b..cfb290284ae 100644
--- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/BooleanTermsIT.java
+++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/BooleanTermsIT.java
@@ -78,7 +78,7 @@ public class BooleanTermsIT extends ESIntegTestCase {
builders[i] = client().prepareIndex("idx", "type").setSource(jsonBuilder()
.startObject()
.field(SINGLE_VALUED_FIELD_NAME, singleValue)
- .field(MULTI_VALUED_FIELD_NAME, multiValue)
+ .array(MULTI_VALUED_FIELD_NAME, multiValue)
.endObject());
}
indexRandom(true, builders);
diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/NestedIT.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/NestedIT.java
index c8b7aa6ad55..51d702e3548 100644
--- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/NestedIT.java
+++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/NestedIT.java
@@ -468,7 +468,7 @@ public class NestedIT extends ESIntegTestCase {
client().prepareIndex("idx4", "product", "1").setSource(jsonBuilder().startObject()
.field("name", "product1")
- .field("categories", "1", "2", "3", "4")
+ .array("categories", "1", "2", "3", "4")
.startArray("property")
.startObject().field("id", 1).endObject()
.startObject().field("id", 2).endObject()
@@ -477,7 +477,7 @@ public class NestedIT extends ESIntegTestCase {
.endObject()).get();
client().prepareIndex("idx4", "product", "2").setSource(jsonBuilder().startObject()
.field("name", "product2")
- .field("categories", "1", "2")
+ .array("categories", "1", "2")
.startArray("property")
.startObject().field("id", 1).endObject()
.startObject().field("id", 5).endObject()
diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/CardinalityIT.java b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/CardinalityIT.java
index 594eba7ddb5..cff1fa746dc 100644
--- a/core/src/test/java/org/elasticsearch/search/aggregations/metrics/CardinalityIT.java
+++ b/core/src/test/java/org/elasticsearch/search/aggregations/metrics/CardinalityIT.java
@@ -134,11 +134,11 @@ public class CardinalityIT extends ESIntegTestCase {
builders[i] = client().prepareIndex("idx", "type").setSource(jsonBuilder()
.startObject()
.field("str_value", "s" + i)
- .field("str_values", new String[]{"s" + (i * 2), "s" + (i * 2 + 1)})
+ .array("str_values", new String[]{"s" + (i * 2), "s" + (i * 2 + 1)})
.field("l_value", i)
- .field("l_values", new int[] {i * 2, i * 2 + 1})
+ .array("l_values", new int[] {i * 2, i * 2 + 1})
.field("d_value", i)
- .field("d_values", new double[]{i * 2, i * 2 + 1})
+ .array("d_values", new double[]{i * 2, i * 2 + 1})
.endObject());
}
indexRandom(true, builders);
diff --git a/core/src/test/java/org/elasticsearch/search/fetch/subphase/highlight/HighlighterSearchIT.java b/core/src/test/java/org/elasticsearch/search/fetch/subphase/highlight/HighlighterSearchIT.java
index 33e8cb3784f..843ab09b2fe 100644
--- a/core/src/test/java/org/elasticsearch/search/fetch/subphase/highlight/HighlighterSearchIT.java
+++ b/core/src/test/java/org/elasticsearch/search/fetch/subphase/highlight/HighlighterSearchIT.java
@@ -1537,7 +1537,7 @@ public class HighlighterSearchIT extends ESIntegTestCase {
.addMapping("type1", "tags", "type=text"));
ensureGreen();
client().prepareIndex("test", "type1", "1")
- .setSource(jsonBuilder().startObject().field("tags",
+ .setSource(jsonBuilder().startObject().array("tags",
"this is a really long tag i would like to highlight",
"here is another one that is very long tag and has the tag token near the end").endObject()).get();
refresh();
diff --git a/core/src/test/java/org/elasticsearch/search/sort/GeoDistanceIT.java b/core/src/test/java/org/elasticsearch/search/sort/GeoDistanceIT.java
index 95c20381cfd..b78496ff18d 100644
--- a/core/src/test/java/org/elasticsearch/search/sort/GeoDistanceIT.java
+++ b/core/src/test/java/org/elasticsearch/search/sort/GeoDistanceIT.java
@@ -230,7 +230,7 @@ public class GeoDistanceIT extends ESIntegTestCase {
.actionGet();
client().prepareIndex("test", "type1", "3")
- .setSource(jsonBuilder().startObject().field("names", "Times Square", "Tribeca").startArray("locations")
+ .setSource(jsonBuilder().startObject().array("names", "Times Square", "Tribeca").startArray("locations")
// to NY: 5.286 km
.startObject().field("lat", 40.759011).field("lon", -73.9844722).endObject()
// to NY: 0.4621 km
@@ -238,7 +238,7 @@ public class GeoDistanceIT extends ESIntegTestCase {
.execute().actionGet();
client().prepareIndex("test", "type1", "4")
- .setSource(jsonBuilder().startObject().field("names", "Wall Street", "Soho").startArray("locations")
+ .setSource(jsonBuilder().startObject().array("names", "Wall Street", "Soho").startArray("locations")
// to NY: 1.055 km
.startObject().field("lat", 40.7051157).field("lon", -74.0088305).endObject()
// to NY: 1.258 km
@@ -246,7 +246,7 @@ public class GeoDistanceIT extends ESIntegTestCase {
.execute().actionGet();
client().prepareIndex("test", "type1", "5")
- .setSource(jsonBuilder().startObject().field("names", "Greenwich Village", "Brooklyn").startArray("locations")
+ .setSource(jsonBuilder().startObject().array("names", "Greenwich Village", "Brooklyn").startArray("locations")
// to NY: 2.029 km
.startObject().field("lat", 40.731033).field("lon", -73.9962255).endObject()
// to NY: 8.572 km
@@ -355,14 +355,14 @@ public class GeoDistanceIT extends ESIntegTestCase {
ensureGreen();
client().prepareIndex("test", "type1", "1")
- .setSource(jsonBuilder().startObject().field("names", "Times Square", "Tribeca").startArray("locations")
+ .setSource(jsonBuilder().startObject().array("names", "Times Square", "Tribeca").startArray("locations")
// to NY: 5.286 km
.startObject().field("lat", 40.759011).field("lon", -73.9844722).endObject()
// to NY: 0.4621 km
.startObject().field("lat", 40.718266).field("lon", -74.007819).endObject().endArray().endObject())
.execute().actionGet();
- client().prepareIndex("test", "type1", "2").setSource(jsonBuilder().startObject().field("names", "Wall Street", "Soho").endObject())
+ client().prepareIndex("test", "type1", "2").setSource(jsonBuilder().startObject().array("names", "Wall Street", "Soho").endObject())
.execute().actionGet();
refresh();
diff --git a/core/src/test/java/org/elasticsearch/search/sort/SimpleSortIT.java b/core/src/test/java/org/elasticsearch/search/sort/SimpleSortIT.java
index 80cda7d7b56..24a82526eda 100644
--- a/core/src/test/java/org/elasticsearch/search/sort/SimpleSortIT.java
+++ b/core/src/test/java/org/elasticsearch/search/sort/SimpleSortIT.java
@@ -25,7 +25,6 @@ import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils;
-import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.MockScriptPlugin;
@@ -251,9 +250,9 @@ public class SimpleSortIT extends ESIntegTestCase {
.setSource(jsonBuilder()
.startObject()
.field("ord", i)
- .field("svalue", new String[]{"" + i, "" + (i + 1), "" + (i + 2)})
- .field("lvalue", new long[]{i, i + 1, i + 2})
- .field("dvalue", new double[]{i, i + 1, i + 2})
+ .array("svalue", new String[]{"" + i, "" + (i + 1), "" + (i + 2)})
+ .array("lvalue", new long[]{i, i + 1, i + 2})
+ .array("dvalue", new double[]{i, i + 1, i + 2})
.startObject("gvalue")
.field("lat", (double) i + 1)
.field("lon", (double) i)
diff --git a/core/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearch2xIT.java b/core/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearch2xIT.java
index 49ad540d956..172183c57c8 100644
--- a/core/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearch2xIT.java
+++ b/core/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearch2xIT.java
@@ -99,7 +99,7 @@ public class CompletionSuggestSearch2xIT extends ESIntegTestCase {
client().prepareIndex(INDEX, TYPE, "" + i)
.setSource(jsonBuilder()
.startObject().startObject(FIELD)
- .field("input", input[i])
+ .array("input", input[i])
.endObject()
.endObject()
)
@@ -941,7 +941,7 @@ public class CompletionSuggestSearch2xIT extends ESIntegTestCase {
builders[i] = client().prepareIndex(INDEX, TYPE, "" + i)
.setSource(jsonBuilder()
.startObject().startObject(FIELD)
- .field("input", input[i])
+ .array("input", input[i])
.field("output", surface[i])
.startObject("payload").field("id", i).endObject()
.field("weight", 1) // WE FORCEFULLY INDEX A BOGUS WEIGHT
@@ -955,7 +955,7 @@ public class CompletionSuggestSearch2xIT extends ESIntegTestCase {
builders[i] = client().prepareIndex(INDEX, TYPE, "n" + i)
.setSource(jsonBuilder()
.startObject().startObject(FIELD)
- .field("input", input[i])
+ .array("input", input[i])
.field("output", surface[i])
.startObject("payload").field("id", i).endObject()
.field("weight", weight[i])
diff --git a/core/src/test/java/org/elasticsearch/search/suggest/ContextSuggestSearch2xIT.java b/core/src/test/java/org/elasticsearch/search/suggest/ContextSuggestSearch2xIT.java
index a3d72f671f7..50733f10838 100644
--- a/core/src/test/java/org/elasticsearch/search/suggest/ContextSuggestSearch2xIT.java
+++ b/core/src/test/java/org/elasticsearch/search/suggest/ContextSuggestSearch2xIT.java
@@ -190,7 +190,7 @@ public class ContextSuggestSearch2xIT extends ESIntegTestCase {
.startObject("context")
.startObject("location")
.field("type", "geo")
- .field("precision", precision)
+ .array("precision", precision)
.endObject()
.endObject()
.endObject().endObject()
@@ -209,7 +209,7 @@ public class ContextSuggestSearch2xIT extends ESIntegTestCase {
.startObject("context")
.startObject("location")
.field("type", "geo")
- .field("precision", precision)
+ .array("precision", precision)
.endObject()
.endObject()
.endObject().endObject()
@@ -314,7 +314,7 @@ public class ContextSuggestSearch2xIT extends ESIntegTestCase {
{ "pizza - treptow", "pizza", "food" } };
for (int i = 0; i < locations.length; i++) {
- XContentBuilder source = jsonBuilder().startObject().startObject(FIELD).field("input", input[i])
+ XContentBuilder source = jsonBuilder().startObject().startObject(FIELD).array("input", input[i])
.startObject("context").field("st", locations[i]).endObject().field("payload", locations[i])
.endObject().endObject();
client().prepareIndex(INDEX, TYPE, "" + i).setSource(source).execute().actionGet();
@@ -343,7 +343,7 @@ public class ContextSuggestSearch2xIT extends ESIntegTestCase {
.addMapping(TYPE, createMapping(TYPE, ContextBuilder.category("st"))));
for (int i = 0; i < HEROS.length; i++) {
- XContentBuilder source = jsonBuilder().startObject().startObject(FIELD).field("input", HEROS[i])
+ XContentBuilder source = jsonBuilder().startObject().startObject(FIELD).array("input", HEROS[i])
.startObject("context").field("st", i%3).endObject()
.startObject("payload").field("group", i % 3).field("id", i).endObject()
.endObject().endObject();
@@ -376,12 +376,12 @@ public class ContextSuggestSearch2xIT extends ESIntegTestCase {
XContentBuilder doc1 = jsonBuilder();
doc1.startObject().startObject("suggest_field")
.field("input", "backpack_red")
- .startObject("context").field("color", "red", "all_colors").endObject()
+ .startObject("context").array("color", "red", "all_colors").endObject()
.endObject().endObject();
XContentBuilder doc2 = jsonBuilder();
doc2.startObject().startObject("suggest_field")
.field("input", "backpack_green")
- .startObject("context").field("color", "green", "all_colors").endObject()
+ .startObject("context").array("color", "green", "all_colors").endObject()
.endObject().endObject();
client().prepareIndex(INDEX, TYPE, "1")
@@ -451,7 +451,7 @@ public class ContextSuggestSearch2xIT extends ESIntegTestCase {
client().prepareIndex(INDEX, TYPE, "" + i)
.setSource(
jsonBuilder().startObject().field("category", Integer.toString(i % 3)).startObject(FIELD)
- .field("input", HEROS[i])
+ .array("input", HEROS[i])
.startObject("context").endObject().field("payload", Integer.toString(i % 3))
.endObject().endObject()).execute().actionGet();
}
@@ -508,7 +508,7 @@ public class ContextSuggestSearch2xIT extends ESIntegTestCase {
client().prepareIndex(INDEX, TYPE, "" + i)
.setSource(
jsonBuilder().startObject().startArray("category").value(Integer.toString(i % 3)).value("other").endArray()
- .startObject(FIELD).field("input", HEROS[i]).startObject("context").endObject()
+ .startObject(FIELD).array("input", HEROS[i]).startObject("context").endObject()
.field("payload", Integer.toString(i % 3)).endObject().endObject()).execute().actionGet();
}
@@ -535,7 +535,7 @@ public class ContextSuggestSearch2xIT extends ESIntegTestCase {
client().prepareIndex(INDEX, TYPE, "" + i)
.setSource(
jsonBuilder().startObject().field("categoryA").value("" + (char) ('0' + (i % 3))).field("categoryB")
- .value("" + (char) ('A' + (i % 3))).startObject(FIELD).field("input", HEROS[i])
+ .value("" + (char) ('A' + (i % 3))).startObject(FIELD).array("input", HEROS[i])
.startObject("context").endObject().field("payload", ((char) ('0' + (i % 3))) + "" + (char) ('A' + (i % 3)))
.endObject().endObject()).execute().actionGet();
}
@@ -561,7 +561,7 @@ public class ContextSuggestSearch2xIT extends ESIntegTestCase {
for (int i = 0; i < HEROS.length; i++) {
String source = jsonBuilder().startObject().field("categoryA", "" + (char) ('0' + (i % 3)))
- .field("categoryB", "" + (char) ('a' + (i % 3))).startObject(FIELD).field("input", HEROS[i])
+ .field("categoryB", "" + (char) ('a' + (i % 3))).startObject(FIELD).array("input", HEROS[i])
.startObject("context").endObject().startObject("payload").field("categoryA", "" + (char) ('0' + (i % 3)))
.field("categoryB", "" + (char) ('a' + (i % 3))).endObject().endObject().endObject().string();
client().prepareIndex(INDEX, TYPE, "" + i).setSource(source).execute().actionGet();
@@ -599,7 +599,7 @@ public class ContextSuggestSearch2xIT extends ESIntegTestCase {
String type = types[i % types.length];
client().prepareIndex(INDEX, type, "" + i)
.setSource(
- jsonBuilder().startObject().startObject(FIELD).field("input", HEROS[i])
+ jsonBuilder().startObject().startObject(FIELD).array("input", HEROS[i])
.startObject("context").endObject().field("payload", type).endObject().endObject()).execute().actionGet();
}
diff --git a/core/src/test/java/org/elasticsearch/search/suggest/completion/CategoryContextMappingTests.java b/core/src/test/java/org/elasticsearch/search/suggest/completion/CategoryContextMappingTests.java
index de912bb9636..fd7a33ee5ba 100644
--- a/core/src/test/java/org/elasticsearch/search/suggest/completion/CategoryContextMappingTests.java
+++ b/core/src/test/java/org/elasticsearch/search/suggest/completion/CategoryContextMappingTests.java
@@ -77,7 +77,7 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
.field("weight", 4)
.endObject()
.startObject()
- .field("input", "suggestion5", "suggestion6", "suggestion7")
+ .array("input", "suggestion5", "suggestion6", "suggestion7")
.field("weight", 5)
.endObject()
.endArray()
@@ -107,7 +107,7 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
.startObject()
.startArray("completion")
.startObject()
- .field("input", "suggestion5", "suggestion6", "suggestion7")
+ .array("input", "suggestion5", "suggestion6", "suggestion7")
.startObject("contexts")
.field("ctx", "ctx1")
.endObject()
@@ -139,7 +139,7 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
ParsedDocument parsedDocument = defaultMapper.parse("test", "type1", "1", jsonBuilder()
.startObject()
.startObject("completion")
- .field("input", "suggestion5", "suggestion6", "suggestion7")
+ .array("input", "suggestion5", "suggestion6", "suggestion7")
.startObject("contexts")
.array("ctx", "ctx1", "ctx2", "ctx3")
.endObject()
@@ -175,7 +175,7 @@ public class CategoryContextMappingTests extends ESSingleNodeTestCase {
.startObject()
.startArray("completion")
.startObject()
- .field("input", "suggestion5", "suggestion6", "suggestion7")
+ .array("input", "suggestion5", "suggestion6", "suggestion7")
.field("weight", 5)
.startObject("contexts")
.array("ctx", "ctx1", "ctx2", "ctx3")
diff --git a/core/src/test/java/org/elasticsearch/search/suggest/completion/GeoContextMappingTests.java b/core/src/test/java/org/elasticsearch/search/suggest/completion/GeoContextMappingTests.java
index 33624ed8002..2237c1a41da 100644
--- a/core/src/test/java/org/elasticsearch/search/suggest/completion/GeoContextMappingTests.java
+++ b/core/src/test/java/org/elasticsearch/search/suggest/completion/GeoContextMappingTests.java
@@ -77,7 +77,7 @@ public class GeoContextMappingTests extends ESSingleNodeTestCase {
.field("weight", 4)
.endObject()
.startObject()
- .field("input", "suggestion5", "suggestion6", "suggestion7")
+ .array("input", "suggestion5", "suggestion6", "suggestion7")
.field("weight", 5)
.endObject()
.endArray()
@@ -108,7 +108,7 @@ public class GeoContextMappingTests extends ESSingleNodeTestCase {
.startObject()
.startArray("completion")
.startObject()
- .field("input", "suggestion5", "suggestion6", "suggestion7")
+ .array("input", "suggestion5", "suggestion6", "suggestion7")
.startObject("contexts")
.startObject("ctx")
.field("lat", 43.6624803)
@@ -143,7 +143,7 @@ public class GeoContextMappingTests extends ESSingleNodeTestCase {
ParsedDocument parsedDocument = defaultMapper.parse("test", "type1", "1", jsonBuilder()
.startObject()
.startObject("completion")
- .field("input", "suggestion5", "suggestion6", "suggestion7")
+ .array("input", "suggestion5", "suggestion6", "suggestion7")
.startObject("contexts")
.startArray("ctx")
.startObject()
@@ -188,7 +188,7 @@ public class GeoContextMappingTests extends ESSingleNodeTestCase {
.startObject()
.startArray("completion")
.startObject()
- .field("input", "suggestion5", "suggestion6", "suggestion7")
+ .array("input", "suggestion5", "suggestion6", "suggestion7")
.field("weight", 5)
.startObject("contexts")
.array("loc1", "ezs42e44yx96")
diff --git a/core/src/test/java/org/elasticsearch/threadpool/SimpleThreadPoolIT.java b/core/src/test/java/org/elasticsearch/threadpool/SimpleThreadPoolIT.java
index 974929dddf2..3928c95bcf8 100644
--- a/core/src/test/java/org/elasticsearch/threadpool/SimpleThreadPoolIT.java
+++ b/core/src/test/java/org/elasticsearch/threadpool/SimpleThreadPoolIT.java
@@ -76,11 +76,11 @@ public class SimpleThreadPoolIT extends ESIntegTestCase {
builders[i] = client().prepareIndex("idx", "type").setSource(jsonBuilder()
.startObject()
.field("str_value", "s" + i)
- .field("str_values", new String[]{"s" + (i * 2), "s" + (i * 2 + 1)})
+ .array("str_values", new String[]{"s" + (i * 2), "s" + (i * 2 + 1)})
.field("l_value", i)
- .field("l_values", new int[]{i * 2, i * 2 + 1})
+ .array("l_values", new int[]{i * 2, i * 2 + 1})
.field("d_value", i)
- .field("d_values", new double[]{i * 2, i * 2 + 1})
+ .array("d_values", new double[]{i * 2, i * 2 + 1})
.endObject());
}
indexRandom(true, builders);
diff --git a/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/ObjectPathTests.java b/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/ObjectPathTests.java
index 5559fd3f385..1f97a6ed13b 100644
--- a/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/ObjectPathTests.java
+++ b/test/framework/src/test/java/org/elasticsearch/test/rest/yaml/ObjectPathTests.java
@@ -22,8 +22,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESTestCase;
-import org.elasticsearch.test.rest.yaml.ObjectPath;
-import org.elasticsearch.test.rest.yaml.Stash;
import java.io.IOException;
import java.util.HashMap;