nice(er) code

This commit is contained in:
kimchy 2010-03-29 11:27:38 +03:00
parent a5dc0fcf9a
commit 3decb2a61e
18 changed files with 427 additions and 379 deletions

View File

@ -21,11 +21,17 @@ package org.elasticsearch.index.mapper.json;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
/**
* @author kimchy (Shay Banon)
*/
@ -49,6 +55,15 @@ public class JsonBinaryFieldMapper extends JsonFieldMapper<byte[]> {
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode binaryNode = (ObjectNode) node;
JsonBinaryFieldMapper.Builder builder = binaryField(name);
parseJsonField(builder, name, binaryNode, parserContext);
return builder;
}
}
protected JsonBinaryFieldMapper(Names names) {
super(names, Field.Index.NO, Field.Store.YES, Field.TermVector.NO, 1.0f, true, true, null, null);
}

View File

@ -21,11 +21,20 @@ package org.elasticsearch.index.mapper.json;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.util.Booleans;
import org.elasticsearch.util.lucene.Lucene;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
import static org.elasticsearch.util.json.JacksonNodes.*;
/**
* @author kimchy (shay.banon)
@ -85,6 +94,23 @@ public class JsonBooleanFieldMapper extends JsonFieldMapper<Boolean> {
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode booleanNode = (ObjectNode) node;
JsonBooleanFieldMapper.Builder builder = booleanField(name);
parseJsonField(builder, name, booleanNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = booleanNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeBooleanValue(propNode));
}
}
return builder;
}
}
private Boolean nullValue;
protected JsonBooleanFieldMapper(Names names, Field.Index index, Field.Store store, Field.TermVector termVector,

View File

@ -23,15 +23,23 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.search.*;
import org.apache.lucene.util.NumericUtils;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.analysis.NumericDateAnalyzer;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.util.Numbers;
import org.elasticsearch.util.joda.FormatDateTimeFormatter;
import org.elasticsearch.util.joda.Joda;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
/**
* @author kimchy (shay.banon)
@ -75,6 +83,24 @@ public class JsonDateFieldMapper extends JsonNumberFieldMapper<Long> {
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode dateNode = (ObjectNode) node;
JsonDateFieldMapper.Builder builder = dateField(name);
parseNumberField(builder, name, dateNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = dateNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(propNode.getValueAsText());
} else if (propName.equals("format")) {
builder.dateTimeFormatter(parseDateTimeFormatter(propName, propNode));
}
}
return builder;
}
}
private final FormatDateTimeFormatter dateTimeFormatter;

View File

@ -48,7 +48,7 @@ public class JsonDocumentMapperParser implements DocumentMapperParser {
private final AnalysisService analysisService;
private final JsonObjectTypeParser rootObjectTypeParser = new JsonObjectTypeParser();
private final JsonObjectMapper.TypeParser rootObjectTypeParser = new JsonObjectMapper.TypeParser();
private final Object typeParsersMutex = new Object();
@ -57,17 +57,17 @@ public class JsonDocumentMapperParser implements DocumentMapperParser {
public JsonDocumentMapperParser(AnalysisService analysisService) {
this.analysisService = analysisService;
typeParsers = new MapBuilder<String, JsonTypeParser>()
.put(JsonShortFieldMapper.JSON_TYPE, new JsonShortTypeParser())
.put(JsonIntegerFieldMapper.JSON_TYPE, new JsonIntegerTypeParser())
.put(JsonLongFieldMapper.JSON_TYPE, new JsonLongTypeParser())
.put(JsonFloatFieldMapper.JSON_TYPE, new JsonFloatTypeParser())
.put(JsonDoubleFieldMapper.JSON_TYPE, new JsonDoubleTypeParser())
.put(JsonBooleanFieldMapper.JSON_TYPE, new JsonBooleanTypeParser())
.put(JsonBinaryFieldMapper.JSON_TYPE, new JsonBinaryTypeParser())
.put(JsonDateFieldMapper.JSON_TYPE, new JsonDateTypeParser())
.put(JsonStringFieldMapper.JSON_TYPE, new JsonStringTypeParser())
.put(JsonObjectMapper.JSON_TYPE, new JsonObjectTypeParser())
.put(JsonMultiFieldMapper.JSON_TYPE, new JsonMultiFieldTypeParser())
.put(JsonShortFieldMapper.JSON_TYPE, new JsonShortFieldMapper.TypeParser())
.put(JsonIntegerFieldMapper.JSON_TYPE, new JsonIntegerFieldMapper.TypeParser())
.put(JsonLongFieldMapper.JSON_TYPE, new JsonLongFieldMapper.TypeParser())
.put(JsonFloatFieldMapper.JSON_TYPE, new JsonFloatFieldMapper.TypeParser())
.put(JsonDoubleFieldMapper.JSON_TYPE, new JsonDoubleFieldMapper.TypeParser())
.put(JsonBooleanFieldMapper.JSON_TYPE, new JsonBooleanFieldMapper.TypeParser())
.put(JsonBinaryFieldMapper.JSON_TYPE, new JsonBinaryFieldMapper.TypeParser())
.put(JsonDateFieldMapper.JSON_TYPE, new JsonDateFieldMapper.TypeParser())
.put(JsonStringFieldMapper.JSON_TYPE, new JsonStringFieldMapper.TypeParser())
.put(JsonObjectMapper.JSON_TYPE, new JsonObjectMapper.TypeParser())
.put(JsonMultiFieldMapper.JSON_TYPE, new JsonMultiFieldMapper.TypeParser())
.immutableMap();
}

View File

@ -23,13 +23,22 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.search.*;
import org.apache.lucene.util.NumericUtils;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.analysis.NumericDoubleAnalyzer;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.util.Numbers;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
import static org.elasticsearch.util.json.JacksonNodes.*;
/**
* @author kimchy (shay.banon)
@ -64,6 +73,24 @@ public class JsonDoubleFieldMapper extends JsonNumberFieldMapper<Double> {
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode doubleNode = (ObjectNode) node;
JsonDoubleFieldMapper.Builder builder = doubleField(name);
parseNumberField(builder, name, doubleNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = doubleNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeDoubleValue(propNode));
}
}
return builder;
}
}
private final Double nullValue;
private final String nullValueAsString;

View File

@ -23,13 +23,22 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.search.*;
import org.apache.lucene.util.NumericUtils;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.analysis.NumericFloatAnalyzer;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.util.Numbers;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
import static org.elasticsearch.util.json.JacksonNodes.*;
/**
* @author kimchy (Shay Banon)
@ -64,6 +73,22 @@ public class JsonFloatFieldMapper extends JsonNumberFieldMapper<Float> {
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode floatNode = (ObjectNode) node;
JsonFloatFieldMapper.Builder builder = floatField(name);
parseNumberField(builder, name, floatNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = floatNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeFloatValue(propNode));
}
}
return builder;
}
}
private final Float nullValue;

View File

@ -23,13 +23,22 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.search.*;
import org.apache.lucene.util.NumericUtils;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.analysis.NumericIntegerAnalyzer;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.util.Numbers;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
import static org.elasticsearch.util.json.JacksonNodes.*;
/**
* @author kimchy (shay.banon)
@ -64,6 +73,23 @@ public class JsonIntegerFieldMapper extends JsonNumberFieldMapper<Integer> {
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode integerNode = (ObjectNode) node;
JsonIntegerFieldMapper.Builder builder = integerField(name);
parseNumberField(builder, name, integerNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = integerNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeIntegerValue(propNode));
}
}
return builder;
}
}
private final Integer nullValue;
private final String nullValueAsString;

View File

@ -23,13 +23,22 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.search.*;
import org.apache.lucene.util.NumericUtils;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.analysis.NumericLongAnalyzer;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.util.Numbers;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
import static org.elasticsearch.util.json.JacksonNodes.*;
/**
* @author kimchy (shay.banon)
@ -64,6 +73,23 @@ public class JsonLongFieldMapper extends JsonNumberFieldMapper<Long> {
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode longNode = (ObjectNode) node;
JsonLongFieldMapper.Builder builder = longField(name);
parseNumberField(builder, name, longNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = longNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeLongValue(propNode));
}
}
return builder;
}
}
private final Long nullValue;
private final String nullValueAsString;

View File

@ -20,17 +20,23 @@
package org.elasticsearch.index.mapper.json;
import com.google.common.collect.ImmutableMap;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.FieldMapperListener;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.MergeMappingException;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static com.google.common.collect.Lists.*;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
import static org.elasticsearch.util.MapBuilder.*;
/**
@ -94,6 +100,43 @@ public class JsonMultiFieldMapper implements JsonMapper, JsonIncludeInAllMapper
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode multiFieldNode = (ObjectNode) node;
JsonMultiFieldMapper.Builder builder = multiField(name);
for (Iterator<Map.Entry<String, JsonNode>> fieldsIt = multiFieldNode.getFields(); fieldsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = fieldsIt.next();
String fieldName = entry.getKey();
JsonNode fieldNode = entry.getValue();
if (fieldName.equals("pathType")) {
builder.pathType(parsePathType(name, fieldNode.getValueAsText()));
} else if (fieldName.equals("fields")) {
ObjectNode fieldsNode = (ObjectNode) fieldNode;
for (Iterator<Map.Entry<String, JsonNode>> propsIt = fieldsNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry1 = propsIt.next();
String propName = entry1.getKey();
JsonNode propNode = entry1.getValue();
String type;
JsonNode typeNode = propNode.get("type");
if (typeNode != null) {
type = typeNode.getTextValue();
} else {
throw new MapperParsingException("No type specified for property [" + propName + "]");
}
JsonTypeParser typeParser = parserContext.typeParser(type);
if (typeParser == null) {
throw new MapperParsingException("No handler for type [" + type + "] declared on field [" + fieldName + "]");
}
builder.add(typeParser.parse(propName, propNode, parserContext));
}
}
}
return builder;
}
}
private final String name;
private final JsonPath.Type pathType;

View File

@ -20,26 +20,29 @@
package org.elasticsearch.index.mapper.json;
import com.google.common.collect.ImmutableMap;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.ElasticSearchIllegalStateException;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.FieldMapperListener;
import org.elasticsearch.index.mapper.InternalMapper;
import org.elasticsearch.index.mapper.MergeMappingException;
import org.elasticsearch.index.mapper.*;
import org.elasticsearch.util.concurrent.ThreadSafe;
import org.elasticsearch.util.joda.FormatDateTimeFormatter;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static com.google.common.collect.ImmutableMap.*;
import static com.google.common.collect.Lists.*;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
import static org.elasticsearch.util.MapBuilder.*;
import static org.elasticsearch.util.json.JacksonNodes.*;
/**
* @author kimchy (shay.banon)
@ -151,6 +154,80 @@ public class JsonObjectMapper implements JsonMapper, JsonIncludeInAllMapper {
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode objectNode = (ObjectNode) node;
JsonObjectMapper.Builder builder = object(name);
for (Iterator<Entry<String, JsonNode>> fieldsIt = objectNode.getFields(); fieldsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = fieldsIt.next();
String fieldName = entry.getKey();
JsonNode fieldNode = entry.getValue();
if (fieldName.equals("dynamic")) {
builder.dynamic(nodeBooleanValue(fieldNode));
} else if (fieldName.equals("type")) {
String type = fieldNode.getTextValue();
if (!type.equals("object")) {
throw new MapperParsingException("Trying to parse an object but has a different type [" + type + "] for [" + name + "]");
}
} else if (fieldName.equals("dateFormats")) {
List<FormatDateTimeFormatter> dateTimeFormatters = newArrayList();
if (fieldNode.isArray()) {
for (JsonNode node1 : (ArrayNode) fieldNode) {
dateTimeFormatters.add(parseDateTimeFormatter(fieldName, node1));
}
} else if ("none".equals(fieldNode.getValueAsText())) {
dateTimeFormatters = null;
} else {
dateTimeFormatters.add(parseDateTimeFormatter(fieldName, fieldNode));
}
if (dateTimeFormatters == null) {
builder.noDateTimeFormatter();
} else {
builder.dateTimeFormatter(dateTimeFormatters);
}
} else if (fieldName.equals("enabled")) {
builder.enabled(nodeBooleanValue(fieldNode));
} else if (fieldName.equals("pathType")) {
builder.pathType(parsePathType(name, fieldNode.getValueAsText()));
} else if (fieldName.equals("properties")) {
parseProperties(builder, (ObjectNode) fieldNode, parserContext);
} else if (fieldName.equals("includeInAll")) {
builder.includeInAll(nodeBooleanValue(fieldNode));
}
}
return builder;
}
private void parseProperties(JsonObjectMapper.Builder objBuilder, ObjectNode propsNode, JsonTypeParser.ParserContext parserContext) {
for (Iterator<Map.Entry<String, JsonNode>> propsIt = propsNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
String type;
JsonNode typeNode = propNode.get("type");
if (typeNode != null) {
type = typeNode.getTextValue();
} else {
// lets see if we can derive this...
if (propNode.isObject() && propNode.get("properties") != null) {
type = JsonObjectMapper.JSON_TYPE;
} else if (propNode.isObject() && propNode.get("fields") != null) {
type = JsonMultiFieldMapper.JSON_TYPE;
} else {
throw new MapperParsingException("No type specified for property [" + propName + "]");
}
}
JsonTypeParser typeParser = parserContext.typeParser(type);
if (typeParser == null) {
throw new MapperParsingException("No handler for type [" + type + "] declared on field [" + propName + "]");
}
objBuilder.add(typeParser.parse(propName, propNode, parserContext));
}
}
}
private final String name;
private final boolean enabled;

View File

@ -23,13 +23,22 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.search.*;
import org.apache.lucene.util.NumericUtils;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.analysis.NumericIntegerAnalyzer;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.util.Numbers;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
import static org.elasticsearch.util.json.JacksonNodes.*;
/**
* @author kimchy (shay.banon)
@ -64,6 +73,23 @@ public class JsonShortFieldMapper extends JsonNumberFieldMapper<Short> {
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode shortNode = (ObjectNode) node;
JsonShortFieldMapper.Builder builder = shortField(name);
parseNumberField(builder, name, shortNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = shortNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeShortValue(propNode));
}
}
return builder;
}
}
private final Short nullValue;
private final String nullValueAsString;

View File

@ -21,11 +21,19 @@ package org.elasticsearch.index.mapper.json;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
/**
* @author kimchy (shay.banon)
@ -67,6 +75,24 @@ public class JsonStringFieldMapper extends JsonFieldMapper<String> implements Js
}
}
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode stringNode = (ObjectNode) node;
JsonStringFieldMapper.Builder builder = stringField(name);
parseJsonField(builder, name, stringNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = stringNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(propNode.getValueAsText());
}
}
return builder;
}
}
private final String nullValue;
private Boolean includeInAll;

View File

@ -21,18 +21,14 @@ package org.elasticsearch.index.mapper.json;
import org.apache.lucene.document.Field;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.util.joda.FormatDateTimeFormatter;
import org.elasticsearch.util.joda.Joda;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static com.google.common.collect.Lists.*;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.util.json.JacksonNodes.*;
/**
@ -40,264 +36,6 @@ import static org.elasticsearch.util.json.JacksonNodes.*;
*/
public class JsonTypeParsers {
public static class JsonObjectTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode objectNode = (ObjectNode) node;
JsonObjectMapper.Builder builder = object(name);
for (Iterator<Map.Entry<String, JsonNode>> fieldsIt = objectNode.getFields(); fieldsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = fieldsIt.next();
String fieldName = entry.getKey();
JsonNode fieldNode = entry.getValue();
if (fieldName.equals("dynamic")) {
builder.dynamic(nodeBooleanValue(fieldNode));
} else if (fieldName.equals("type")) {
String type = fieldNode.getTextValue();
if (!type.equals("object")) {
throw new MapperParsingException("Trying to parse an object but has a different type [" + type + "] for [" + name + "]");
}
} else if (fieldName.equals("dateFormats")) {
List<FormatDateTimeFormatter> dateTimeFormatters = newArrayList();
if (fieldNode.isArray()) {
for (JsonNode node1 : (ArrayNode) fieldNode) {
dateTimeFormatters.add(parseDateTimeFormatter(fieldName, node1));
}
} else if ("none".equals(fieldNode.getValueAsText())) {
dateTimeFormatters = null;
} else {
dateTimeFormatters.add(parseDateTimeFormatter(fieldName, fieldNode));
}
if (dateTimeFormatters == null) {
builder.noDateTimeFormatter();
} else {
builder.dateTimeFormatter(dateTimeFormatters);
}
} else if (fieldName.equals("enabled")) {
builder.enabled(nodeBooleanValue(fieldNode));
} else if (fieldName.equals("pathType")) {
builder.pathType(parsePathType(name, fieldNode.getValueAsText()));
} else if (fieldName.equals("properties")) {
parseProperties(builder, (ObjectNode) fieldNode, parserContext);
} else if (fieldName.equals("includeInAll")) {
builder.includeInAll(nodeBooleanValue(fieldNode));
}
}
return builder;
}
private void parseProperties(JsonObjectMapper.Builder objBuilder, ObjectNode propsNode, JsonTypeParser.ParserContext parserContext) {
for (Iterator<Map.Entry<String, JsonNode>> propsIt = propsNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
String type;
JsonNode typeNode = propNode.get("type");
if (typeNode != null) {
type = typeNode.getTextValue();
} else {
// lets see if we can derive this...
if (propNode.isObject() && propNode.get("properties") != null) {
type = JsonObjectMapper.JSON_TYPE;
} else if (propNode.isObject() && propNode.get("fields") != null) {
type = JsonMultiFieldMapper.JSON_TYPE;
} else {
throw new MapperParsingException("No type specified for property [" + propName + "]");
}
}
JsonTypeParser typeParser = parserContext.typeParser(type);
if (typeParser == null) {
throw new MapperParsingException("No handler for type [" + type + "] declared on field [" + propName + "]");
}
objBuilder.add(typeParser.parse(propName, propNode, parserContext));
}
}
}
public static class JsonMultiFieldTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode multiFieldNode = (ObjectNode) node;
JsonMultiFieldMapper.Builder builder = multiField(name);
for (Iterator<Map.Entry<String, JsonNode>> fieldsIt = multiFieldNode.getFields(); fieldsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = fieldsIt.next();
String fieldName = entry.getKey();
JsonNode fieldNode = entry.getValue();
if (fieldName.equals("pathType")) {
builder.pathType(parsePathType(name, fieldNode.getValueAsText()));
} else if (fieldName.equals("fields")) {
ObjectNode fieldsNode = (ObjectNode) fieldNode;
for (Iterator<Map.Entry<String, JsonNode>> propsIt = fieldsNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry1 = propsIt.next();
String propName = entry1.getKey();
JsonNode propNode = entry1.getValue();
String type;
JsonNode typeNode = propNode.get("type");
if (typeNode != null) {
type = typeNode.getTextValue();
} else {
throw new MapperParsingException("No type specified for property [" + propName + "]");
}
JsonTypeParser typeParser = parserContext.typeParser(type);
if (typeParser == null) {
throw new MapperParsingException("No handler for type [" + type + "] declared on field [" + fieldName + "]");
}
builder.add(typeParser.parse(propName, propNode, parserContext));
}
}
}
return builder;
}
}
public static class JsonDateTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode dateNode = (ObjectNode) node;
JsonDateFieldMapper.Builder builder = dateField(name);
parseNumberField(builder, name, dateNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = dateNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(propNode.getValueAsText());
} else if (propName.equals("format")) {
builder.dateTimeFormatter(parseDateTimeFormatter(propName, propNode));
}
}
return builder;
}
}
public static class JsonShortTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode shortNode = (ObjectNode) node;
JsonShortFieldMapper.Builder builder = shortField(name);
parseNumberField(builder, name, shortNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = shortNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeShortValue(propNode));
}
}
return builder;
}
}
public static class JsonIntegerTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode integerNode = (ObjectNode) node;
JsonIntegerFieldMapper.Builder builder = integerField(name);
parseNumberField(builder, name, integerNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = integerNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeIntegerValue(propNode));
}
}
return builder;
}
}
public static class JsonLongTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode longNode = (ObjectNode) node;
JsonLongFieldMapper.Builder builder = longField(name);
parseNumberField(builder, name, longNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = longNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeLongValue(propNode));
}
}
return builder;
}
}
public static class JsonFloatTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode floatNode = (ObjectNode) node;
JsonFloatFieldMapper.Builder builder = floatField(name);
parseNumberField(builder, name, floatNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = floatNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeFloatValue(propNode));
}
}
return builder;
}
}
public static class JsonDoubleTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode doubleNode = (ObjectNode) node;
JsonDoubleFieldMapper.Builder builder = doubleField(name);
parseNumberField(builder, name, doubleNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = doubleNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeDoubleValue(propNode));
}
}
return builder;
}
}
public static class JsonStringTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode stringNode = (ObjectNode) node;
JsonStringFieldMapper.Builder builder = stringField(name);
parseJsonField(builder, name, stringNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = stringNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(propNode.getValueAsText());
}
}
return builder;
}
}
public static class JsonBinaryTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode binaryNode = (ObjectNode) node;
JsonBinaryFieldMapper.Builder builder = binaryField(name);
parseJsonField(builder, name, binaryNode, parserContext);
return builder;
}
}
public static class JsonBooleanTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode booleanNode = (ObjectNode) node;
JsonBooleanFieldMapper.Builder builder = booleanField(name);
parseJsonField(builder, name, booleanNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = booleanNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeBooleanValue(propNode));
}
}
return builder;
}
}
public static void parseNumberField(JsonNumberFieldMapper.Builder builder, String name, ObjectNode numberNode, JsonTypeParser.ParserContext parserContext) {
parseJsonField(builder, name, numberNode, parserContext);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = numberNode.getFields(); propsIt.hasNext();) {

View File

@ -20,7 +20,7 @@
package org.elasticsearch.plugin.attachments;
import com.google.inject.AbstractModule;
import org.elasticsearch.plugin.attachments.index.mapper.JsonAttachmentMapperInjector;
import org.elasticsearch.plugin.attachments.index.mapper.JsonAttachmentMapperService;
/**
* @author kimchy (shay.banon)
@ -28,6 +28,6 @@ import org.elasticsearch.plugin.attachments.index.mapper.JsonAttachmentMapperInj
public class AttachmentsIndexModule extends AbstractModule {
@Override protected void configure() {
bind(JsonAttachmentMapperInjector.class).asEagerSingleton();
bind(JsonAttachmentMapperService.class).asEagerSingleton();
}
}

View File

@ -21,10 +21,8 @@ package org.elasticsearch.plugin.attachments.index.mapper;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.codehaus.jackson.Base64Variant;
import org.codehaus.jackson.Base64Variants;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.*;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.mapper.FieldMapperListener;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.MergeMappingException;
@ -33,8 +31,11 @@ import org.elasticsearch.util.io.FastByteArrayInputStream;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.index.mapper.json.JsonMapperBuilders.*;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
import static org.elasticsearch.plugin.attachments.tika.TikaInstance.*;
/**
@ -133,6 +134,63 @@ public class JsonAttachmentMapper implements JsonMapper {
}
}
/**
* <pre>
* field1 : { type : "attachment" }
* </pre>
* Or:
* <pre>
* field1 : {
* type : "attachment",
* fields : {
* field1 : {type : "binary"},
* title : {store : "yes"},
* date : {store : "yes"}
* }
* }
* </pre>
*
* @author kimchy (shay.banon)
*/
public static class TypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode attachmentNode = (ObjectNode) node;
JsonAttachmentMapper.Builder builder = new JsonAttachmentMapper.Builder(name);
for (Iterator<Map.Entry<String, JsonNode>> fieldsIt = attachmentNode.getFields(); fieldsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = fieldsIt.next();
String fieldName = entry.getKey();
JsonNode fieldNode = entry.getValue();
if (fieldName.equals("pathType")) {
builder.pathType(parsePathType(name, fieldNode.getValueAsText()));
} else if (fieldName.equals("fields")) {
ObjectNode fieldsNode = (ObjectNode) fieldNode;
for (Iterator<Map.Entry<String, JsonNode>> propsIt = fieldsNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry1 = propsIt.next();
String propName = entry1.getKey();
JsonNode propNode = entry1.getValue();
if (name.equals(propName)) {
// that is the content
builder.content((JsonStringFieldMapper.Builder) parserContext.typeParser("string").parse(name, propNode, parserContext));
} else if ("date".equals(propName)) {
builder.date((JsonDateFieldMapper.Builder) parserContext.typeParser("date").parse("date", propNode, parserContext));
} else if ("title".equals(propName)) {
builder.title((JsonStringFieldMapper.Builder) parserContext.typeParser("string").parse("title", propNode, parserContext));
} else if ("author".equals(propName)) {
builder.author((JsonStringFieldMapper.Builder) parserContext.typeParser("string").parse("author", propNode, parserContext));
} else if ("keywords".equals(propName)) {
builder.keywords((JsonStringFieldMapper.Builder) parserContext.typeParser("string").parse("keywords", propNode, parserContext));
}
}
}
}
return builder;
}
}
private final String name;

