package com.belladati.sdk.util.impl; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; import org.apache.http.entity.StringEntity; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.belladati.sdk.exception.impl.UnknownViewTypeException; import com.belladati.sdk.exception.interval.InvalidAbsoluteIntervalException; import com.belladati.sdk.exception.interval.InvalidRelativeIntervalException; import com.belladati.sdk.exception.interval.NullIntervalException; import com.belladati.sdk.intervals.AbsoluteInterval; import com.belladati.sdk.intervals.CustomInterval; import com.belladati.sdk.intervals.DateUnit; import com.belladati.sdk.intervals.Interval; import com.belladati.sdk.intervals.IntervalUnit; import com.belladati.sdk.intervals.RelativeInterval; import com.belladati.sdk.intervals.TimeUnit; import com.belladati.sdk.test.SDKTest; import com.belladati.sdk.test.TestRequestHandler; import com.belladati.sdk.view.View; import com.belladati.sdk.view.ViewType; import com.belladati.sdk.view.impl.ViewImpl; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.IntNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; @Test public class IntervalTest extends SDKTest { private final String viewId = "viewId"; private final String viewName = "name"; private final String viewsUri = String.format("/api/reports/views/%s/chart", viewId); private final Calendar start = new GregorianCalendar(2012, 1, 2, 3, 4, 5); private final Calendar end = new GregorianCalendar(2013, 7, 8, 9, 10, 11); private final String startVal = "startVal"; private final String endVal = "endVal"; private final ObjectMapper mapper = new ObjectMapper(); /** absolute time interval down to seconds */ public void absoluteSecondsToJson() { Interval<?> interval = new AbsoluteInterval<IntervalUnit>(TimeUnit.SECOND, start, end); ObjectNode from = mapper.createObjectNode().put("hour", start.get(Calendar.HOUR)) .put("minute", start.get(Calendar.MINUTE)).put("second", start.get(Calendar.SECOND)); ObjectNode to = mapper.createObjectNode().put("hour", end.get(Calendar.HOUR)).put("minute", end.get(Calendar.MINUTE)) .put("second", end.get(Calendar.SECOND)); JsonNode expectedJson = buildIntervalNode(TimeUnit.SECOND, from, to, "absolute"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** absolute time interval down to minutes */ public void absoluteMinutesToJson() { Interval<?> interval = new AbsoluteInterval<IntervalUnit>(TimeUnit.MINUTE, start, end); ObjectNode from = mapper.createObjectNode().put("hour", start.get(Calendar.HOUR)).put("minute", start.get(Calendar.MINUTE)); ObjectNode to = mapper.createObjectNode().put("hour", end.get(Calendar.HOUR)).put("minute", end.get(Calendar.MINUTE)); JsonNode expectedJson = buildIntervalNode(TimeUnit.MINUTE, from, to, "absolute"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** absolute time interval down to hours */ public void absoluteHoursToJson() { Interval<?> interval = new AbsoluteInterval<IntervalUnit>(TimeUnit.HOUR, start, end); ObjectNode from = mapper.createObjectNode().put("hour", start.get(Calendar.HOUR)); ObjectNode to = mapper.createObjectNode().put("hour", end.get(Calendar.HOUR)); JsonNode expectedJson = buildIntervalNode(TimeUnit.HOUR, from, to, "absolute"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** absolute date interval down to days */ public void absoluteDaysToJson() { Interval<?> interval = new AbsoluteInterval<IntervalUnit>(DateUnit.DAY, start, end); ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)) .put("month", start.get(Calendar.MONTH) + 1).put("day", start.get(Calendar.DAY_OF_MONTH)); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)).put("month", end.get(Calendar.MONTH) + 1) .put("day", end.get(Calendar.DAY_OF_MONTH)); JsonNode expectedJson = buildIntervalNode(DateUnit.DAY, from, to, "absolute"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** absolute date interval down to weeks */ public void absoluteWeeksToJson() { Interval<?> interval = new AbsoluteInterval<IntervalUnit>(DateUnit.WEEK, start, end); ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)).put("week", start.get(Calendar.WEEK_OF_YEAR)); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)).put("week", end.get(Calendar.WEEK_OF_YEAR)); JsonNode expectedJson = buildIntervalNode(DateUnit.WEEK, from, to, "absolute"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** absolute date interval down to months */ public void absoluteMonthsToJson() { Interval<?> interval = new AbsoluteInterval<IntervalUnit>(DateUnit.MONTH, start, end); ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)).put("month", start.get(Calendar.MONTH) + 1); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)).put("month", end.get(Calendar.MONTH) + 1); JsonNode expectedJson = buildIntervalNode(DateUnit.MONTH, from, to, "absolute"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** absolute date interval down to quarters */ public void absoluteQuartersToJson() { Interval<?> interval = new AbsoluteInterval<IntervalUnit>(DateUnit.QUARTER, start, end); ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)).put("quarter", start.get(Calendar.MONTH) / 3 + 1); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)).put("quarter", end.get(Calendar.MONTH) / 3 + 1); JsonNode expectedJson = buildIntervalNode(DateUnit.QUARTER, from, to, "absolute"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** absolute date interval down to years */ public void absoluteYearsToJson() { Interval<?> interval = new AbsoluteInterval<IntervalUnit>(DateUnit.YEAR, start, end); ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)); JsonNode expectedJson = buildIntervalNode(DateUnit.YEAR, from, to, "absolute"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** relative intervals */ @Test(dataProvider = "intervalUnitProvider") public void relativeToJson(IntervalUnit unit) { Interval<?> interval = new RelativeInterval<IntervalUnit>(unit, -10, 10); JsonNode from = new IntNode(-10); JsonNode to = new IntNode(10); JsonNode expectedJson = buildIntervalNode(unit, from, to, "relative"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** custom intervals */ @Test(dataProvider = "intervalUnitProvider") public void customToJson(IntervalUnit unit) { Interval<?> interval = new CustomInterval<IntervalUnit>(unit, startVal, endVal); JsonNode from = new TextNode(startVal); JsonNode to = new TextNode(endVal); JsonNode expectedJson = buildIntervalNode(unit, from, to, "custom"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** start and end may be equal in absolute intervals */ public void startEndEqualAbsolute() { Interval<?> interval = new AbsoluteInterval<IntervalUnit>(TimeUnit.HOUR, start, start); ObjectNode from = mapper.createObjectNode().put("hour", start.get(Calendar.HOUR)); ObjectNode to = mapper.createObjectNode().put("hour", start.get(Calendar.HOUR)); JsonNode expectedJson = buildIntervalNode(TimeUnit.HOUR, from, to, "absolute"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** start and end may be equal in relative intervals */ public void startEndEqualRelative() { Interval<?> interval = new RelativeInterval<IntervalUnit>(DateUnit.DAY, 10, 10); JsonNode from = new IntNode(10); JsonNode to = new IntNode(10); JsonNode expectedJson = buildIntervalNode(DateUnit.DAY, from, to, "relative"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** start and end may be equal in custom intervals */ public void startEndEqualCustom() { Interval<?> interval = new CustomInterval<IntervalUnit>(DateUnit.DAY, startVal, startVal); JsonNode from = new TextNode(startVal); JsonNode to = new TextNode(startVal); JsonNode expectedJson = buildIntervalNode(DateUnit.DAY, from, to, "custom"); assertEquals(interval.toJson(), expectedJson); assertEquals(interval.toString(), expectedJson.toString()); } /** start may not be later than end in absolute intervals */ public void startAfterEndAbsolute() { try { new AbsoluteInterval<IntervalUnit>(TimeUnit.HOUR, end, start); fail("did not throw exception"); } catch (InvalidAbsoluteIntervalException e) { assertEquals(e.getIntervalUnit(), TimeUnit.HOUR); assertEquals(e.getStart(), end); assertEquals(e.getEnd(), start); } } /** start may not be greater than end in relative intervals */ public void startAfterEndRelative() { try { new RelativeInterval<IntervalUnit>(DateUnit.DAY, 10, -10); fail("did not throw exception"); } catch (InvalidRelativeIntervalException e) { assertEquals(e.getIntervalUnit(), DateUnit.DAY); assertEquals((int) e.getStart(), 10); assertEquals((int) e.getEnd(), -10); } } /** interval unit may not be null in absolute intervals */ @Test(expectedExceptions = NullIntervalException.class) public void unitNullAbsolute() { new AbsoluteInterval<IntervalUnit>(null, start, end); } /** interval unit may not be null in relative intervals */ @Test(expectedExceptions = NullIntervalException.class) public void unitNullRelative() { new RelativeInterval<IntervalUnit>(null, -1, 1); } /** interval unit may not be null in custom intervals */ @Test(expectedExceptions = NullIntervalException.class) public void unitNullCustom() { new CustomInterval<IntervalUnit>(null, startVal, endVal); } /** interval start may not be null */ @Test(expectedExceptions = NullIntervalException.class) public void startNullAbsolute() { new AbsoluteInterval<IntervalUnit>(TimeUnit.HOUR, null, end); } /** interval end may not be null */ @Test(expectedExceptions = NullIntervalException.class) public void endNullAbsolute() { new AbsoluteInterval<IntervalUnit>(TimeUnit.HOUR, start, null); } /** interval start may not be null */ @Test(expectedExceptions = NullIntervalException.class) public void startNullCustom() { new CustomInterval<IntervalUnit>(TimeUnit.HOUR, null, endVal); } /** interval end may not be null */ @Test(expectedExceptions = NullIntervalException.class) public void endNullCustom() { new CustomInterval<IntervalUnit>(TimeUnit.HOUR, startVal, null); } /** interval start may not be empty */ @Test(expectedExceptions = NullIntervalException.class) public void startEmptyCustom() { new CustomInterval<IntervalUnit>(TimeUnit.HOUR, " ", endVal); } /** interval end may not be empty */ @Test(expectedExceptions = NullIntervalException.class) public void endEmptyCustom() { new CustomInterval<IntervalUnit>(TimeUnit.HOUR, startVal, " "); } /** Query parameters with time only are correct. */ public void queryStringTimeOnly() throws UnknownViewTypeException { final ObjectNode from = mapper.createObjectNode().put("hour", start.get(Calendar.HOUR)); final ObjectNode to = mapper.createObjectNode().put("hour", end.get(Calendar.HOUR)); server.register(viewsUri, new TestRequestHandler() { @Override protected void handle(HttpHolder holder) throws IOException { String intervalString = holder.getUrlParameters().get("dateTimeDefinition"); assertNotNull(intervalString); ObjectNode intervalNode = buildIntervalNode(TimeUnit.HOUR, from, to, "absolute"); assertEquals(mapper.readTree(intervalString), intervalNode); holder.response.setEntity(new StringEntity("{}")); } }); service.setupViewLoader(viewId, ViewType.CHART).setTimeInterval(new AbsoluteInterval<TimeUnit>(TimeUnit.HOUR, start, end)) .loadContent(); server.assertRequestUris(viewsUri); } /** Query parameters with date only are correct. */ public void queryStringDateOnly() throws UnknownViewTypeException { final ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)); final ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)); server.register(viewsUri, new TestRequestHandler() { @Override protected void handle(HttpHolder holder) throws IOException { String intervalString = holder.getUrlParameters().get("dateTimeDefinition"); assertNotNull(intervalString); ObjectNode intervalNode = buildIntervalNode(DateUnit.YEAR, from, to, "absolute"); assertEquals(mapper.readTree(intervalString), intervalNode); holder.response.setEntity(new StringEntity("{}")); } }); service.setupViewLoader(viewId, ViewType.CHART).setDateInterval(new AbsoluteInterval<DateUnit>(DateUnit.YEAR, start, end)) .loadContent(); server.assertRequestUris(viewsUri); } /** Query parameters with both intervals are correct. */ public void queryStringBoth() throws UnknownViewTypeException { final ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)); final ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)); server.register(viewsUri, new TestRequestHandler() { @Override protected void handle(HttpHolder holder) throws IOException { String intervalString = holder.getUrlParameters().get("dateTimeDefinition"); assertNotNull(intervalString); ObjectNode intervalNode = buildIntervalNode(DateUnit.YEAR, from, to, "absolute"); intervalNode.setAll(buildIntervalNode(TimeUnit.MINUTE, new IntNode(-10), new IntNode(10), "relative")); assertEquals(mapper.readTree(intervalString), intervalNode); holder.response.setEntity(new StringEntity("{}")); } }); service.setupViewLoader(viewId, ViewType.CHART).setDateInterval(new AbsoluteInterval<DateUnit>(DateUnit.YEAR, start, end)) .setTimeInterval(new RelativeInterval<TimeUnit>(TimeUnit.MINUTE, -10, 10)).loadContent(); server.assertRequestUris(viewsUri); } /** absolute time interval in seconds */ public void predefinedSecondInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("hour", start.get(Calendar.HOUR)) .put("minute", start.get(Calendar.MINUTE)).put("second", start.get(Calendar.SECOND)); ObjectNode to = mapper.createObjectNode().put("hour", end.get(Calendar.HOUR)).put("minute", end.get(Calendar.MINUTE)) .put("second", end.get(Calendar.SECOND)); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(TimeUnit.SECOND, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); Calendar expectedStart = new GregorianCalendar(0, 0, 0, start.get(Calendar.HOUR), start.get(Calendar.MINUTE), start.get(Calendar.SECOND)); Calendar expectedEnd = new GregorianCalendar(0, 0, 0, end.get(Calendar.HOUR), end.get(Calendar.MINUTE), end.get(Calendar.SECOND)); assertFalse(view.hasPredefinedDateInterval()); assertTrue(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); AbsoluteInterval<TimeUnit> interval = (AbsoluteInterval<TimeUnit>) view.getPredefinedTimeInterval(); assertEquals(interval.getIntervalUnit(), TimeUnit.SECOND); assertEquals(interval.getStart(), expectedStart); assertEquals(interval.getEnd(), expectedEnd); } /** absolute time interval in minutes */ public void predefinedMinuteInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("hour", start.get(Calendar.HOUR)).put("minute", start.get(Calendar.MINUTE)); ObjectNode to = mapper.createObjectNode().put("hour", end.get(Calendar.HOUR)).put("minute", end.get(Calendar.MINUTE)); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(TimeUnit.MINUTE, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); Calendar expectedStart = new GregorianCalendar(0, 0, 0, start.get(Calendar.HOUR), start.get(Calendar.MINUTE), 0); Calendar expectedEnd = new GregorianCalendar(0, 0, 0, end.get(Calendar.HOUR), end.get(Calendar.MINUTE), 0); assertFalse(view.hasPredefinedDateInterval()); assertTrue(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); AbsoluteInterval<TimeUnit> interval = (AbsoluteInterval<TimeUnit>) view.getPredefinedTimeInterval(); assertEquals(interval.getIntervalUnit(), TimeUnit.MINUTE); assertEquals(interval.getStart(), expectedStart); assertEquals(interval.getEnd(), expectedEnd); } /** absolute time interval in hours */ public void predefinedHourInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("hour", start.get(Calendar.HOUR)); ObjectNode to = mapper.createObjectNode().put("hour", end.get(Calendar.HOUR)); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(TimeUnit.HOUR, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); Calendar expectedStart = new GregorianCalendar(0, 0, 0, start.get(Calendar.HOUR), 0, 0); Calendar expectedEnd = new GregorianCalendar(0, 0, 0, end.get(Calendar.HOUR), 0, 0); assertFalse(view.hasPredefinedDateInterval()); assertTrue(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); AbsoluteInterval<TimeUnit> interval = (AbsoluteInterval<TimeUnit>) view.getPredefinedTimeInterval(); assertEquals(interval.getIntervalUnit(), TimeUnit.HOUR); assertEquals(interval.getStart(), expectedStart); assertEquals(interval.getEnd(), expectedEnd); } /** absolute date interval in days */ public void predefinedDayInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)) .put("month", start.get(Calendar.MONTH) + 1).put("day", start.get(Calendar.DAY_OF_MONTH)); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)).put("month", end.get(Calendar.MONTH) + 1) .put("day", end.get(Calendar.DAY_OF_MONTH)); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(DateUnit.DAY, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); Calendar expectedStart = new GregorianCalendar(start.get(Calendar.YEAR), start.get(Calendar.MONTH), start.get(Calendar.DAY_OF_MONTH)); Calendar expectedEnd = new GregorianCalendar(end.get(Calendar.YEAR), end.get(Calendar.MONTH), end.get(Calendar.DAY_OF_MONTH)); assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); AbsoluteInterval<DateUnit> interval = (AbsoluteInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), DateUnit.DAY); assertEquals(interval.getStart(), expectedStart); assertEquals(interval.getEnd(), expectedEnd); assertNull(view.getPredefinedTimeInterval()); } /** absolute week interval in weeks */ public void predefinedWeekInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)).put("week", start.get(Calendar.WEEK_OF_YEAR)); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)).put("week", end.get(Calendar.WEEK_OF_YEAR)); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(DateUnit.WEEK, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); Calendar expectedStart = new GregorianCalendar(start.get(Calendar.YEAR), 0, 1); expectedStart.set(Calendar.WEEK_OF_YEAR, start.get(Calendar.WEEK_OF_YEAR)); Calendar expectedEnd = new GregorianCalendar(end.get(Calendar.YEAR), 0, 1); expectedEnd.set(Calendar.WEEK_OF_YEAR, end.get(Calendar.WEEK_OF_YEAR)); assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); AbsoluteInterval<DateUnit> interval = (AbsoluteInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), DateUnit.WEEK); assertEquals(interval.getStart(), expectedStart); assertEquals(interval.getEnd(), expectedEnd); assertNull(view.getPredefinedTimeInterval()); } /** absolute date interval in months */ public void predefinedMonthInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)).put("month", start.get(Calendar.MONTH) + 1); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)).put("month", end.get(Calendar.MONTH) + 1); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(DateUnit.MONTH, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); Calendar expectedStart = new GregorianCalendar(start.get(Calendar.YEAR), start.get(Calendar.MONTH), 1); Calendar expectedEnd = new GregorianCalendar(end.get(Calendar.YEAR), end.get(Calendar.MONTH), 1); assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); AbsoluteInterval<DateUnit> interval = (AbsoluteInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), DateUnit.MONTH); assertEquals(interval.getStart(), expectedStart); assertEquals(interval.getEnd(), expectedEnd); assertNull(view.getPredefinedTimeInterval()); } /** absolute date interval in quarters */ public void predefinedQuarterInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)).put("quarter", start.get(Calendar.MONTH) / 3 + 1); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)).put("quarter", end.get(Calendar.MONTH) / 3 + 1); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(DateUnit.QUARTER, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); Calendar expectedStart = new GregorianCalendar(start.get(Calendar.YEAR), (start.get(Calendar.MONTH) / 3) * 3, 1); Calendar expectedEnd = new GregorianCalendar(end.get(Calendar.YEAR), (end.get(Calendar.MONTH) / 3) * 3, 1); assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); AbsoluteInterval<DateUnit> interval = (AbsoluteInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), DateUnit.QUARTER); assertEquals(interval.getStart(), expectedStart); assertEquals(interval.getEnd(), expectedEnd); assertNull(view.getPredefinedTimeInterval()); } /** absolute date interval in years */ public void predefinedYearInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("year", start.get(Calendar.YEAR)); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(DateUnit.YEAR, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); Calendar expectedStart = new GregorianCalendar(start.get(Calendar.YEAR), 0, 1); Calendar expectedEnd = new GregorianCalendar(end.get(Calendar.YEAR), 0, 1); assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); AbsoluteInterval<DateUnit> interval = (AbsoluteInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), DateUnit.YEAR); assertEquals(interval.getStart(), expectedStart); assertEquals(interval.getEnd(), expectedEnd); assertNull(view.getPredefinedTimeInterval()); } /** predefined relative intervals */ @Test(dataProvider = "intervalUnitProvider") public void predefinedRelativeInterval(IntervalUnit unit) throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(unit, new IntNode(-3), new IntNode(3), "rElAtIvE")); View view = ViewImpl.buildView(service, viewNode); if (unit instanceof DateUnit) { assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); RelativeInterval<DateUnit> interval = (RelativeInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), unit); assertEquals(interval.getStart(), -3); assertEquals(interval.getEnd(), 3); assertNull(view.getPredefinedTimeInterval()); } else { assertFalse(view.hasPredefinedDateInterval()); assertTrue(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); RelativeInterval<TimeUnit> interval = (RelativeInterval<TimeUnit>) view.getPredefinedTimeInterval(); assertEquals(interval.getIntervalUnit(), unit); assertEquals(interval.getStart(), -3); assertEquals(interval.getEnd(), 3); } } /** predefined custom intervals */ @Test(dataProvider = "intervalUnitProvider") public void predefinedCustomInterval(IntervalUnit unit) throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(unit, new TextNode(startVal), new TextNode(endVal), "cUsToM")); View view = ViewImpl.buildView(service, viewNode); if (unit instanceof DateUnit) { assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); CustomInterval<DateUnit> interval = (CustomInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), unit); assertEquals(interval.getStart(), startVal); assertEquals(interval.getEnd(), endVal); assertNull(view.getPredefinedTimeInterval()); } else { assertFalse(view.hasPredefinedDateInterval()); assertTrue(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); CustomInterval<TimeUnit> interval = (CustomInterval<TimeUnit>) view.getPredefinedTimeInterval(); assertEquals(interval.getIntervalUnit(), unit); assertEquals(interval.getStart(), startVal); assertEquals(interval.getEnd(), endVal); } } /** an interval that's not a known type */ @Test(dataProvider = "intervalUnitProvider") public void predefinedUnknownInterval(IntervalUnit unit) throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(unit, new IntNode(-3), new IntNode(3), "something else")); View view = ViewImpl.buildView(service, viewNode); assertFalse(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); assertNull(view.getPredefinedTimeInterval()); } /** invalid relative intervals are ignored */ @Test(dataProvider = "intervalUnitProvider") public void invalidRelativeInterval(IntervalUnit unit) throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(unit, new TextNode("abc"), new IntNode(3), "relative")); View view = ViewImpl.buildView(service, viewNode); assertFalse(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); assertNull(view.getPredefinedTimeInterval()); } /** invalid absolute intervals are ignored */ public void invalidAbsoluteInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("year", "abc"); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(DateUnit.YEAR, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); assertFalse(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); assertNull(view.getPredefinedTimeInterval()); } /** invalid custom intervals are ignored */ @Test(dataProvider = "intervalUnitProvider") public void invalidCustomInterval(IntervalUnit unit) throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(unit, new TextNode(""), new TextNode(endVal), "custom")); View view = ViewImpl.buildView(service, viewNode); assertFalse(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); assertNull(view.getPredefinedTimeInterval()); } /** intervals with numeric strings instead of numbers are allowed */ @Test(dataProvider = "intervalUnitProvider") public void stringRelativeInterval(IntervalUnit unit) throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(unit, new TextNode("-3"), new IntNode(3), "relative")); View view = ViewImpl.buildView(service, viewNode); if (unit instanceof DateUnit) { assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); RelativeInterval<DateUnit> interval = (RelativeInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), unit); assertEquals(interval.getStart(), -3); assertEquals(interval.getEnd(), 3); assertNull(view.getPredefinedTimeInterval()); } else { assertFalse(view.hasPredefinedDateInterval()); assertTrue(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); RelativeInterval<TimeUnit> interval = (RelativeInterval<TimeUnit>) view.getPredefinedTimeInterval(); assertEquals(interval.getIntervalUnit(), unit); assertEquals(interval.getStart(), -3); assertEquals(interval.getEnd(), 3); } } /** intervals with numeric strings instead of numbers are allowed */ public void stringAbsoluteInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("year", "" + start.get(Calendar.YEAR)); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(DateUnit.YEAR, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); AbsoluteInterval<DateUnit> interval = (AbsoluteInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), DateUnit.YEAR); assertEquals(interval.getStart(), new GregorianCalendar(start.get(Calendar.YEAR), 0, 1)); assertEquals(interval.getEnd(), new GregorianCalendar(end.get(Calendar.YEAR), 0, 1)); assertNull(view.getPredefinedTimeInterval()); } /** intervals with numbers instead of strings are allowed */ @Test(dataProvider = "intervalUnitProvider") public void numberCustomInterval(IntervalUnit unit) throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(unit, new IntNode(1), new IntNode(2), "custom")); View view = ViewImpl.buildView(service, viewNode); if (unit instanceof DateUnit) { assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); CustomInterval<DateUnit> interval = (CustomInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), unit); assertEquals(interval.getStart(), "1"); assertEquals(interval.getEnd(), "2"); assertNull(view.getPredefinedTimeInterval()); } else { assertFalse(view.hasPredefinedDateInterval()); assertTrue(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); CustomInterval<TimeUnit> interval = (CustomInterval<TimeUnit>) view.getPredefinedTimeInterval(); assertEquals(interval.getIntervalUnit(), unit); assertEquals(interval.getStart(), "1"); assertEquals(interval.getEnd(), "2"); } } /** intervals with numeric fraction strings instead of numbers are allowed */ @Test(dataProvider = "intervalUnitProvider") public void fractionRelativeInterval(IntervalUnit unit) throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(unit, new TextNode("-3.0"), new IntNode(3), "relative")); View view = ViewImpl.buildView(service, viewNode); if (unit instanceof DateUnit) { assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); RelativeInterval<DateUnit> interval = (RelativeInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), unit); assertEquals(interval.getStart(), -3); assertEquals(interval.getEnd(), 3); assertNull(view.getPredefinedTimeInterval()); } else { assertFalse(view.hasPredefinedDateInterval()); assertTrue(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); RelativeInterval<TimeUnit> interval = (RelativeInterval<TimeUnit>) view.getPredefinedTimeInterval(); assertEquals(interval.getIntervalUnit(), unit); assertEquals(interval.getStart(), -3); assertEquals(interval.getEnd(), 3); } } /** intervals with numeric fraction strings instead of numbers are allowed */ public void fractionAbsoluteInterval() throws UnknownViewTypeException { ObjectNode from = mapper.createObjectNode().put("year", "" + start.get(Calendar.YEAR) + ".0"); ObjectNode to = mapper.createObjectNode().put("year", end.get(Calendar.YEAR)); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); viewNode.put("dateTimeDefinition", buildIntervalNode(DateUnit.YEAR, from, to, "absolute")); View view = ViewImpl.buildView(service, viewNode); assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); AbsoluteInterval<DateUnit> interval = (AbsoluteInterval<DateUnit>) view.getPredefinedDateInterval(); assertEquals(interval.getIntervalUnit(), DateUnit.YEAR); assertEquals(interval.getStart(), new GregorianCalendar(start.get(Calendar.YEAR), 0, 1)); assertEquals(interval.getEnd(), new GregorianCalendar(end.get(Calendar.YEAR), 0, 1)); assertNull(view.getPredefinedTimeInterval()); } /** intervals with invalid units are ignored */ public void invalidUnits() throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); ObjectNode definitionNode = buildIntervalNode(DateUnit.DAY, new TextNode("-3"), new IntNode(3), "relative"); definitionNode.setAll(buildIntervalNode(TimeUnit.HOUR, new TextNode("-3"), new IntNode(3), "relative")); ((ObjectNode) definitionNode.get("dateInterval")).put("aggregationType", "not a date unit"); ((ObjectNode) definitionNode.get("timeInterval")).put("aggregationType", "not a time unit"); viewNode.put("dateTimeDefinition", definitionNode); View view = ViewImpl.buildView(service, viewNode); assertFalse(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); assertNull(view.getPredefinedTimeInterval()); } /** intervals with null units are ignored */ public void noUnits() throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); ObjectNode definitionNode = buildIntervalNode(DateUnit.DAY, new TextNode("-3"), new IntNode(3), "relative"); definitionNode.setAll(buildIntervalNode(TimeUnit.HOUR, new TextNode("-3"), new IntNode(3), "relative")); ((ObjectNode) definitionNode.get("dateInterval")).remove("aggregationType"); ((ObjectNode) definitionNode.get("timeInterval")).remove("aggregationType"); viewNode.put("dateTimeDefinition", definitionNode); View view = ViewImpl.buildView(service, viewNode); assertFalse(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); assertNull(view.getPredefinedTimeInterval()); } /** intervals with start after end are ignored */ public void startAfterEnd() throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); ObjectNode definitionNode = buildIntervalNode(DateUnit.DAY, new IntNode(3), new IntNode(-3), "relative"); definitionNode.setAll(buildIntervalNode(TimeUnit.HOUR, new IntNode(3), new IntNode(-3), "relative")); viewNode.put("dateTimeDefinition", definitionNode); View view = ViewImpl.buildView(service, viewNode); assertFalse(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); assertNull(view.getPredefinedDateInterval()); assertNull(view.getPredefinedTimeInterval()); } /** interval units are not case-sensitive */ public void unitCaseInsensitive() throws UnknownViewTypeException { ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); ObjectNode definitionNode = buildIntervalNode(DateUnit.DAY, new TextNode("-3"), new IntNode(3), "relative"); definitionNode.setAll(buildIntervalNode(TimeUnit.HOUR, new TextNode("-3"), new IntNode(3), "relative")); ((ObjectNode) definitionNode.get("dateInterval")).put("aggregationType", "dAy"); ((ObjectNode) definitionNode.get("timeInterval")).put("aggregationType", "hOuR"); viewNode.put("dateTimeDefinition", definitionNode); View view = ViewImpl.buildView(service, viewNode); assertTrue(view.hasPredefinedDateInterval()); assertTrue(view.hasPredefinedTimeInterval()); } /** two intervals with same parameters are equal */ public void intervalEquals() { assertEquals(new RelativeInterval<IntervalUnit>(DateUnit.DAY, -1, 1), new RelativeInterval<IntervalUnit>(DateUnit.DAY, -1, 1)); assertEquals(new AbsoluteInterval<IntervalUnit>(DateUnit.DAY, start, end), new AbsoluteInterval<IntervalUnit>(DateUnit.DAY, start, end)); assertEquals(new AbsoluteInterval<IntervalUnit>(DateUnit.DAY, Calendar.getInstance(), Calendar.getInstance()), new AbsoluteInterval<IntervalUnit>(DateUnit.DAY, Calendar.getInstance(), Calendar.getInstance())); assertNotEquals(new RelativeInterval<IntervalUnit>(DateUnit.DAY, -1, 1), new RelativeInterval<IntervalUnit>(DateUnit.DAY, -1, -1)); assertNotEquals(new AbsoluteInterval<IntervalUnit>(DateUnit.DAY, start, end), new AbsoluteInterval<IntervalUnit>(DateUnit.DAY, start, start)); assertNotEquals(new RelativeInterval<IntervalUnit>(DateUnit.DAY, -1, 1), new RelativeInterval<IntervalUnit>(DateUnit.MONTH, -1, 1)); assertNotEquals(new AbsoluteInterval<IntervalUnit>(DateUnit.DAY, start, end), new AbsoluteInterval<IntervalUnit>(DateUnit.MONTH, start, end)); assertFalse(new RelativeInterval<IntervalUnit>(DateUnit.DAY, -1, 1).equals(new Object())); } /** system locale doesn't affect upper/lowercase conversion */ @Test(dataProvider = "intervalUnitProvider", groups = "locale") public void localeCaseConversion(IntervalUnit unit) throws UnknownViewTypeException { Locale.setDefault(new Locale("tr")); ObjectNode viewNode = builder.buildViewNode(viewId, viewName, "chart"); ObjectNode intervalNode = buildIntervalNode(unit, new TextNode("-3.0"), new IntNode(3), "relative"); // set the aggregation type to lower case in English conversion // when converted back using Turkish, i will not become I String unitType = unit instanceof DateUnit ? "dateInterval" : "timeInterval"; ObjectNode typeNode = (ObjectNode) intervalNode.get(unitType); typeNode.put("aggregationType", typeNode.get("aggregationType").asText().toLowerCase(Locale.ENGLISH)); viewNode.put("dateTimeDefinition", intervalNode); View view = ViewImpl.buildView(service, viewNode); if (unit instanceof DateUnit) { assertTrue(view.hasPredefinedDateInterval()); assertFalse(view.hasPredefinedTimeInterval()); } else { assertFalse(view.hasPredefinedDateInterval()); assertTrue(view.hasPredefinedTimeInterval()); } } @DataProvider(name = "intervalUnitProvider") protected Object[][] provideIntervalUnits() { List<IntervalUnit[]> unitList = new ArrayList<IntervalUnit[]>(); for (IntervalUnit unit : DateUnit.values()) { unitList.add(new IntervalUnit[] { unit }); } for (IntervalUnit unit : TimeUnit.values()) { unitList.add(new IntervalUnit[] { unit }); } return unitList.toArray(new IntervalUnit[0][0]); } private ObjectNode buildIntervalNode(IntervalUnit intervalUnit, JsonNode from, JsonNode to, String type) { ObjectNode expectedJson = mapper.createObjectNode(); ObjectNode timeInterval = mapper.createObjectNode(); ObjectNode intervalNode = mapper.createObjectNode(); String unitType = intervalUnit instanceof DateUnit ? "dateInterval" : "timeInterval"; expectedJson.put(unitType, timeInterval); timeInterval.put("interval", intervalNode); timeInterval.put("aggregationType", intervalUnit.name()); intervalNode.put("from", from); intervalNode.put("to", to); intervalNode.put("type", type); return expectedJson; } }