org.elasticsearch.xcontent.support.MapXContentParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch-x-content Show documentation
Show all versions of elasticsearch-x-content Show documentation
Elasticsearch subproject :libs:elasticsearch-x-content
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.xcontent.support;
import org.elasticsearch.xcontent.DeprecationHandler;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xcontent.XContentLocation;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.CharBuffer;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Wraps a map generated by XContentParser's map() method into XContent Parser
*/
public class MapXContentParser extends AbstractXContentParser {
private XContentType xContentType;
private TokenIterator iterator;
private boolean closed;
public static XContentParser wrapObject(Object sourceMap) throws IOException {
XContentParser parser = new MapXContentParser(
NamedXContentRegistry.EMPTY,
DeprecationHandler.IGNORE_DEPRECATIONS,
Collections.singletonMap("dummy_field", sourceMap),
XContentType.JSON
);
parser.nextToken(); // start object
parser.nextToken(); // field name
parser.nextToken(); // field value
return parser;
}
public MapXContentParser(
NamedXContentRegistry xContentRegistry,
DeprecationHandler deprecationHandler,
Map map,
XContentType xContentType
) {
super(xContentRegistry, deprecationHandler);
this.xContentType = xContentType;
this.iterator = new MapIterator(null, null, map);
}
@Override
protected boolean doBooleanValue() throws IOException {
if (iterator != null && iterator.currentValue() instanceof Boolean) {
return (Boolean) iterator.currentValue();
} else {
throw new IllegalStateException("Cannot get boolean value for the current token " + currentToken());
}
}
@Override
protected short doShortValue() throws IOException {
return numberValue().shortValue();
}
@Override
protected int doIntValue() throws IOException {
return numberValue().intValue();
}
@Override
protected long doLongValue() throws IOException {
return numberValue().longValue();
}
@Override
protected float doFloatValue() throws IOException {
return numberValue().floatValue();
}
@Override
protected double doDoubleValue() throws IOException {
return numberValue().doubleValue();
}
@Override
public XContentType contentType() {
return xContentType;
}
@Override
public void allowDuplicateKeys(boolean allowDuplicateKeys) {
throw new UnsupportedOperationException("Allowing duplicate keys is not possible for maps");
}
@Override
public Token nextToken() throws IOException {
if (iterator == null) {
return null;
} else {
iterator = iterator.next();
}
return currentToken();
}
@Override
public void skipChildren() throws IOException {
Token token = currentToken();
if (token == Token.START_OBJECT || token == Token.START_ARRAY) {
iterator = iterator.skipChildren();
}
}
@Override
public Token currentToken() {
if (iterator == null) {
return null;
} else {
return iterator.currentToken();
}
}
@Override
public String currentName() throws IOException {
if (iterator == null) {
return null;
} else {
return iterator.currentName();
}
}
@Override
public String text() throws IOException {
if (iterator != null) {
if (currentToken() == Token.VALUE_STRING || currentToken() == Token.VALUE_NUMBER || currentToken() == Token.VALUE_BOOLEAN) {
return iterator.currentValue().toString();
} else if (currentToken() == Token.FIELD_NAME) {
return iterator.currentName();
} else {
return null;
}
} else {
throw new IllegalStateException("Cannot get text for the current token " + currentToken());
}
}
@Override
public CharBuffer charBuffer() throws IOException {
throw new UnsupportedOperationException("use text() instead");
}
@Override
public Object objectText() throws IOException {
throw new UnsupportedOperationException("use text() instead");
}
@Override
public Object objectBytes() throws IOException {
throw new UnsupportedOperationException("use text() instead");
}
@Override
public boolean hasTextCharacters() {
return false;
}
@Override
public char[] textCharacters() throws IOException {
throw new UnsupportedOperationException("use text() instead");
}
@Override
public int textLength() throws IOException {
throw new UnsupportedOperationException("use text() instead");
}
@Override
public int textOffset() throws IOException {
throw new UnsupportedOperationException("use text() instead");
}
@Override
public Number numberValue() throws IOException {
if (iterator != null && currentToken() == Token.VALUE_NUMBER) {
return (Number) iterator.currentValue();
} else {
throw new IllegalStateException("Cannot get numeric value for the current token " + currentToken());
}
}
@Override
public NumberType numberType() throws IOException {
Number number = numberValue();
if (number instanceof Integer) {
return NumberType.INT;
} else if (number instanceof BigInteger) {
return NumberType.BIG_INTEGER;
} else if (number instanceof Long) {
return NumberType.LONG;
} else if (number instanceof Float) {
return NumberType.FLOAT;
} else if (number instanceof Double) {
return NumberType.DOUBLE;
} else if (number instanceof BigDecimal) {
return NumberType.BIG_DECIMAL;
}
throw new IllegalStateException("No matching token for number_type [" + number.getClass() + "]");
}
@Override
public byte[] binaryValue() throws IOException {
if (iterator != null && iterator.currentValue() instanceof byte[]) {
return (byte[]) iterator.currentValue();
} else {
throw new IllegalStateException("Cannot get binary value for the current token " + currentToken());
}
}
@Override
public XContentLocation getTokenLocation() {
return new XContentLocation(0, 0);
}
@Override
public boolean isClosed() {
return closed;
}
@Override
public void close() throws IOException {
closed = true;
}
/**
* Iterator over the elements of the map
*/
private abstract static class TokenIterator {
protected final TokenIterator parent;
protected final String name;
protected Token currentToken;
protected State state = State.BEFORE;
TokenIterator(TokenIterator parent, String name) {
this.parent = parent;
this.name = name;
}
public abstract TokenIterator next();
public abstract TokenIterator skipChildren();
public Token currentToken() {
return currentToken;
}
public abstract Object currentValue();
/**
* name of the field name of the current element
*/
public abstract String currentName();
/**
* field name that the child element needs to inherit.
*
* In most cases this is the same as currentName() except with embedded arrays. In "foo": [[42]] the first START_ARRAY
* token will have the name "foo", but the second START_ARRAY will have no name.
*/
public abstract String childName();
@SuppressWarnings("unchecked")
TokenIterator processValue(Object value) {
if (value instanceof Map) {
return new MapIterator(this, childName(), (Map) value).next();
} else if (value instanceof List) {
return new ArrayIterator(this, childName(), (List