Mapper: Allow to configure `date_formats` only on the root object mapper, closes #437.

This commit is contained in:
kimchy 2010-10-17 19:56:58 +02:00
parent 69ecf8b66b
commit 0a3d187e6a
2 changed files with 87 additions and 85 deletions

View File

@ -23,7 +23,6 @@ import org.elasticsearch.ElasticSearchIllegalStateException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.util.concurrent.ThreadSafe;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
@ -53,11 +52,6 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
public static final boolean ENABLED = true;
public static final boolean DYNAMIC = true;
public static final ContentPath.Type PATH_TYPE = ContentPath.Type.FULL;
public static final FormatDateTimeFormatter[] DATE_TIME_FORMATTERS =
new FormatDateTimeFormatter[]{
DateFieldMapper.Defaults.DATE_TIME_FORMATTER,
Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd")
};
}
public static class Builder<T extends Builder, Y extends ObjectMapper> extends XContentMapper.Builder<T, Y> {
@ -68,8 +62,6 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
protected ContentPath.Type pathType = Defaults.PATH_TYPE;
protected List<FormatDateTimeFormatter> dateTimeFormatters = newArrayList();
protected Boolean includeInAll;
protected final List<XContentMapper.Builder> mappersBuilders = newArrayList();
@ -94,45 +86,17 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
return builder;
}
public T noDateTimeFormatter() {
this.dateTimeFormatters = null;
return builder;
}
public T includeInAll(boolean includeInAll) {
this.includeInAll = includeInAll;
return builder;
}
public T dateTimeFormatter(Iterable<FormatDateTimeFormatter> dateTimeFormatters) {
for (FormatDateTimeFormatter dateTimeFormatter : dateTimeFormatters) {
this.dateTimeFormatters.add(dateTimeFormatter);
}
return builder;
}
public T dateTimeFormatter(FormatDateTimeFormatter[] dateTimeFormatters) {
this.dateTimeFormatters.addAll(newArrayList(dateTimeFormatters));
return builder;
}
public T dateTimeFormatter(FormatDateTimeFormatter dateTimeFormatter) {
this.dateTimeFormatters.add(dateTimeFormatter);
return builder;
}
public T add(XContentMapper.Builder builder) {
mappersBuilders.add(builder);
return this.builder;
}
@Override public Y build(BuilderContext context) {
if (dateTimeFormatters == null) {
dateTimeFormatters = newArrayList();
} else if (dateTimeFormatters.isEmpty()) {
// add the default one
dateTimeFormatters.addAll(newArrayList(Defaults.DATE_TIME_FORMATTERS));
}
ContentPath.Type origPathType = context.path().pathType();
context.path().pathType(pathType);
context.path().add(name);
@ -142,8 +106,7 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
XContentMapper mapper = builder.build(context);
mappers.put(mapper.name(), mapper);
}
ObjectMapper objectMapper = createMapper(name, enabled, dynamic, pathType,
dateTimeFormatters.toArray(new FormatDateTimeFormatter[dateTimeFormatters.size()]), mappers);
ObjectMapper objectMapper = createMapper(name, enabled, dynamic, pathType, mappers);
context.path().pathType(origPathType);
context.path().remove();
@ -153,9 +116,8 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
return (Y) objectMapper;
}
protected ObjectMapper createMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType,
FormatDateTimeFormatter[] dateTimeFormatters, Map<String, XContentMapper> mappers) {
return new ObjectMapper(name, enabled, dynamic, pathType, dateTimeFormatters, mappers);
protected ObjectMapper createMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType, Map<String, XContentMapper> mappers) {
return new ObjectMapper(name, enabled, dynamic, pathType, mappers);
}
}
@ -175,22 +137,6 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
if (!type.equals("object")) {
throw new MapperParsingException("Trying to parse an object but has a different type [" + type + "] for [" + name + "]");
}
} else if (fieldName.equals("date_formats")) {
List<FormatDateTimeFormatter> dateTimeFormatters = newArrayList();
if (fieldNode instanceof List) {
for (Object node1 : (List) fieldNode) {
dateTimeFormatters.add(parseDateTimeFormatter(fieldName, node1));
}
} else if ("none".equals(fieldNode.toString())) {
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("path")) {
@ -251,8 +197,6 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
private final ContentPath.Type pathType;
private final FormatDateTimeFormatter[] dateTimeFormatters;
private Boolean includeInAll;
private volatile ImmutableMap<String, XContentMapper> mappers = ImmutableMap.of();
@ -263,22 +207,16 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
this(name, Defaults.ENABLED, Defaults.DYNAMIC, Defaults.PATH_TYPE);
}
protected ObjectMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType) {
this(name, enabled, dynamic, pathType, Defaults.DATE_TIME_FORMATTERS);
this(name, enabled, dynamic, pathType, null);
}
protected ObjectMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType,
FormatDateTimeFormatter[] dateTimeFormatters) {
this(name, enabled, dynamic, pathType, dateTimeFormatters, null);
}
ObjectMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType,
FormatDateTimeFormatter[] dateTimeFormatters, Map<String, XContentMapper> mappers) {
ObjectMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType, Map<String, XContentMapper> mappers) {
this.name = name;
this.enabled = enabled;
this.dynamic = dynamic;
this.pathType = pathType;
this.dateTimeFormatters = dateTimeFormatters;
if (mappers != null) {
this.mappers = copyOf(mappers);
}
@ -385,8 +323,7 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
BuilderContext builderContext = new BuilderContext(context.path());
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "object");
if (builder == null) {
builder = XContentMapperBuilders.object(currentFieldName).enabled(true)
.dynamic(dynamic).pathType(pathType).dateTimeFormatter(dateTimeFormatters);
builder = XContentMapperBuilders.object(currentFieldName).enabled(true).dynamic(dynamic).pathType(pathType);
}
objectMapper = builder.build(builderContext);
putMapper(objectMapper);
@ -452,7 +389,7 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
boolean isDate = false;
// a safe check since "1" gets parsed as well
if (text.contains(":") || text.contains("-") || text.contains("/")) {
for (FormatDateTimeFormatter dateTimeFormatter : dateTimeFormatters) {
for (FormatDateTimeFormatter dateTimeFormatter : context.root().dateTimeFormatters()) {
try {
dateTimeFormatter.parser().parseMillis(text);
XContentMapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "date");
@ -605,14 +542,6 @@ public class ObjectMapper implements XContentMapper, IncludeInAllMapper {
doXContent(builder, params);
if (dateTimeFormatters.length > 0) {
builder.startArray("date_formats");
for (FormatDateTimeFormatter dateTimeFormatter : dateTimeFormatters) {
builder.value(dateTimeFormatter.format());
}
builder.endArray();
}
// check internal mappers first (this is only relevant for root object)
for (XContentMapper mapper : mappers.values()) {
if (mapper instanceof InternalMapper) {

View File

@ -21,6 +21,7 @@ package org.elasticsearch.index.mapper.xcontent;
import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.mapper.MapperParsingException;
@ -30,21 +31,54 @@ import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.collect.Lists.*;
import static org.elasticsearch.index.mapper.xcontent.XContentTypeParsers.*;
/**
* @author kimchy (shay.banon)
*/
public class RootObjectMapper extends ObjectMapper {
public static class Defaults {
public static final FormatDateTimeFormatter[] DATE_TIME_FORMATTERS =
new FormatDateTimeFormatter[]{
DateFieldMapper.Defaults.DATE_TIME_FORMATTER,
Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd")
};
}
public static class Builder extends ObjectMapper.Builder<Builder, RootObjectMapper> {
protected final List<DynamicTemplate> dynamicTemplates = newArrayList();
protected List<FormatDateTimeFormatter> dateTimeFormatters = newArrayList();
public Builder(String name) {
super(name);
this.builder = this;
}
public Builder noDateTimeFormatter() {
this.dateTimeFormatters = null;
return builder;
}
public Builder dateTimeFormatter(Iterable<FormatDateTimeFormatter> dateTimeFormatters) {
for (FormatDateTimeFormatter dateTimeFormatter : dateTimeFormatters) {
this.dateTimeFormatters.add(dateTimeFormatter);
}
return builder;
}
public Builder dateTimeFormatter(FormatDateTimeFormatter[] dateTimeFormatters) {
this.dateTimeFormatters.addAll(newArrayList(dateTimeFormatters));
return builder;
}
public Builder dateTimeFormatter(FormatDateTimeFormatter dateTimeFormatter) {
this.dateTimeFormatters.add(dateTimeFormatter);
return builder;
}
public Builder add(DynamicTemplate dynamicTemplate) {
this.dynamicTemplates.add(dynamicTemplate);
return this;
@ -58,8 +92,16 @@ public class RootObjectMapper extends ObjectMapper {
}
@Override protected ObjectMapper createMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType, FormatDateTimeFormatter[] dateTimeFormatters, Map<String, XContentMapper> mappers) {
return new RootObjectMapper(name, enabled, dynamic, pathType, dateTimeFormatters, mappers, dynamicTemplates.toArray(new DynamicTemplate[dynamicTemplates.size()]));
@Override protected ObjectMapper createMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType, Map<String, XContentMapper> mappers) {
if (dateTimeFormatters == null) {
dateTimeFormatters = newArrayList();
} else if (dateTimeFormatters.isEmpty()) {
// add the default one
dateTimeFormatters.addAll(newArrayList(Defaults.DATE_TIME_FORMATTERS));
}
return new RootObjectMapper(name, enabled, dynamic, pathType, mappers,
dateTimeFormatters.toArray(new FormatDateTimeFormatter[dateTimeFormatters.size()]),
dynamicTemplates.toArray(new DynamicTemplate[dynamicTemplates.size()]));
}
}
@ -70,7 +112,23 @@ public class RootObjectMapper extends ObjectMapper {
}
@Override protected void processField(ObjectMapper.Builder builder, String fieldName, Object fieldNode) {
if (fieldName.equals("dynamic_templates")) {
if (fieldName.equals("date_formats")) {
List<FormatDateTimeFormatter> dateTimeFormatters = newArrayList();
if (fieldNode instanceof List) {
for (Object node1 : (List) fieldNode) {
dateTimeFormatters.add(parseDateTimeFormatter(fieldName, node1));
}
} else if ("none".equals(fieldNode.toString())) {
dateTimeFormatters = null;
} else {
dateTimeFormatters.add(parseDateTimeFormatter(fieldName, fieldNode));
}
if (dateTimeFormatters == null) {
((Builder) builder).noDateTimeFormatter();
} else {
((Builder) builder).dateTimeFormatter(dateTimeFormatters);
}
} else if (fieldName.equals("dynamic_templates")) {
// "dynamic_templates" : [
// {
// "template_1" : {
@ -93,12 +151,19 @@ public class RootObjectMapper extends ObjectMapper {
}
}
private final FormatDateTimeFormatter[] dateTimeFormatters;
private volatile DynamicTemplate dynamicTemplates[];
RootObjectMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType,
FormatDateTimeFormatter[] dateTimeFormatters, Map<String, XContentMapper> mappers, DynamicTemplate dynamicTemplates[]) {
super(name, enabled, dynamic, pathType, dateTimeFormatters, mappers);
RootObjectMapper(String name, boolean enabled, boolean dynamic, ContentPath.Type pathType, Map<String, XContentMapper> mappers,
FormatDateTimeFormatter[] dateTimeFormatters, DynamicTemplate dynamicTemplates[]) {
super(name, enabled, dynamic, pathType, mappers);
this.dynamicTemplates = dynamicTemplates;
this.dateTimeFormatters = dateTimeFormatters;
}
public FormatDateTimeFormatter[] dateTimeFormatters() {
return dateTimeFormatters;
}
public XContentMapper.Builder findTemplateBuilder(ParseContext context, String name, String dynamicType) {
@ -141,6 +206,14 @@ public class RootObjectMapper extends ObjectMapper {
}
@Override protected void doXContent(XContentBuilder builder, Params params) throws IOException {
if (dateTimeFormatters.length > 0) {
builder.startArray("date_formats");
for (FormatDateTimeFormatter dateTimeFormatter : dateTimeFormatters) {
builder.value(dateTimeFormatter.format());
}
builder.endArray();
}
if (dynamicTemplates != null && dynamicTemplates.length > 0) {
builder.startArray("dynamic_templates");
for (DynamicTemplate dynamicTemplate : dynamicTemplates) {