XContentParser.Token token;
String fieldName = null;
String distinctField = null;
MutableDateTime dateTime = new MutableDateTime(DateTimeZone.UTC);
// get the interesting fields from the "facet-query"
// basically it's the same code as in the regular DateHisogramFacetParser
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
fieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
} else if (token.isValue()) {
if ("field".equals(fieldName)) {
keyField = parser.text();
} else if ("key_field".equals(fieldName) || "keyField".equals(fieldName)) {
keyField = parser.text();
} else if ("value_field".equals(fieldName) || "distinctField".equals(fieldName)) {
distinctField = parser.text();
} else if ("interval".equals(fieldName)) {
intervalSet = true;
if (token == XContentParser.Token.VALUE_NUMBER) {
interval = parser.longValue();
} else {
sInterval = parser.text();
}
} else if ("time_zone".equals(fieldName) || "timeZone".equals(fieldName)) {
if (token == XContentParser.Token.VALUE_NUMBER) {
dateTime.setZone(DateTimeZone.forOffsetHours(parser.intValue()));
} else {
String text = parser.text();
int index = text.indexOf(':');
if (index != -1) {
// format like -02:30
dateTime.setZone(DateTimeZone.forOffsetHoursMinutes(
Integer.parseInt(text.substring(0, index)),
Integer.parseInt(text.substring(index + 1))
));
} else {
// id, listed here: http://joda-time.sourceforge.net/timezones.html
dateTime.setZone(DateTimeZone.forID(text));
}
}
} else if ("order".equals(fieldName) || "comparator".equals(fieldName)) {
comparatorType = DateHistogramFacet.ComparatorType.fromString(parser.text());
}
}
}
// validation; opposed to the DateHistogramFacetParser the distinctField and interval is also required
if (keyField == null) {
throw new FacetPhaseExecutionException(facetName, "key field is required to be set for distinct histogram facet, either using [field] or using [key_field]");
}
FieldMapper keyMapper = context.smartNameFieldMapper(keyField);
if (keyMapper == null) {
throw new FacetPhaseExecutionException(facetName, "(key) field [" + keyField + "] not found");
} else if (!keyMapper.fieldDataType().getType().equals("long")) {
throw new FacetPhaseExecutionException(facetName, "(key) field [" + keyField + "] is not of type date");
}
if (distinctField == null) {
throw new FacetPhaseExecutionException(facetName, "distinct field is required to be set for distinct histogram facet, either using [value_field] or using [distinctField]");
}
FieldMapper distinctFieldMapper = context.smartNameFieldMapper(distinctField);
if (distinctFieldMapper == null) {
throw new FacetPhaseExecutionException(facetName, "no mapping found for " + distinctField);
}
if (!intervalSet) {
throw new FacetPhaseExecutionException(facetName, "[interval] is required to be set for distinct histogram facet");
}
// this is specific to the "Distinct" DateHistogram. Use a MutableDateTime to take care of the interval and rounding.
// we set the rounding after we set the zone, for it to take affect
if (sInterval != null) {
int index = sInterval.indexOf(':');
if (index != -1) {
// set with rounding
DateFieldParser fieldParser = dateFieldParsers.get(sInterval.substring(0, index));
if (fieldParser == null) {
throw new FacetPhaseExecutionException(facetName, "failed to parse interval [" + sInterval + "] with custom rounding using built in intervals (year/month/...)");
}
DateTimeField field = fieldParser.parse(dateTime.getChronology());
int rounding = this.rounding.get(sInterval.substring(index + 1));
if (rounding == -1) {
throw new FacetPhaseExecutionException(facetName, "failed to parse interval [" + sInterval + "], rounding type [" + (sInterval.substring(index + 1)) + "] not found");
}
dateTime.setRounding(field, rounding);
} else {
DateFieldParser fieldParser = dateFieldParsers.get(sInterval);
if (fieldParser != null) {
DateTimeField field = fieldParser.parse(dateTime.getChronology());
dateTime.setRounding(field, MutableDateTime.ROUND_FLOOR);
} else {
// time interval
try {
interval = TimeValue.parseTimeValue(sInterval, null).millis();
} catch (Exception e) {