View File

@ -30,11 +30,11 @@ import org.elasticsearch.util.settings.Settings;
/**
* @author kimchy (shay.banon)
*/
public class JsonAttachmentMapperInjector extends AbstractIndexComponent {
public class JsonAttachmentMapperService extends AbstractIndexComponent {
@Inject public JsonAttachmentMapperInjector(Index index, @IndexSettings Settings indexSettings, MapperService mapperService) {
@Inject public JsonAttachmentMapperService(Index index, @IndexSettings Settings indexSettings, MapperService mapperService) {
super(index, indexSettings);
((JsonDocumentMapperParser) mapperService.documentMapperParser()).putTypeParser("attachment", new JsonAttachmentTypeParser());
((JsonDocumentMapperParser) mapperService.documentMapperParser()).putTypeParser("attachment", new JsonAttachmentMapper.TypeParser());
}
}

View File

@ -1,91 +0,0 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.plugin.attachments.index.mapper;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ObjectNode;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.json.JsonDateFieldMapper;
import org.elasticsearch.index.mapper.json.JsonMapper;
import org.elasticsearch.index.mapper.json.JsonStringFieldMapper;
import org.elasticsearch.index.mapper.json.JsonTypeParser;
import java.util.Iterator;
import java.util.Map;
import static org.elasticsearch.index.mapper.json.JsonTypeParsers.*;
/**
* <pre>
* field1 : { type : "attachment" }
* </pre>
* Or:
* <pre>
* field1 : {
* type : "attachment",
* fields : {
* field1 : {type : "binary"},
* title : {store : "yes"},
* date : {store : "yes"}
* }
* }
* </pre>
*
* @author kimchy (shay.banon)
*/
public class JsonAttachmentTypeParser implements JsonTypeParser {
@Override public JsonMapper.Builder parse(String name, JsonNode node, ParserContext parserContext) throws MapperParsingException {
ObjectNode attachmentNode = (ObjectNode) node;
JsonAttachmentMapper.Builder builder = new JsonAttachmentMapper.Builder(name);
for (Iterator<Map.Entry<String, JsonNode>> fieldsIt = attachmentNode.getFields(); fieldsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = fieldsIt.next();
String fieldName = entry.getKey();
JsonNode fieldNode = entry.getValue();
if (fieldName.equals("pathType")) {
builder.pathType(parsePathType(name, fieldNode.getValueAsText()));
} else if (fieldName.equals("fields")) {
ObjectNode fieldsNode = (ObjectNode) fieldNode;
for (Iterator<Map.Entry<String, JsonNode>> propsIt = fieldsNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry1 = propsIt.next();
String propName = entry1.getKey();
JsonNode propNode = entry1.getValue();
if (name.equals(propName)) {
// that is the content
builder.content((JsonStringFieldMapper.Builder) parserContext.typeParser("string").parse(name, propNode, parserContext));
} else if ("date".equals(propName)) {
builder.date((JsonDateFieldMapper.Builder) parserContext.typeParser("date").parse("date", propNode, parserContext));
} else if ("title".equals(propName)) {
builder.title((JsonStringFieldMapper.Builder) parserContext.typeParser("string").parse("title", propNode, parserContext));
} else if ("author".equals(propName)) {
builder.author((JsonStringFieldMapper.Builder) parserContext.typeParser("string").parse("author", propNode, parserContext));
} else if ("keywords".equals(propName)) {
builder.keywords((JsonStringFieldMapper.Builder) parserContext.typeParser("string").parse("keywords", propNode, parserContext));
}
}
}
}
return builder;
}
}

View File

@ -42,7 +42,7 @@ public class SimpleAttachmentMapperTests {
@BeforeTest public void setupMapperParser() {
mapperParser = new JsonDocumentMapperParser(new AnalysisService(new Index("test")));
mapperParser.putTypeParser(JsonAttachmentMapper.JSON_TYPE, new JsonAttachmentTypeParser());
mapperParser.putTypeParser(JsonAttachmentMapper.JSON_TYPE, new JsonAttachmentMapper.TypeParser());
}
@Test public void testSimpleMappings() throws Exception {