| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF 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 org.apache.solr.client.solrj.io.stream.eval; |
| |
| import java.io.IOException; |
| import java.time.Instant; |
| import java.time.LocalDateTime; |
| import java.time.MonthDay; |
| import java.time.YearMonth; |
| import java.time.ZoneOffset; |
| import java.util.Calendar; |
| import java.util.Date; |
| import java.util.GregorianCalendar; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.TimeZone; |
| |
| import org.apache.commons.collections4.map.HashedMap; |
| import org.apache.solr.client.solrj.io.Tuple; |
| import org.apache.solr.client.solrj.io.eval.StreamEvaluator; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorDay; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorDayOfQuarter; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorDayOfYear; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorEpoch; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorHour; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorMinute; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorMonth; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorQuarter; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorSecond; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorWeek; |
| import org.apache.solr.client.solrj.io.eval.TemporalEvaluatorYear; |
| import org.apache.solr.client.solrj.io.stream.StreamContext; |
| import org.apache.solr.client.solrj.io.stream.expr.Explanation; |
| import org.apache.solr.client.solrj.io.stream.expr.StreamExpression; |
| import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParser; |
| import org.apache.solr.client.solrj.io.stream.expr.StreamFactory; |
| import org.junit.Test; |
| |
| import static junit.framework.Assert.assertEquals; |
| import static junit.framework.Assert.assertTrue; |
| |
| /** |
| * Tests numeric Date/Time stream evaluators |
| */ |
| public class TemporalEvaluatorsTest { |
| |
| |
| StreamFactory factory; |
| Map<String, Object> values; |
| |
| public TemporalEvaluatorsTest() { |
| super(); |
| |
| factory = new StreamFactory(); |
| |
| factory.withFunctionName(TemporalEvaluatorYear.FUNCTION_NAME, TemporalEvaluatorYear.class); |
| factory.withFunctionName(TemporalEvaluatorMonth.FUNCTION_NAME, TemporalEvaluatorMonth.class); |
| factory.withFunctionName(TemporalEvaluatorDay.FUNCTION_NAME, TemporalEvaluatorDay.class); |
| factory.withFunctionName(TemporalEvaluatorDayOfYear.FUNCTION_NAME, TemporalEvaluatorDayOfYear.class); |
| factory.withFunctionName(TemporalEvaluatorHour.FUNCTION_NAME, TemporalEvaluatorHour.class); |
| factory.withFunctionName(TemporalEvaluatorMinute.FUNCTION_NAME, TemporalEvaluatorMinute.class); |
| factory.withFunctionName(TemporalEvaluatorSecond.FUNCTION_NAME, TemporalEvaluatorSecond.class); |
| factory.withFunctionName(TemporalEvaluatorEpoch.FUNCTION_NAME, TemporalEvaluatorEpoch.class); |
| factory.withFunctionName(TemporalEvaluatorWeek.FUNCTION_NAME, TemporalEvaluatorWeek.class); |
| factory.withFunctionName(TemporalEvaluatorQuarter.FUNCTION_NAME, TemporalEvaluatorQuarter.class); |
| factory.withFunctionName(TemporalEvaluatorDayOfQuarter.FUNCTION_NAME, TemporalEvaluatorDayOfQuarter.class); |
| |
| values = new HashedMap<>(); |
| } |
| |
| @Test |
| public void testInvalidExpression() throws Exception { |
| |
| StreamEvaluator evaluator; |
| |
| try { |
| evaluator = factory.constructEvaluator("week()"); |
| StreamContext streamContext = new StreamContext(); |
| evaluator.setStreamContext(streamContext); |
| assertTrue(false); |
| } catch (IOException e) { |
| assertTrue(e.getCause().getCause().getMessage().contains("Invalid expression week()")); |
| } |
| |
| try { |
| evaluator = factory.constructEvaluator("week(a, b)"); |
| StreamContext streamContext = new StreamContext(); |
| evaluator.setStreamContext(streamContext); |
| assertTrue(false); |
| } catch (IOException e) { |
| assertTrue(e.getCause().getCause().getMessage().contains("expecting one value but found 2")); |
| } |
| |
| try { |
| evaluator = factory.constructEvaluator("Week()"); |
| StreamContext streamContext = new StreamContext(); |
| evaluator.setStreamContext(streamContext); |
| assertTrue(false); |
| } catch (IOException e) { |
| assertTrue(e.getMessage().contains("Invalid evaluator expression Week() - function 'Week' is unknown")); |
| } |
| } |
| |
| |
| @Test |
| public void testInvalidValues() throws Exception { |
| StreamEvaluator evaluator = factory.constructEvaluator("year(a)"); |
| |
| |
| try { |
| values.clear(); |
| values.put("a", 12); |
| StreamContext streamContext = new StreamContext(); |
| evaluator.setStreamContext(streamContext); |
| Object result = evaluator.evaluate(new Tuple(values)); |
| assertTrue(false); |
| } catch (IOException e) { |
| assertEquals("Invalid parameter 12 - The parameter must be a string formatted ISO_INSTANT or of type Long,Instant,Date,LocalDateTime or TemporalAccessor.", e.getMessage()); |
| } |
| |
| try { |
| values.clear(); |
| values.put("a", "1995-12-31"); |
| StreamContext streamContext = new StreamContext(); |
| evaluator.setStreamContext(streamContext); |
| Object result = evaluator.evaluate(new Tuple(values)); |
| assertTrue(false); |
| } catch (IOException e) { |
| assertEquals("Invalid parameter 1995-12-31 - The String must be formatted in the ISO_INSTANT date format.", e.getMessage()); |
| } |
| |
| try { |
| values.clear(); |
| values.put("a", ""); |
| StreamContext streamContext = new StreamContext(); |
| evaluator.setStreamContext(streamContext); |
| Object result = evaluator.evaluate(new Tuple(values)); |
| assertTrue(false); |
| } catch (IOException e) { |
| assertEquals("Invalid parameter - The parameter must be a string formatted ISO_INSTANT or of type Long,Instant,Date,LocalDateTime or TemporalAccessor.", e.getMessage()); |
| } |
| |
| values.clear(); |
| } |
| |
| @Test |
| public void testAllFunctions() throws Exception { |
| |
| //year, month, day, dayofyear, hour, minute, quarter, week, second, epoch |
| testFunction("year(a)", "1995-12-31T23:59:59Z", 1995L); |
| testFunction("month(a)","1995-12-31T23:59:59Z", 12L); |
| testFunction("day(a)", "1995-12-31T23:59:59Z", 31L); |
| testFunction("dayOfYear(a)", "1995-12-31T23:59:59Z", 365L); |
| testFunction("dayOfQuarter(a)", "1995-12-31T23:59:59Z", 92L); |
| testFunction("hour(a)", "1995-12-31T23:59:59Z", 23L); |
| testFunction("minute(a)", "1995-12-31T23:59:59Z", 59L); |
| testFunction("quarter(a)","1995-12-31T23:59:59Z", 4L); |
| testFunction("week(a)", "1995-12-31T23:59:59Z", 52L); |
| testFunction("second(a)", "1995-12-31T23:59:58Z", 58L); |
| testFunction("epoch(a)", "1995-12-31T23:59:59Z", 820454399000l); |
| |
| testFunction("year(a)", "2017-03-17T10:30:45Z", 2017L); |
| testFunction("year('a')", "2017-03-17T10:30:45Z", 2017L); |
| testFunction("month(a)","2017-03-17T10:30:45Z", 3L); |
| testFunction("day(a)", "2017-03-17T10:30:45Z", 17L); |
| testFunction("day('a')", "2017-03-17T10:30:45Z", 17L); |
| testFunction("dayOfYear(a)", "2017-03-17T10:30:45Z", 76L); |
| testFunction("dayOfQuarter(a)", "2017-03-17T10:30:45Z", 76L); |
| testFunction("hour(a)", "2017-03-17T10:30:45Z", 10L); |
| testFunction("minute(a)", "2017-03-17T10:30:45Z", 30L); |
| testFunction("quarter(a)","2017-03-17T10:30:45Z", 1L); |
| testFunction("week(a)", "2017-03-17T10:30:45Z", 11L); |
| testFunction("second(a)", "2017-03-17T10:30:45Z", 45L); |
| testFunction("epoch(a)", "2017-03-17T10:30:45Z", 1489746645000l); |
| |
| testFunction("epoch(a)", new Date(1489746645500l).toInstant().toString(), 1489746645500l); |
| testFunction("epoch(a)", new Date(820454399990l).toInstant().toString(), 820454399990l); |
| |
| } |
| |
| @Test |
| public void testFunctionsOnDate() throws Exception { |
| Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.ROOT); |
| calendar.set(2017, 12, 5, 23, 59); |
| Date aDate = calendar.getTime(); |
| testFunction("year(a)", aDate, calendar.get(Calendar.YEAR)); |
| testFunction("month(a)", aDate, calendar.get(Calendar.MONTH)+1); |
| testFunction("day(a)", aDate, calendar.get(Calendar.DAY_OF_MONTH)); |
| testFunction("hour(a)", aDate, calendar.get(Calendar.HOUR_OF_DAY)); |
| testFunction("minute(a)", aDate, calendar.get(Calendar.MINUTE)); |
| testFunction("epoch(a)", aDate, aDate.getTime()); |
| } |
| |
| @Test |
| public void testFunctionsOnInstant() throws Exception { |
| Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.ROOT); |
| calendar.set(2017, 12, 5, 23, 59); |
| Date aDate = calendar.getTime(); |
| Instant instant = aDate.toInstant(); |
| testFunction("year(a)", instant, calendar.get(Calendar.YEAR)); |
| testFunction("month(a)", instant, calendar.get(Calendar.MONTH)+1); |
| testFunction("day(a)", instant, calendar.get(Calendar.DAY_OF_MONTH)); |
| testFunction("hour(a)", instant, calendar.get(Calendar.HOUR_OF_DAY)); |
| testFunction("minute(a)", instant, calendar.get(Calendar.MINUTE)); |
| testFunction("epoch(a)", instant, aDate.getTime()); |
| } |
| |
| @Test |
| public void testFunctionsLocalDateTime() throws Exception { |
| |
| LocalDateTime localDateTime = LocalDateTime.of(2017,12,5, 23, 59); |
| Date aDate = Date.from(localDateTime.atZone(ZoneOffset.UTC).toInstant()); |
| testFunction("year(a)", localDateTime, 2017); |
| testFunction("month(a)", localDateTime, 12); |
| testFunction("day(a)", localDateTime, 5); |
| testFunction("hour(a)", localDateTime, 23); |
| testFunction("minute(a)", localDateTime, 59); |
| testFunction("epoch(a)", localDateTime, aDate.getTime()); |
| } |
| |
| @Test |
| public void testFunctionsOnLong() throws Exception { |
| |
| Long longDate = 1512518340000l; |
| |
| testFunction("year(a)", longDate, 2017); |
| testFunction("month(a)", longDate, 12); |
| testFunction("day(a)", longDate, 5); |
| testFunction("hour(a)", longDate, 23); |
| testFunction("minute(a)", longDate, 59); |
| testFunction("second(a)", longDate, 0); |
| testFunction("epoch(a)", longDate, longDate); |
| |
| } |
| |
| @Test |
| public void testLimitedFunctions() throws Exception { |
| |
| MonthDay monthDay = MonthDay.of(12,5); |
| testFunction("month(a)", monthDay, 12); |
| testFunction("day(a)", monthDay, 5); |
| |
| try { |
| testFunction("year(a)", monthDay, 2017); |
| assertTrue(false); |
| } catch (IOException e) { |
| assertEquals("It is not possible to call 'year' function on java.time.MonthDay", e.getMessage()); |
| } |
| |
| YearMonth yearMonth = YearMonth.of(2018, 4); |
| testFunction("month(a)", yearMonth, 4); |
| testFunction("year(a)", yearMonth, 2018); |
| |
| try { |
| testFunction("day(a)", yearMonth, 5); |
| assertTrue(false); |
| } catch (IOException e) { |
| assertEquals("It is not possible to call 'day' function on java.time.YearMonth", e.getMessage()); |
| } |
| |
| } |
| |
| |
| public void testFunction(String expression, Object value, Number expected) throws Exception { |
| StreamEvaluator evaluator = factory.constructEvaluator(expression); |
| StreamContext streamContext = new StreamContext(); |
| evaluator.setStreamContext(streamContext); |
| values.clear(); |
| values.put("a", value); |
| Object result = evaluator.evaluate(new Tuple(values)); |
| assertTrue(result instanceof Number); |
| assertEquals(expected.longValue(), result); |
| } |
| |
| @Test |
| public void testExplain() throws IOException { |
| StreamExpression express = StreamExpressionParser.parse("month('myfield')"); |
| TemporalEvaluatorMonth datePartEvaluator = new TemporalEvaluatorMonth(express,factory); |
| Explanation explain = datePartEvaluator.toExplanation(factory); |
| assertEquals("month(myfield)", explain.getExpression()); |
| |
| express = StreamExpressionParser.parse("day(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbb)"); |
| TemporalEvaluatorDay dayPartEvaluator = new TemporalEvaluatorDay(express,factory); |
| explain = dayPartEvaluator.toExplanation(factory); |
| assertEquals("day(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbb)", explain.getExpression()); |
| } |
| } |