Centralized xcontent parsing of time values

- Renamed `WatcherDateUtils` to `WatcherDateTimeUtils`

Original commit: elastic/x-pack-elasticsearch@6b5557058a
This commit is contained in:
uboness 2015-05-11 15:14:51 +02:00
parent e0a70722e0
commit 575208c338
14 changed files with 148 additions and 25 deletions

View File

@ -19,7 +19,7 @@ import java.io.IOException;
import java.util.Locale;
import static org.elasticsearch.common.joda.time.DateTimeZone.UTC;
import static org.elasticsearch.watcher.support.WatcherDateUtils.dateTimeFormatter;
import static org.elasticsearch.watcher.support.WatcherDateTimeUtils.dateTimeFormatter;
/**
*

View File

@ -18,6 +18,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.watcher.execution.WatchExecutionContext;
import org.elasticsearch.watcher.execution.Wid;
import org.elasticsearch.watcher.license.LicenseService;
import org.elasticsearch.watcher.support.WatcherDateTimeUtils;
import org.elasticsearch.watcher.support.clock.Clock;
import org.elasticsearch.watcher.actions.throttler.ActionThrottler;
import org.elasticsearch.watcher.actions.throttler.Throttler;
@ -153,10 +154,10 @@ public class ActionWrapper implements ToXContent {
if (Transform.Field.TRANSFORM.match(currentFieldName)) {
transform = transformRegistry.parse(watchId, parser);
} else if (Throttler.Field.THROTTLE_PERIOD.match(currentFieldName)) {
if (token == XContentParser.Token.VALUE_NUMBER) {
throttlePeriod = new TimeValue(parser.longValue());
} else {
throw new ActionException("could not parse action [{}/{}]. expected field [{}] to hold a numeric value, but instead found", watchId, actionId, currentFieldName, token);
try {
throttlePeriod = WatcherDateTimeUtils.parseTimeValue(parser, null);
} catch (WatcherDateTimeUtils.ParseException pe) {
throw new ActionException("could not parse action [{}/{}]. failed to parse field [{}] as time value", pe, watchId, actionId, currentFieldName);
}
} else {
// it's the type of the action

View File

@ -7,10 +7,9 @@ package org.elasticsearch.watcher.actions.throttler;
import org.elasticsearch.watcher.actions.ActionStatus;
import org.elasticsearch.watcher.actions.ActionStatus.AckStatus;
import org.elasticsearch.watcher.actions.throttler.Throttler;
import org.elasticsearch.watcher.execution.WatchExecutionContext;
import static org.elasticsearch.watcher.support.WatcherDateUtils.formatDate;
import static org.elasticsearch.watcher.support.WatcherDateTimeUtils.formatDate;
/**
*

View File

@ -18,7 +18,7 @@ import org.elasticsearch.watcher.condition.Condition;
import org.elasticsearch.watcher.condition.ConditionRegistry;
import org.elasticsearch.watcher.input.Input;
import org.elasticsearch.watcher.input.InputRegistry;
import org.elasticsearch.watcher.support.WatcherDateUtils;
import org.elasticsearch.watcher.support.WatcherDateTimeUtils;
import org.elasticsearch.watcher.transform.Transform;
import org.elasticsearch.watcher.transform.TransformRegistry;
@ -72,7 +72,7 @@ public class WatchExecutionResult implements ToXContent {
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
WatcherDateUtils.writeDate(Field.EXECUTION_TIME.getPreferredName(), builder, executionTime);
WatcherDateTimeUtils.writeDate(Field.EXECUTION_TIME.getPreferredName(), builder, executionTime);
if (inputResult != null) {
builder.startObject(Field.INPUT.getPreferredName())
.field(inputResult.type(), inputResult, params)
@ -109,8 +109,8 @@ public class WatchExecutionResult implements ToXContent {
currentFieldName = parser.currentName();
} else if (Field.EXECUTION_TIME.match(currentFieldName)) {
try {
executionTime = WatcherDateUtils.parseDate(currentFieldName, parser, UTC);
} catch (WatcherDateUtils.ParseException pe) {
executionTime = WatcherDateTimeUtils.parseDate(currentFieldName, parser, UTC);
} catch (WatcherDateTimeUtils.ParseException pe) {
throw new WatcherException("could not parse watch execution [{}]. failed to parse date field [{}]", pe, wid, currentFieldName);
}
} else if (Field.ACTIONS.match(currentFieldName)) {

View File

@ -12,10 +12,14 @@ import org.elasticsearch.common.joda.DateMathParser;
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
import org.elasticsearch.common.joda.time.DateTime;
import org.elasticsearch.common.joda.time.DateTimeZone;
import org.elasticsearch.common.joda.time.PeriodType;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.core.DateFieldMapper;
import org.elasticsearch.watcher.WatcherException;
import org.elasticsearch.watcher.actions.ActionException;
import org.elasticsearch.watcher.rest.action.RestExecuteWatchAction;
import org.elasticsearch.watcher.support.clock.Clock;
import java.io.IOException;
@ -24,12 +28,12 @@ import java.util.concurrent.TimeUnit;
/**
*
*/
public class WatcherDateUtils {
public class WatcherDateTimeUtils {
public static final FormatDateTimeFormatter dateTimeFormatter = DateFieldMapper.Defaults.DATE_TIME_FORMATTER;
public static final DateMathParser dateMathParser = new DateMathParser(dateTimeFormatter, TimeUnit.SECONDS);
private WatcherDateUtils() {
private WatcherDateTimeUtils() {
}
public static DateTime parseDate(String dateAsText) {
@ -116,6 +120,24 @@ public class WatcherDateUtils {
return in.readBoolean() ? new DateTime(in.readLong(), timeZone) : null;
}
public static TimeValue parseTimeValue(XContentParser parser, TimeValue defaultValue) throws IOException {
return parseTimeValue(parser, TimeUnit.MILLISECONDS, defaultValue);
}
public static TimeValue parseTimeValue(XContentParser parser, TimeUnit defaultTimeUnit, TimeValue defaultValue) throws IOException {
XContentParser.Token token = parser.currentToken();
if (token == XContentParser.Token.VALUE_NULL) {
return defaultValue;
}
if (token == XContentParser.Token.VALUE_NUMBER) {
return new TimeValue(parser.longValue(), defaultTimeUnit);
} else if (token == XContentParser.Token.VALUE_STRING) {
return TimeValue.parseTimeValue(parser.text(), defaultValue);
} else {
throw new ParseException("could not parse time value. expected either a string or a numeric value but found [{}] instead", token);
}
}
public static class ParseException extends WatcherException {
public ParseException(String msg, Throwable cause, Object... args) {
super(msg, cause, args);

View File

@ -25,7 +25,7 @@ import java.lang.reflect.Array;
import java.util.*;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.watcher.support.WatcherDateUtils.formatDate;
import static org.elasticsearch.watcher.support.WatcherDateTimeUtils.formatDate;
/**
*/

View File

@ -10,7 +10,7 @@ import org.elasticsearch.common.joda.time.DateTime;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.watcher.WatcherException;
import org.elasticsearch.watcher.support.WatcherDateUtils;
import org.elasticsearch.watcher.support.WatcherDateTimeUtils;
import org.elasticsearch.watcher.support.clock.Clock;
import org.elasticsearch.watcher.trigger.TriggerEvent;
@ -47,8 +47,8 @@ public class ScheduleTriggerEvent extends TriggerEvent {
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
WatcherDateUtils.writeDate(Field.TRIGGERED_TIME.getPreferredName(), builder, triggeredTime);
WatcherDateUtils.writeDate(Field.SCHEDULED_TIME.getPreferredName(), builder, scheduledTime);
WatcherDateTimeUtils.writeDate(Field.TRIGGERED_TIME.getPreferredName(), builder, triggeredTime);
WatcherDateTimeUtils.writeDate(Field.SCHEDULED_TIME.getPreferredName(), builder, scheduledTime);
return builder.endObject();
}
@ -63,15 +63,15 @@ public class ScheduleTriggerEvent extends TriggerEvent {
currentFieldName = parser.currentName();
} else if (Field.TRIGGERED_TIME.match(currentFieldName)) {
try {
triggeredTime = WatcherDateUtils.parseDateMath(currentFieldName, parser, UTC, clock);
} catch (WatcherDateUtils.ParseException pe) {
triggeredTime = WatcherDateTimeUtils.parseDateMath(currentFieldName, parser, UTC, clock);
} catch (WatcherDateTimeUtils.ParseException pe) {
//Failed to parse as a date try datemath parsing
throw new ParseException("could not parse [{}] trigger event for [{}] for watch [{}]. failed to parse date field [{}]", pe, ScheduleTriggerEngine.TYPE, context, watchId, currentFieldName);
}
} else if (Field.SCHEDULED_TIME.match(currentFieldName)) {
try {
scheduledTime = WatcherDateUtils.parseDateMath(currentFieldName, parser, UTC, clock);
} catch (WatcherDateUtils.ParseException pe) {
scheduledTime = WatcherDateTimeUtils.parseDateMath(currentFieldName, parser, UTC, clock);
} catch (WatcherDateTimeUtils.ParseException pe) {
throw new ParseException("could not parse [{}] trigger event for [{}] for watch [{}]. failed to parse date field [{}]", pe, ScheduleTriggerEngine.TYPE, context, watchId, currentFieldName);
}
}else {

View File

@ -32,6 +32,7 @@ import org.elasticsearch.watcher.condition.always.ExecutableAlwaysCondition;
import org.elasticsearch.watcher.input.ExecutableInput;
import org.elasticsearch.watcher.input.InputRegistry;
import org.elasticsearch.watcher.input.none.ExecutableNoneInput;
import org.elasticsearch.watcher.support.WatcherDateTimeUtils;
import org.elasticsearch.watcher.support.clock.Clock;
import org.elasticsearch.watcher.support.secret.SecretService;
import org.elasticsearch.watcher.support.secret.SensitiveXContentParser;
@ -286,12 +287,19 @@ public class Watch implements TriggerEngine.Job, ToXContent {
} else if (Field.TRANSFORM.match(currentFieldName)) {
transform = transformRegistry.parse(id, parser);
} else if (Field.THROTTLE_PERIOD.match(currentFieldName)) {
<<<<<<< HEAD
if (token == XContentParser.Token.VALUE_STRING) {
throttlePeriod = TimeValue.parseTimeValue(parser.text(), null);
} else if (token == XContentParser.Token.VALUE_NUMBER) {
throttlePeriod = TimeValue.timeValueMillis(parser.longValue());
} else {
throw new ParseException("could not parse watch [{}]. expected field [{}] to either be string or numeric, but found [{}] instead", id, currentFieldName, token);
=======
try {
throttlePeriod = WatcherDateTimeUtils.parseTimeValue(parser, null);
} catch (WatcherDateTimeUtils.ParseException pe) {
throw new ParseException("could not parse watch [{}]. failed to parse time value for field [{}]", pe, id, currentFieldName);
>>>>>>> Centralized xcontent parsing of time values
}
} else if (Field.ACTIONS.match(currentFieldName)) {
actions = actionRegistry.parseActions(id, parser);

View File

@ -25,7 +25,7 @@ import java.io.IOException;
import java.util.Map;
import static org.elasticsearch.common.joda.time.DateTimeZone.UTC;
import static org.elasticsearch.watcher.support.WatcherDateUtils.*;
import static org.elasticsearch.watcher.support.WatcherDateTimeUtils.*;
/**
*

View File

@ -13,7 +13,7 @@ import org.elasticsearch.watcher.watch.Watch;
import org.elasticsearch.watcher.watch.WatchStatus;
import org.junit.Test;
import static org.elasticsearch.watcher.support.WatcherDateUtils.formatDate;
import static org.elasticsearch.watcher.support.WatcherDateTimeUtils.formatDate;
import static org.elasticsearch.watcher.test.WatcherTestUtils.EMPTY_PAYLOAD;
import static org.elasticsearch.watcher.test.WatcherTestUtils.mockExecutionContext;
import static org.hamcrest.CoreMatchers.nullValue;

View File

@ -0,0 +1,88 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.watcher.support;
import com.carrotsearch.randomizedtesting.annotations.Repeat;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.watcher.test.WatcherTestUtils.xContentParser;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
/**
*
*/
public class WatcherDateTimeUtilsTests extends ElasticsearchTestCase {
@Test @Repeat(iterations = 20)
public void testParseTimeValue_Numeric() throws Exception {
TimeValue value = new TimeValue(randomInt(100), randomFrom(TimeUnit.values()));
XContentParser parser = xContentParser(jsonBuilder().startObject().field("value", value.getMillis()).endObject());
parser.nextToken(); // start object
parser.nextToken(); // field name
parser.nextToken(); // value
TimeValue parsed = WatcherDateTimeUtils.parseTimeValue(parser, null);
assertThat(parsed, notNullValue());
assertThat(parsed.millis(), is(value.millis()));
}
@Test @Repeat(iterations = 10)
public void testParseTimeValue_String() throws Exception {
ImmutableMap<String, TimeValue> values = ImmutableMap.<String, TimeValue>builder()
.put("5s", TimeValue.timeValueSeconds(5))
.put("5m", TimeValue.timeValueMinutes(5))
.put("5h", TimeValue.timeValueHours(5))
.put("5", TimeValue.timeValueMillis(5))
.build();
String key = randomFrom(values.keySet().toArray(new String[values.size()]));
XContentParser parser = xContentParser(jsonBuilder().startObject().field("value", key).endObject());
parser.nextToken(); // start object
parser.nextToken(); // field name
parser.nextToken(); // value
TimeValue parsed = WatcherDateTimeUtils.parseTimeValue(parser, null);
assertThat(parsed, notNullValue());
assertThat(parsed.millis(), is(values.get(key).millis()));
}
@Test
public void testParseTimeValue_Null() throws Exception {
XContentParser parser = xContentParser(jsonBuilder().startObject().nullField("value").endObject());
parser.nextToken(); // start object
parser.nextToken(); // field name
parser.nextToken(); // value
TimeValue parsed = WatcherDateTimeUtils.parseTimeValue(parser, null);
assertThat(parsed, nullValue());
}
@Test
public void testParseTimeValue_Null_DefaultValue() throws Exception {
XContentParser parser = xContentParser(jsonBuilder().startObject().nullField("value").endObject());
parser.nextToken(); // start object
parser.nextToken(); // field name
parser.nextToken(); // value
TimeValue defaultValue = new TimeValue(randomInt(100), randomFrom(TimeUnit.values()));
TimeValue parsed = WatcherDateTimeUtils.parseTimeValue(parser, defaultValue);
assertThat(parsed, notNullValue());
assertThat(parsed, sameInstance(defaultValue));
}
}

View File

@ -27,7 +27,7 @@ import java.io.IOException;
import java.util.*;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.watcher.support.WatcherDateUtils.formatDate;
import static org.elasticsearch.watcher.support.WatcherDateTimeUtils.formatDate;
import static org.elasticsearch.watcher.support.WatcherUtils.DEFAULT_INDICES_OPTIONS;
import static org.elasticsearch.watcher.support.WatcherUtils.flattenModel;
import static org.elasticsearch.watcher.test.WatcherTestUtils.getRandomSupportedSearchType;

View File

@ -16,6 +16,7 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
@ -89,6 +90,10 @@ public final class WatcherTestUtils {
private WatcherTestUtils() {
}
public static XContentParser xContentParser(XContentBuilder builder) throws IOException {
return builder.contentType().xContent().createParser(builder.bytes());
}
public static SearchRequest newInputSearchRequest(String... indices) {
SearchRequest request = new SearchRequest(indices);
request.indicesOptions(WatcherUtils.DEFAULT_INDICES_OPTIONS);

View File

@ -57,7 +57,7 @@ import static org.elasticsearch.index.query.FilterBuilders.*;
import static org.elasticsearch.index.query.QueryBuilders.*;
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.SUITE;
import static org.elasticsearch.watcher.support.WatcherDateUtils.parseDate;
import static org.elasticsearch.watcher.support.WatcherDateTimeUtils.parseDate;
import static org.elasticsearch.watcher.test.WatcherTestUtils.*;
import static org.hamcrest.Matchers.*;