From 8f1c7cc2ab7f354570f277cb8385a4b791779d06 Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Fri, 28 Sep 2018 08:54:50 +0100 Subject: [PATCH] Jackson serialization for facets --- .../refine/browsing/DecoratedValue.java | 4 + .../refine/browsing/facets/FacetConfig.java | 8 + .../refine/browsing/facets/ListFacet.java | 130 ++++++++++++++- .../browsing/facets/NominalFacetChoice.java | 5 + .../refine/browsing/facets/RangeFacet.java | 129 ++++++++++++++- .../browsing/facets/ScatterplotFacet.java | 150 ++++++++++++++++++ .../browsing/facets/TextSearchFacet.java | 47 +++++- .../browsing/facets/TimeRangeFacet.java | 121 +++++++++++++- .../refine/util/SerializationFilters.java | 4 +- .../browsing/facets/TimeRangeFacetTests.java | 10 +- .../google/refine/tests/util/TestUtils.java | 1 - 11 files changed, 589 insertions(+), 20 deletions(-) diff --git a/main/src/com/google/refine/browsing/DecoratedValue.java b/main/src/com/google/refine/browsing/DecoratedValue.java index 90bde0930..31c617a97 100644 --- a/main/src/com/google/refine/browsing/DecoratedValue.java +++ b/main/src/com/google/refine/browsing/DecoratedValue.java @@ -39,6 +39,8 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.util.StringUtils; @@ -50,7 +52,9 @@ import com.google.refine.util.StringUtils; * Facet choices that are presented to the user as text are stored as decorated values. */ public class DecoratedValue implements Jsonizable { + @JsonProperty("v") final public Object value; + @JsonProperty("l") final public String label; public DecoratedValue(Object value, String label) { diff --git a/main/src/com/google/refine/browsing/facets/FacetConfig.java b/main/src/com/google/refine/browsing/facets/FacetConfig.java index c6786749e..3971b66d4 100644 --- a/main/src/com/google/refine/browsing/facets/FacetConfig.java +++ b/main/src/com/google/refine/browsing/facets/FacetConfig.java @@ -2,6 +2,8 @@ package com.google.refine.browsing.facets; import org.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.model.Project; @@ -28,4 +30,10 @@ public interface FacetConfig extends Jsonizable { * @return a computed facet on the given project. */ public Facet apply(Project project); + + /** + * The facet type as stored in json. + */ + @JsonProperty("type") + public String getJsonType(); } diff --git a/main/src/com/google/refine/browsing/facets/ListFacet.java b/main/src/com/google/refine/browsing/facets/ListFacet.java index d5cdfa45f..780e73f80 100644 --- a/main/src/com/google/refine/browsing/facets/ListFacet.java +++ b/main/src/com/google/refine/browsing/facets/ListFacet.java @@ -36,12 +36,20 @@ package com.google.refine.browsing.facets; import java.util.LinkedList; import java.util.List; import java.util.Properties; +import java.util.stream.Collectors; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + import com.google.refine.ProjectManager; import com.google.refine.browsing.DecoratedValue; import com.google.refine.browsing.FilteredRecords; @@ -60,24 +68,51 @@ import com.google.refine.model.Project; import com.google.refine.util.JSONUtilities; public class ListFacet implements Facet { + public static final String ERR_TOO_MANY_CHOICES = "Too many choices"; + + /** + * Wrapper to respect the serialization format + */ + public static class DecoratedValueWrapper { + @JsonProperty("v") + public final DecoratedValue value; + @JsonCreator + public DecoratedValueWrapper( + @JsonProperty("v") DecoratedValue value) { + this.value = value; + } + } + /* * Configuration */ public static class ListFacetConfig implements FacetConfig { + @JsonProperty("name") public String name; + @JsonProperty("expression") public String expression; + @JsonProperty("columnName") public String columnName; + @JsonProperty("invert") public boolean invert; // If true, then facet won't show the blank and error choices + @JsonProperty("omitBlank") public boolean omitBlank; + @JsonProperty("omitError") public boolean omitError; + @JsonIgnore public List selection = new LinkedList<>(); + @JsonProperty("selectNumber") public boolean selectNumber; + @JsonProperty("selectDateTime") public boolean selectDateTime; + @JsonProperty("selectBoolean") public boolean selectBoolean; + @JsonProperty("selectBlank") public boolean selectBlank; + @JsonProperty("selectError") public boolean selectError; @Override @@ -107,6 +142,13 @@ public class ListFacet implements Facet { writer.endObject(); } + @JsonProperty("selection") + public List getWrappedSelection() { + return selection.stream() + .map(e -> new DecoratedValueWrapper(e)) + .collect(Collectors.toList()); + } + @Override public void initializeFromJSON(JSONObject o) { name = o.getString("name"); @@ -143,6 +185,27 @@ public class ListFacet implements Facet { facet.initializeFromConfig(this, project); return facet; } + + @Override + public String getJsonType() { + return "list"; + } + } + + /** + * Wrapper class for choice counts and selection status for blank and error + */ + public static class OtherChoice { + @JsonProperty("s") + boolean selected; + @JsonProperty("c") + int count; + public OtherChoice( + @JsonProperty("s") boolean selected, + @JsonProperty("c") int count) { + this.selected = selected; + this.count = count; + } } ListFacetConfig _config = new ListFacetConfig(); @@ -166,6 +229,69 @@ public class ListFacet implements Facet { public ListFacet() { } + + @JsonProperty("name") + public String getName() { + return _config.name; + } + + @JsonProperty("columnName") + public String getColumnName() { + return _config.columnName; + } + + @JsonProperty("expression") + public String getExpression() { + return _config.expression; + } + + @JsonProperty("invert") + public boolean getInvert() { + return _config.invert; + } + + @JsonProperty("error") + @JsonInclude(Include.NON_NULL) + public String getError() { + if (_errorMessage == null && _choices.size() > getLimit()) { + return ERR_TOO_MANY_CHOICES; + } + return _errorMessage; + } + + @JsonProperty("choiceCount") + @JsonInclude(Include.NON_NULL) + public Integer getChoiceCount() { + if (_errorMessage == null && _choices.size() > getLimit()) + return _choices.size(); + return null; + } + + @JsonProperty("choices") + @JsonInclude(Include.NON_NULL) + public List getChoices() { + if (getError() == null) + return _choices; + return null; + } + + @JsonProperty("blankChoice") + @JsonInclude(Include.NON_NULL) + public OtherChoice getBlankChoice() { + if (getError() == null && !_config.omitBlank && (_config.selectBlank || _blankCount > 0)) { + return new OtherChoice(_config.selectBlank, _blankCount); + } + return null; + } + + @JsonProperty("errorChoice") + @JsonInclude(Include.NON_NULL) + public OtherChoice getErrorChoice() { + if (getError() == null && !_config.omitError && (_config.selectError || _errorCount > 0)) { + return new OtherChoice(_config.selectError, _errorCount); + } + return null; + } @Override public void write(JSONWriter writer, Properties options) @@ -180,7 +306,7 @@ public class ListFacet implements Facet { if (_errorMessage != null) { writer.key("error"); writer.value(_errorMessage); } else if (_choices.size() > getLimit()) { - writer.key("error"); writer.value("Too many choices"); + writer.key("error"); writer.value(ERR_TOO_MANY_CHOICES); writer.key("choiceCount"); writer.value(_choices.size()); } else { writer.key("choices"); writer.array(); @@ -359,4 +485,4 @@ public class ListFacet implements Facet { } return a; } -} \ No newline at end of file +} diff --git a/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java b/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java index 96d5674d0..ad59ff61a 100644 --- a/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java +++ b/main/src/com/google/refine/browsing/facets/NominalFacetChoice.java @@ -38,6 +38,8 @@ import java.util.Properties; import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.Jsonizable; import com.google.refine.browsing.DecoratedValue; @@ -46,8 +48,11 @@ import com.google.refine.browsing.DecoratedValue; * and a flag of whether it has been selected. */ public class NominalFacetChoice implements Jsonizable { + @JsonProperty("v") final public DecoratedValue decoratedValue; + @JsonProperty("c") public int count; + @JsonProperty("s") public boolean selected; public NominalFacetChoice(DecoratedValue decoratedValue) { diff --git a/main/src/com/google/refine/browsing/facets/RangeFacet.java b/main/src/com/google/refine/browsing/facets/RangeFacet.java index 662253697..48621873b 100644 --- a/main/src/com/google/refine/browsing/facets/RangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/RangeFacet.java @@ -39,6 +39,11 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; @@ -59,22 +64,35 @@ import com.google.refine.model.Project; import com.google.refine.util.JSONUtilities; public class RangeFacet implements Facet { + + public static final String ERR_NO_NUMERIC_VALUE_PRESENT = "No numeric value present."; + /* * Configuration, from the client side */ public static class RangeFacetConfig implements FacetConfig { + @JsonProperty("name") protected String _name; // name of facet + @JsonProperty("expression") protected String _expression; // expression to compute numeric value(s) per row + @JsonProperty("columnName") protected String _columnName; // column to base expression on, if any + @JsonProperty(FROM) protected double _from; // the numeric selection + @JsonProperty(TO) protected double _to; + @JsonProperty("selectNumeric") protected boolean _selectNumeric; // whether the numeric selection applies, default true + @JsonProperty("selectNonNumeric") protected boolean _selectNonNumeric; + @JsonProperty("selectBlank") protected boolean _selectBlank; + @JsonProperty("selectError") protected boolean _selectError; + @JsonIgnore protected boolean _selected; // false if we're certain that all rows will match // and there isn't any filtering to do @@ -122,6 +140,11 @@ public class RangeFacet implements Facet { facet.initializeFromConfig(this, project); return facet; } + + @Override + public String getJsonType() { + return "range"; + } } RangeFacetConfig _config = new RangeFacetConfig(); @@ -141,16 +164,24 @@ public class RangeFacet implements Facet { protected int[] _baseBins; protected int[] _bins; + @JsonProperty("baseNumericCount") protected int _baseNumericCount; + @JsonProperty("baseNonNumericCount") protected int _baseNonNumericCount; + @JsonProperty("baseBlankCount") protected int _baseBlankCount; + @JsonProperty("baseErrorCount") protected int _baseErrorCount; + @JsonProperty("numericCount") protected int _numericCount; + @JsonProperty("nonNumericCount") protected int _nonNumericCount; + @JsonProperty("blankCount") protected int _blankCount; + @JsonProperty("errorCount") protected int _errorCount; - + public RangeFacet() { } @@ -159,6 +190,100 @@ public class RangeFacet implements Facet { protected static final String TO = "to"; protected static final String FROM = "from"; + @JsonProperty("name") + public String getName() { + return _config._name; + } + + @JsonProperty("expression") + public String getExpression() { + return _config._expression; + } + + @JsonProperty("columnName") + public String getColumnName() { + return _config._columnName; + } + + @JsonProperty("error") + @JsonInclude(Include.NON_NULL) + public String getError() { + if (_errorMessage != null) { + return _errorMessage; + } else if (!isFiniteRange()) { + return ERR_NO_NUMERIC_VALUE_PRESENT; + } + return null; + } + + @JsonIgnore + public boolean isFiniteRange() { + return !Double.isInfinite(_min) && !Double.isInfinite(_max); + } + + @JsonProperty(MIN) + @JsonInclude(Include.NON_NULL) + public Double getMin() { + if (getError() == null) { + return _min; + } + return null; + } + + @JsonProperty(MAX) + @JsonInclude(Include.NON_NULL) + public Double getMax() { + if (getError() == null) { + return _max; + } + return null; + } + + @JsonProperty("step") + @JsonInclude(Include.NON_NULL) + public Double getStep() { + if (getError() == null) { + return _step; + } + return null; + } + + @JsonProperty("bins") + @JsonInclude(Include.NON_NULL) + public int[] getBins() { + if (getError() == null) { + return _bins; + } + return null; + } + + @JsonProperty("baseBins") + @JsonInclude(Include.NON_NULL) + public int[] getBaseBins() { + if (getError() == null) { + return _baseBins; + } + return null; + } + + @JsonProperty(FROM) + @JsonInclude(Include.NON_NULL) + public Double getFrom() { + if (getError() == null) { + return _config._from; + } + return null; + } + + @JsonProperty(TO) + @JsonInclude(Include.NON_NULL) + public Double getTo() { + if (getError() == null) { + return _config._to; + } + return null; + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { @@ -191,7 +316,7 @@ public class RangeFacet implements Facet { writer.key(FROM); writer.value(_config._from); writer.key(TO); writer.value(_config._to); } else { - writer.key("error"); writer.value("No numeric value present."); + writer.key("error"); writer.value(ERR_NO_NUMERIC_VALUE_PRESENT); } writer.key("baseNumericCount"); writer.value(_baseNumericCount); diff --git a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java index 3a6862d59..3945251d7 100644 --- a/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java +++ b/main/src/com/google/refine/browsing/facets/ScatterplotFacet.java @@ -51,6 +51,11 @@ import org.json.JSONWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; @@ -80,33 +85,61 @@ public class ScatterplotFacet implements Facet { * Configuration, from the client side */ public static class ScatterplotFacetConfig implements FacetConfig { + @JsonProperty("name") protected String name; // name of facet + @JsonProperty(X_EXPRESSION) protected String expression_x; // expression to compute the x numeric value(s) per row + @JsonProperty(Y_EXPRESSION) protected String expression_y; // expression to compute the y numeric value(s) per row + @JsonProperty(X_COLUMN_NAME) protected String columnName_x; // column to base the x expression on, if any + @JsonProperty(Y_COLUMN_NAME) protected String columnName_y; // column to base the y expression on, if any + @JsonProperty(SIZE) protected int size; + @JsonIgnore protected int dim_x; + @JsonIgnore protected int dim_y; + @JsonIgnore protected String rotation_str; + @JsonIgnore protected int rotation; + @JsonIgnore protected double l; + @JsonProperty(DOT) protected double dot; + @JsonIgnore protected String color_str; + @JsonIgnore protected Color color; + @JsonProperty(FROM_X) protected double from_x; // the numeric selection for the x axis, from 0 to 1 + @JsonProperty(TO_X) protected double to_x; + @JsonProperty(FROM_Y) protected double from_y; // the numeric selection for the y axis, from 0 to 1 + @JsonProperty(TO_Y) protected double to_y; protected boolean selected; // false if we're certain that all rows will match // and there isn't any filtering to do + @JsonProperty(DIM_X) + public String getDimX() { + return dim_x == LIN ? "lin" : "log"; + } + + @JsonProperty(DIM_Y) + public String getDimY() { + return dim_y == LIN ? "lin" : "log"; + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { @@ -193,6 +226,11 @@ public class ScatterplotFacet implements Facet { return NO_ROTATION; } } + + @Override + public String getJsonType() { + return "scatterplot"; + } } ScatterplotFacetConfig config; @@ -255,6 +293,118 @@ public class ScatterplotFacet implements Facet { } } + @JsonProperty(NAME) + public String getName() { + return config.name; + } + + @JsonProperty(X_COLUMN_NAME) + public String getXColumnName() { + return config.columnName_x; + } + + @JsonProperty(X_EXPRESSION) + public String getXExpression() { + return config.expression_x; + } + + @JsonProperty(Y_COLUMN_NAME) + public String getYColumnName() { + return config.columnName_y; + } + + @JsonProperty(Y_EXPRESSION) + public String getYExpression() { + return config.expression_y; + } + + @JsonProperty(SIZE) + public int getSize() { + return config.size; + } + + @JsonProperty(DIM_X) + public int getDimX() { + return config.dim_x; + } + + @JsonProperty(DIM_Y) + public int getDimY() { + return config.dim_y; + } + + @JsonProperty(DOT) + public double getDot() { + return config.dot; + } + + @JsonProperty(ROTATION) + public double getRotation() { + return config.rotation; + } + + @JsonProperty(COLOR) + public String getColorString() { + return config.color_str; + } + + @JsonProperty(IMAGE) + @JsonInclude(Include.NON_NULL) + public String getImage() { + if(IMAGE_URI) { + return image; + } + return null; + } + + @JsonProperty(ERROR_X) + @JsonInclude(Include.NON_NULL) + public String getErrorX() { + return errorMessage_x; + } + + @JsonProperty(FROM_X) + @JsonInclude(Include.NON_NULL) + public Double getFromX() { + if (errorMessage_x == null && !Double.isInfinite(min_x) && !Double.isInfinite(max_x)) { + return config.from_x; + } + return null; + } + + @JsonProperty(TO_X) + @JsonInclude(Include.NON_NULL) + public Double getToX() { + if (errorMessage_x == null && !Double.isInfinite(min_x) && !Double.isInfinite(max_x)) { + return config.to_x; + } + return null; + } + + @JsonProperty(ERROR_Y) + @JsonInclude(Include.NON_NULL) + public String getErrorY() { + return errorMessage_y; + } + + @JsonProperty(FROM_Y) + @JsonInclude(Include.NON_NULL) + public Double getFromY() { + if (errorMessage_y == null && !Double.isInfinite(min_y) && !Double.isInfinite(max_y)) { + return config.from_y; + } + return null; + } + + @JsonProperty(TO_Y) + @JsonInclude(Include.NON_NULL) + public Double getToY() { + if (errorMessage_y == null && !Double.isInfinite(min_y) && !Double.isInfinite(max_y)) { + return config.to_y; + } + return null; + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { diff --git a/main/src/com/google/refine/browsing/facets/TextSearchFacet.java b/main/src/com/google/refine/browsing/facets/TextSearchFacet.java index 96f97813b..c627f8258 100644 --- a/main/src/com/google/refine/browsing/facets/TextSearchFacet.java +++ b/main/src/com/google/refine/browsing/facets/TextSearchFacet.java @@ -40,6 +40,8 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; @@ -58,11 +60,17 @@ public class TextSearchFacet implements Facet { * Configuration */ public static class TextSearchFacetConfig implements FacetConfig { + @JsonProperty("name") protected String _name; + @JsonProperty("columnName") protected String _columnName; + @JsonProperty("query") protected String _query = null; + @JsonProperty("mode") protected String _mode; + @JsonProperty("caseSensitive") protected boolean _caseSensitive; + @JsonProperty("invert") protected boolean _invert; @Override @@ -76,7 +84,7 @@ public class TextSearchFacet implements Facet { writer.key("caseSensitive"); writer.value(_caseSensitive); writer.key("invert"); writer.value(_invert); writer.key("type"); writer.value("text"); - writer.endObject(); + writer.endObject(); } @Override @@ -97,6 +105,11 @@ public class TextSearchFacet implements Facet { } _invert = o.has("invert") && o.getBoolean("invert"); } + + @Override + public String getJsonType() { + return "text"; + } } TextSearchFacetConfig _config = new TextSearchFacetConfig(); @@ -109,7 +122,37 @@ public class TextSearchFacet implements Facet { public TextSearchFacet() { } - + + @JsonProperty("name") + public String getName() { + return _config._name; + } + + @JsonProperty("columnName") + public String getColumnName() { + return _config._columnName; + } + + @JsonProperty("query") + public String getQuery() { + return _config._query; + } + + @JsonProperty("mode") + public String getMode() { + return _config._mode; + } + + @JsonProperty("caseSensitive") + public boolean isCaseSensitive() { + return _config._caseSensitive; + } + + @JsonProperty("invert") + public boolean isInverted() { + return _config._invert; + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { diff --git a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java index 30e1ece0c..98cd0d1ee 100644 --- a/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java +++ b/main/src/com/google/refine/browsing/facets/TimeRangeFacet.java @@ -39,6 +39,11 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; + import com.google.refine.browsing.FilteredRecords; import com.google.refine.browsing.FilteredRows; import com.google.refine.browsing.RecordFilter; @@ -63,18 +68,28 @@ public class TimeRangeFacet implements Facet { * Configuration, from the client side */ public static class TimeRangeFacetConfig implements FacetConfig { + @JsonProperty("name") protected String _name; // name of facet + @JsonProperty("expression") protected String _expression; // expression to compute numeric value(s) per row + @JsonProperty("columnName") protected String _columnName; // column to base expression on, if any + @JsonProperty(FROM) protected double _from; // the numeric selection + @JsonProperty(TO) protected double _to; + @JsonProperty("selectTime") protected boolean _selectTime; // whether the time selection applies, default true + @JsonProperty("selectNonTime") protected boolean _selectNonTime; + @JsonProperty("selectBlank") protected boolean _selectBlank; + @JsonProperty("selectError") protected boolean _selectError; + @JsonIgnore protected boolean _selected; // false if we're certain that all rows will match // and there isn't any filtering to do @@ -123,6 +138,11 @@ public class TimeRangeFacet implements Facet { facet.initializeFromConfig(this, project); return facet; } + + @Override + public String getJsonType() { + return "timerange"; + } } protected TimeRangeFacetConfig _config; @@ -142,14 +162,22 @@ public class TimeRangeFacet implements Facet { /* * Computed data */ + @JsonProperty("baseTimeCount") protected int _baseTimeCount; + @JsonProperty("baseNonTimeCount") protected int _baseNonTimeCount; + @JsonProperty("baseBlankCount") protected int _baseBlankCount; + @JsonProperty("baseErrorCount") protected int _baseErrorCount; - + + @JsonProperty("timeCount") protected int _timeCount; + @JsonProperty("nonTimeCount") protected int _nonTimeCount; + @JsonProperty("blankCount") protected int _blankCount; + @JsonProperty("errorCount") protected int _errorCount; protected static final String MIN = "min"; @@ -157,6 +185,87 @@ public class TimeRangeFacet implements Facet { protected static final String TO = "to"; protected static final String FROM = "from"; + @JsonProperty("name") + public String getName() { + return _config._name; + } + + @JsonProperty("expression") + public String getExpression() { + return _config._expression; + } + + @JsonProperty("columnName") + public String getColumnName() { + return _config._columnName; + } + + @JsonProperty("error") + @JsonInclude(Include.NON_NULL) + public String getError() { + return _errorMessage; + } + + @JsonProperty(MIN) + @JsonInclude(Include.NON_NULL) + public Double getMin() { + if(getError() == null) { + return _min; + } + return null; + } + + @JsonProperty(MAX) + @JsonInclude(Include.NON_NULL) + public Double getMax() { + if(getError() == null) { + return _max; + } + return null; + } + + @JsonProperty("step") + @JsonInclude(Include.NON_NULL) + public Double getStep() { + return _step; + } + + @JsonProperty("bins") + @JsonInclude(Include.NON_NULL) + public int[] getBins() { + if (getError() == null) { + return _bins; + } + return null; + } + + @JsonProperty("baseBins") + @JsonInclude(Include.NON_NULL) + public int[] getBaseBins() { + if (getError() == null) { + return _baseBins; + } + return null; + } + + @JsonProperty(FROM) + @JsonInclude(Include.NON_NULL) + public Double getFrom() { + if (getError() == null) { + return _config._from; + } + return null; + } + + @JsonProperty(TO) + @JsonInclude(Include.NON_NULL) + public Double getTo() { + if (getError() == null) { + return _config._to; + } + return null; + } + @Override public void write(JSONWriter writer, Properties options) throws JSONException { @@ -169,9 +278,9 @@ public class TimeRangeFacet implements Facet { writer.key("error"); writer.value(_errorMessage); } else { if (!Double.isInfinite(_min) && !Double.isInfinite(_max)) { - writer.key(MIN); writer.value(_min); - writer.key(MAX); writer.value(_max); - writer.key("step"); writer.value(_step); + writer.key(MIN); writer.value((long)_min); + writer.key(MAX); writer.value((long)_max); + writer.key("step"); writer.value((long)_step); writer.key("bins"); writer.array(); for (int b : _bins) { @@ -185,8 +294,8 @@ public class TimeRangeFacet implements Facet { } writer.endArray(); - writer.key(FROM); writer.value(_config._from); - writer.key(TO); writer.value(_config._to); + writer.key(FROM); writer.value((long)_config._from); + writer.key(TO); writer.value((long)_config._to); } writer.key("baseTimeCount"); writer.value(_baseTimeCount); diff --git a/main/src/com/google/refine/util/SerializationFilters.java b/main/src/com/google/refine/util/SerializationFilters.java index c8752c22f..646892b3e 100644 --- a/main/src/com/google/refine/util/SerializationFilters.java +++ b/main/src/com/google/refine/util/SerializationFilters.java @@ -66,8 +66,8 @@ public class SerializationFilters { @Override public void serialize(Double arg0, JsonGenerator gen, SerializerProvider s) throws IOException { - if (new Double(arg0.intValue()).equals(arg0)) { - gen.writeNumber(arg0.intValue()); + if (new Double(arg0.longValue()).equals(arg0)) { + gen.writeNumber(arg0.longValue()); } else { gen.writeNumber(arg0); } diff --git a/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java b/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java index f95c22ceb..16794c035 100644 --- a/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java +++ b/main/tests/server/src/com/google/refine/tests/browsing/facets/TimeRangeFacetTests.java @@ -20,13 +20,13 @@ public class TimeRangeFacetTests extends RefineTest { + "\"name\":\"my column\"," + "\"expression\":\"value\"," + "\"columnName\":\"my column\"," - + "\"min\":1.199329445E12," - + "\"max\":1.51496695E12," - + "\"step\":3.1556952E10," + + "\"min\":1199329445000," + + "\"max\":1514966950000," + + "\"step\":31556952000," + "\"bins\":[1,0,0,0,1,0,0,0,0,0,1]," + "\"baseBins\":[1,0,0,0,1,0,0,0,0,0,1]," - + "\"from\":1.262443349E12," - + "\"to\":1.51496695E12," + + "\"from\":1262443349000," + + "\"to\":1514966950000," + "\"baseTimeCount\":3," + "\"baseNonTimeCount\":1," + "\"baseBlankCount\":0," diff --git a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java index 0e00b7e0c..68f51e3fd 100644 --- a/main/tests/server/src/com/google/refine/tests/util/TestUtils.java +++ b/main/tests/server/src/com/google/refine/tests/util/TestUtils.java @@ -21,7 +21,6 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.google.refine.Jsonizable; import com.google.refine.util.JSONUtilities; -import com.google.refine.util.JsonViews; import com.google.refine.util.ParsingUtilities;