mirror of https://github.com/apache/druid.git
serde tests + equals/hashCode fixes for extraction functions
This commit is contained in:
parent
d3f5bddc5c
commit
e01ed16030
|
@ -20,6 +20,7 @@ package io.druid.query.extraction;
|
|||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import com.metamx.common.StringUtils;
|
||||
import org.mozilla.javascript.Context;
|
||||
|
@ -67,6 +68,8 @@ public class JavascriptExtractionFn implements ExtractionFn
|
|||
@JsonProperty("function") String function
|
||||
)
|
||||
{
|
||||
Preconditions.checkNotNull(function, "function must not be null");
|
||||
|
||||
this.function = function;
|
||||
this.fn = compile(function);
|
||||
}
|
||||
|
@ -118,4 +121,29 @@ public class JavascriptExtractionFn implements ExtractionFn
|
|||
"function='" + function + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JavascriptExtractionFn that = (JavascriptExtractionFn) o;
|
||||
|
||||
if (!function.equals(that.function)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return function.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package io.druid.query.extraction;
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.metamx.common.StringUtils;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -39,6 +40,8 @@ public class MatchingDimExtractionFn extends DimExtractionFn
|
|||
@JsonProperty("expr") String expr
|
||||
)
|
||||
{
|
||||
Preconditions.checkNotNull(expr, "expr must not be null");
|
||||
|
||||
this.expr = expr;
|
||||
this.pattern = Pattern.compile(expr);
|
||||
}
|
||||
|
@ -78,4 +81,29 @@ public class MatchingDimExtractionFn extends DimExtractionFn
|
|||
{
|
||||
return String.format("regex_matches(%s)", expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MatchingDimExtractionFn that = (MatchingDimExtractionFn) o;
|
||||
|
||||
if (!expr.equals(that.expr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return expr.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package io.druid.query.extraction;
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.metamx.common.StringUtils;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -39,6 +40,8 @@ public class RegexDimExtractionFn extends DimExtractionFn
|
|||
@JsonProperty("expr") String expr
|
||||
)
|
||||
{
|
||||
Preconditions.checkNotNull(expr, "expr must not be null");
|
||||
|
||||
this.expr = expr;
|
||||
this.pattern = Pattern.compile(expr);
|
||||
}
|
||||
|
@ -77,4 +80,29 @@ public class RegexDimExtractionFn extends DimExtractionFn
|
|||
{
|
||||
return String.format("regex(%s)", expr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RegexDimExtractionFn that = (RegexDimExtractionFn) o;
|
||||
|
||||
if (!expr.equals(that.expr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return expr.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package io.druid.query.extraction;
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.druid.query.search.search.SearchQuerySpec;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -36,6 +37,8 @@ public class SearchQuerySpecDimExtractionFn extends DimExtractionFn
|
|||
@JsonProperty("query") SearchQuerySpec searchQuerySpec
|
||||
)
|
||||
{
|
||||
Preconditions.checkNotNull(searchQuerySpec, "search query must not be null");
|
||||
|
||||
this.searchQuerySpec = searchQuerySpec;
|
||||
}
|
||||
|
||||
|
@ -74,4 +77,29 @@ public class SearchQuerySpecDimExtractionFn extends DimExtractionFn
|
|||
"searchQuerySpec=" + searchQuerySpec +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SearchQuerySpecDimExtractionFn that = (SearchQuerySpecDimExtractionFn) o;
|
||||
|
||||
if (!searchQuerySpec.equals(that.searchQuerySpec)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return searchQuerySpec.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package io.druid.query.extraction;
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.ibm.icu.text.SimpleDateFormat;
|
||||
import com.metamx.common.StringUtils;
|
||||
|
||||
|
@ -43,6 +44,9 @@ public class TimeDimExtractionFn extends DimExtractionFn
|
|||
@JsonProperty("resultFormat") String resultFormat
|
||||
)
|
||||
{
|
||||
Preconditions.checkNotNull(timeFormat, "timeFormat must not be null");
|
||||
Preconditions.checkNotNull(resultFormat, "resultFormat must not be null");
|
||||
|
||||
this.timeFormat = timeFormat;
|
||||
this.timeFormatter = new SimpleDateFormat(timeFormat);
|
||||
this.timeFormatter.setLenient(true);
|
||||
|
@ -100,4 +104,34 @@ public class TimeDimExtractionFn extends DimExtractionFn
|
|||
", resultFormat='" + resultFormat + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TimeDimExtractionFn that = (TimeDimExtractionFn) o;
|
||||
|
||||
if (!resultFormat.equals(that.resultFormat)) {
|
||||
return false;
|
||||
}
|
||||
if (!timeFormat.equals(that.timeFormat)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = timeFormat.hashCode();
|
||||
result = 31 * result + resultFormat.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,4 +110,38 @@ public class TimeFormatExtractionFn implements ExtractionFn
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TimeFormatExtractionFn that = (TimeFormatExtractionFn) o;
|
||||
|
||||
if (locale != null ? !locale.equals(that.locale) : that.locale != null) {
|
||||
return false;
|
||||
}
|
||||
if (!pattern.equals(that.pattern)) {
|
||||
return false;
|
||||
}
|
||||
if (tz != null ? !tz.equals(that.tz) : that.tz != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = tz != null ? tz.hashCode() : 0;
|
||||
result = 31 * result + pattern.hashCode();
|
||||
result = 31 * result + (locale != null ? locale.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.dimension;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.druid.jackson.DefaultObjectMapper;
|
||||
import io.druid.query.extraction.MatchingDimExtractionFn;
|
||||
import io.druid.query.extraction.RegexDimExtractionFn;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ExtractionDimensionSpecTest
|
||||
{
|
||||
@Test
|
||||
public void testSerde() throws Exception
|
||||
{
|
||||
final ObjectMapper objectMapper = new DefaultObjectMapper();
|
||||
|
||||
final String oldJson = "{\n"
|
||||
+ " \"type\": \"extraction\",\n"
|
||||
+ " \"outputName\": \"first3Letters\",\n"
|
||||
+ " \"dimension\": \"myDim\","
|
||||
+ " \"extractionFn\": {\n"
|
||||
+ " \"type\": \"regex\",\n"
|
||||
+ " \"expr\": \"(...).*\"\n"
|
||||
+ " }\n"
|
||||
+ "}";
|
||||
|
||||
final ExtractionDimensionSpec extractionDimensionSpec = (ExtractionDimensionSpec) objectMapper.readValue(oldJson, DimensionSpec.class);
|
||||
|
||||
Assert.assertEquals("first3Letters", extractionDimensionSpec.getOutputName());
|
||||
Assert.assertEquals("myDim", extractionDimensionSpec.getDimension());
|
||||
Assert.assertNotNull(extractionDimensionSpec.getExtractionFn());
|
||||
Assert.assertTrue(extractionDimensionSpec.getExtractionFn() instanceof RegexDimExtractionFn);
|
||||
|
||||
Assert.assertEquals(
|
||||
extractionDimensionSpec,
|
||||
objectMapper.readValue(
|
||||
objectMapper.writeValueAsBytes(extractionDimensionSpec),
|
||||
DimensionSpec.class
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerdeBackwardsCompatibility() throws Exception
|
||||
{
|
||||
final ObjectMapper objectMapper = new DefaultObjectMapper();
|
||||
|
||||
final String oldJson = "{\n"
|
||||
+ " \"type\": \"extraction\",\n"
|
||||
+ " \"outputName\": \"first3Letters\",\n"
|
||||
+ " \"dimension\": \"myDim\","
|
||||
+ " \"dimExtractionFn\": {\n"
|
||||
+ " \"type\": \"regex\",\n"
|
||||
+ " \"expr\": \"(...).*\"\n"
|
||||
+ " }\n"
|
||||
+ "}";
|
||||
|
||||
final ExtractionDimensionSpec extractionDimensionSpec = (ExtractionDimensionSpec) objectMapper.readValue(oldJson, DimensionSpec.class);
|
||||
|
||||
Assert.assertEquals("first3Letters", extractionDimensionSpec.getOutputName());
|
||||
Assert.assertEquals("myDim", extractionDimensionSpec.getDimension());
|
||||
Assert.assertNotNull(extractionDimensionSpec.getExtractionFn());
|
||||
Assert.assertTrue(extractionDimensionSpec.getExtractionFn() instanceof RegexDimExtractionFn);
|
||||
|
||||
Assert.assertEquals(
|
||||
extractionDimensionSpec,
|
||||
objectMapper.readValue(
|
||||
objectMapper.writeValueAsBytes(extractionDimensionSpec),
|
||||
DimensionSpec.class
|
||||
)
|
||||
);
|
||||
|
||||
// new trumps old
|
||||
final String oldAndNewJson = "{\n"
|
||||
+ " \"type\": \"extraction\",\n"
|
||||
+ " \"outputName\": \"first3Letters\",\n"
|
||||
+ " \"dimension\": \"myDim\","
|
||||
+ " \"extractionFn\": {\n"
|
||||
+ " \"type\": \"partial\",\n"
|
||||
+ " \"expr\": \"(...).*\"\n"
|
||||
+ " },\n"
|
||||
+ " \"dimExtractionFn\": {\n"
|
||||
+ " \"type\": \"regex\",\n"
|
||||
+ " \"expr\": \"(...).*\"\n"
|
||||
+ " }\n"
|
||||
+ "}";
|
||||
|
||||
Assert.assertTrue(
|
||||
objectMapper.readValue(oldAndNewJson, DimensionSpec.class)
|
||||
.getExtractionFn() instanceof MatchingDimExtractionFn
|
||||
);
|
||||
}
|
||||
}
|
|
@ -87,12 +87,35 @@ public class TimeFormatExtractionFnTest
|
|||
}
|
||||
|
||||
public void testSerde(TimeFormatExtractionFn fn, String format, DateTimeZone tz, String locale) throws Exception {
|
||||
ObjectMapper objectMapper = new DefaultObjectMapper();
|
||||
String json = objectMapper.writeValueAsString(fn);
|
||||
final ObjectMapper objectMapper = new DefaultObjectMapper();
|
||||
final String json = objectMapper.writeValueAsString(fn);
|
||||
TimeFormatExtractionFn deserialized = objectMapper.readValue(json, TimeFormatExtractionFn.class);
|
||||
|
||||
Assert.assertEquals(format, deserialized.getFormat());
|
||||
Assert.assertEquals(tz, deserialized.getTimeZone());
|
||||
Assert.assertEquals(locale, deserialized.getLocale());
|
||||
|
||||
Assert.assertEquals(fn, deserialized);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerdeFromJson() throws Exception
|
||||
{
|
||||
final ObjectMapper objectMapper = new DefaultObjectMapper();
|
||||
final String json = "{ \"type\" : \"timeFormat\", \"format\" : \"HH\" }";
|
||||
TimeFormatExtractionFn extractionFn = (TimeFormatExtractionFn) objectMapper.readValue(json, ExtractionFn.class);
|
||||
|
||||
Assert.assertEquals("HH", extractionFn.getFormat());
|
||||
Assert.assertEquals(null, extractionFn.getLocale());
|
||||
Assert.assertEquals(null, extractionFn.getTimeZone());
|
||||
|
||||
// round trip
|
||||
Assert.assertEquals(
|
||||
extractionFn,
|
||||
objectMapper.readValue(
|
||||
objectMapper.writeValueAsBytes(extractionFn),
|
||||
ExtractionFn.class
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
|
||||
package io.druid.query.extraction.extraction;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Lists;
|
||||
import io.druid.jackson.DefaultObjectMapper;
|
||||
import io.druid.query.extraction.ExtractionFn;
|
||||
import io.druid.query.extraction.JavascriptExtractionFn;
|
||||
import org.joda.time.DateTime;
|
||||
|
@ -307,4 +309,23 @@ public class JavascriptExtractionFnTest
|
|||
Assert.assertEquals(it.next(), res);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerde() throws Exception
|
||||
{
|
||||
final ObjectMapper objectMapper = new DefaultObjectMapper();
|
||||
final String json = "{ \"type\" : \"javascript\", \"function\" : \"function(str) { return str.substring(0,3); }\" }";
|
||||
JavascriptExtractionFn extractionFn = (JavascriptExtractionFn) objectMapper.readValue(json, ExtractionFn.class);
|
||||
|
||||
Assert.assertEquals("function(str) { return str.substring(0,3); }", extractionFn.getFunction());
|
||||
|
||||
// round trip
|
||||
Assert.assertEquals(
|
||||
extractionFn,
|
||||
objectMapper.readValue(
|
||||
objectMapper.writeValueAsBytes(extractionFn),
|
||||
ExtractionFn.class
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
|
||||
package io.druid.query.extraction.extraction;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.Sets;
|
||||
import io.druid.jackson.DefaultObjectMapper;
|
||||
import io.druid.query.extraction.ExtractionFn;
|
||||
import io.druid.query.extraction.MatchingDimExtractionFn;
|
||||
import org.junit.Assert;
|
||||
|
@ -64,4 +66,23 @@ public class MatchingDimExtractionFnTest
|
|||
Assert.assertTrue(expected.contains(str));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerde() throws Exception
|
||||
{
|
||||
final ObjectMapper objectMapper = new DefaultObjectMapper();
|
||||
final String json = "{ \"type\" : \"partial\", \"expr\" : \".(...)?\" }";
|
||||
MatchingDimExtractionFn extractionFn = (MatchingDimExtractionFn) objectMapper.readValue(json, ExtractionFn.class);
|
||||
|
||||
Assert.assertEquals(".(...)?", extractionFn.getExpr());
|
||||
|
||||
// round trip
|
||||
Assert.assertEquals(
|
||||
extractionFn,
|
||||
objectMapper.readValue(
|
||||
objectMapper.writeValueAsBytes(extractionFn),
|
||||
ExtractionFn.class
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
|
||||
package io.druid.query.extraction.extraction;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.Sets;
|
||||
import io.druid.jackson.DefaultObjectMapper;
|
||||
import io.druid.query.extraction.ExtractionFn;
|
||||
import io.druid.query.extraction.RegexDimExtractionFn;
|
||||
import org.junit.Assert;
|
||||
|
@ -99,4 +101,23 @@ public class RegexDimExtractionFnTest
|
|||
Assert.assertTrue(extracted.contains("b"));
|
||||
Assert.assertTrue(extracted.contains("c"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerde() throws Exception
|
||||
{
|
||||
final ObjectMapper objectMapper = new DefaultObjectMapper();
|
||||
final String json = "{ \"type\" : \"regex\", \"expr\" : \".(...)?\" }";
|
||||
RegexDimExtractionFn extractionFn = (RegexDimExtractionFn) objectMapper.readValue(json, ExtractionFn.class);
|
||||
|
||||
Assert.assertEquals(".(...)?", extractionFn.getExpr());
|
||||
|
||||
// round trip
|
||||
Assert.assertEquals(
|
||||
extractionFn,
|
||||
objectMapper.readValue(
|
||||
objectMapper.writeValueAsBytes(extractionFn),
|
||||
ExtractionFn.class
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,11 @@
|
|||
|
||||
package io.druid.query.extraction.extraction;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.Sets;
|
||||
import io.druid.jackson.DefaultObjectMapper;
|
||||
import io.druid.query.extraction.ExtractionFn;
|
||||
import io.druid.query.extraction.MatchingDimExtractionFn;
|
||||
import io.druid.query.extraction.TimeDimExtractionFn;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -70,4 +73,24 @@ public class TimeDimExtractionFnTest
|
|||
Assert.assertTrue(quarters.contains("Q2/2012"));
|
||||
Assert.assertTrue(quarters.contains("Q4/2012"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerde() throws Exception
|
||||
{
|
||||
final ObjectMapper objectMapper = new DefaultObjectMapper();
|
||||
final String json = "{ \"type\" : \"time\", \"timeFormat\" : \"MM/dd/yyyy\", \"resultFormat\" : \"QQQ/yyyy\" }";
|
||||
TimeDimExtractionFn extractionFn = (TimeDimExtractionFn) objectMapper.readValue(json, ExtractionFn.class);
|
||||
|
||||
Assert.assertEquals("MM/dd/yyyy", extractionFn.getTimeFormat());
|
||||
Assert.assertEquals("QQQ/yyyy", extractionFn.getResultFormat());
|
||||
|
||||
// round trip
|
||||
Assert.assertEquals(
|
||||
extractionFn,
|
||||
objectMapper.readValue(
|
||||
objectMapper.writeValueAsBytes(extractionFn),
|
||||
ExtractionFn.class
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue