| /* |
| * 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.carbondata.core.preagg; |
| |
| import java.sql.Timestamp; |
| import java.util.ArrayList; |
| import java.util.Calendar; |
| import java.util.GregorianCalendar; |
| import java.util.List; |
| |
| import org.apache.carbondata.common.logging.LogServiceFactory; |
| import org.apache.carbondata.core.constants.CarbonCommonConstants; |
| import org.apache.carbondata.core.util.CarbonProperties; |
| |
| import org.apache.log4j.Logger; |
| |
| /** |
| * class for applying time-series udf |
| */ |
| public class TimeSeriesUDF { |
| |
| private static final Logger LOGGER = |
| LogServiceFactory.getLogService(TimeSeriesUDF.class.getName()); |
| |
| public final List<String> TIMESERIES_FUNCTION = new ArrayList<>(); |
| |
| // thread local for keeping calender instance |
| private ThreadLocal<Calendar> calenderThreadLocal = new ThreadLocal<>(); |
| |
| /** |
| * singleton instance |
| */ |
| public static final TimeSeriesUDF INSTANCE = new TimeSeriesUDF(); |
| |
| private TimeSeriesUDF() { |
| initialize(); |
| } |
| |
| /** |
| * Below method will be used to apply udf on data provided |
| * Method will work based on below logic. |
| * Data: 2016-7-23 01:01:30,10 |
| * Year Level UDF will return: 2016-1-1 00:00:00,0 |
| * Month Level UDF will return: 2016-7-1 00:00:00,0 |
| * Day Level UDF will return: 2016-7-23 00:00:00,0 |
| * Hour Level UDF will return: 2016-7-23 01:00:00,0 |
| * Minute Level UDF will return: 2016-7-23 01:01:00,0 |
| * Second Level UDF will return: 2016-7-23 01:01:30,0 |
| * If function does not match with any of the above functions |
| * it will throw IllegalArgumentException |
| * |
| * @param data timestamp data |
| * @param function time series function name |
| * @return data after applying udf |
| */ |
| public Timestamp applyUDF(Timestamp data, String function) { |
| if (null == data) { |
| return data; |
| } |
| initialize(); |
| Calendar calendar = calenderThreadLocal.get(); |
| calendar.clear(); |
| calendar.setTimeInMillis(data.getTime()); |
| TimeSeriesFunctionEnum timeSeriesFunctionEnum = |
| TimeSeriesFunctionEnum.valueOf(function.toUpperCase()); |
| switch (timeSeriesFunctionEnum) { |
| case SECOND: |
| calendar.set(Calendar.MILLISECOND, 0); |
| break; |
| case MINUTE: |
| calendar.set(Calendar.MILLISECOND, 0); |
| calendar.set(Calendar.SECOND, 0); |
| break; |
| case FIVE_MINUTE: |
| setData(calendar, 5); |
| break; |
| case TEN_MINUTE: |
| setData(calendar, 10); |
| break; |
| case FIFTEEN_MINUTE: |
| setData(calendar, 15); |
| break; |
| case THIRTY_MINUTE: |
| setData(calendar, 30); |
| break; |
| case WEEK: |
| calendar.set(Calendar.HOUR_OF_DAY, 0); |
| calendar.set(Calendar.MINUTE, 0); |
| calendar.set(Calendar.SECOND, 0); |
| calendar.set(Calendar.MILLISECOND, 0); |
| calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek()); |
| break; |
| case HOUR: |
| calendar.set(Calendar.MILLISECOND, 0); |
| calendar.set(Calendar.SECOND, 0); |
| calendar.set(Calendar.MINUTE, 0); |
| break; |
| case DAY: |
| calendar.set(Calendar.HOUR_OF_DAY, 0); |
| calendar.set(Calendar.MINUTE, 0); |
| calendar.set(Calendar.SECOND, 0); |
| calendar.set(Calendar.MILLISECOND, 0); |
| break; |
| case MONTH: |
| calendar.set(Calendar.MILLISECOND, 0); |
| calendar.set(Calendar.SECOND, 0); |
| calendar.set(Calendar.MINUTE, 0); |
| calendar.set(Calendar.HOUR_OF_DAY, 0); |
| calendar.set(Calendar.DAY_OF_MONTH, 1); |
| break; |
| case YEAR: |
| calendar.set(Calendar.MONTH, 1); |
| calendar.set(Calendar.DAY_OF_YEAR, 1); |
| calendar.set(Calendar.HOUR_OF_DAY, 0); |
| calendar.set(Calendar.MINUTE, 0); |
| calendar.set(Calendar.SECOND, 0); |
| calendar.set(Calendar.MILLISECOND, 0); |
| break; |
| default: |
| throw new IllegalArgumentException("Invalid time-series function name: " + function); |
| } |
| data.setTime(calendar.getTimeInMillis()); |
| return data; |
| } |
| |
| /** |
| * This method sets the calender data based on the interval time of granularity |
| */ |
| private void setData(Calendar calendar, int intervalTime) { |
| calendar.set(Calendar.MILLISECOND, 0); |
| calendar.set(Calendar.SECOND, 0); |
| calendar.set(Calendar.MINUTE, (calendar.get(Calendar.MINUTE) / intervalTime) * intervalTime); |
| } |
| |
| /** |
| * Below method will be used to initialize the thread local |
| */ |
| private void initialize() { |
| if (calenderThreadLocal.get() == null) { |
| calenderThreadLocal.set(new GregorianCalendar()); |
| } |
| if (TIMESERIES_FUNCTION.isEmpty()) { |
| TIMESERIES_FUNCTION.add("second"); |
| TIMESERIES_FUNCTION.add("minute"); |
| TIMESERIES_FUNCTION.add("five_minute"); |
| TIMESERIES_FUNCTION.add("ten_minute"); |
| TIMESERIES_FUNCTION.add("fifteen_minute"); |
| TIMESERIES_FUNCTION.add("thirty_minute"); |
| TIMESERIES_FUNCTION.add("hour"); |
| TIMESERIES_FUNCTION.add("day"); |
| TIMESERIES_FUNCTION.add("week"); |
| TIMESERIES_FUNCTION.add("month"); |
| TIMESERIES_FUNCTION.add("year"); |
| } |
| int firstDayOfWeek; |
| try { |
| firstDayOfWeek = DaysOfWeekEnum.valueOf(CarbonProperties.getInstance() |
| .getProperty(CarbonCommonConstants.CARBON_TIMESERIES_FIRST_DAY_OF_WEEK, |
| CarbonCommonConstants.CARBON_TIMESERIES_FIRST_DAY_OF_WEEK_DEFAULT).toUpperCase()) |
| .getOrdinal(); |
| } catch (IllegalArgumentException ex) { |
| LOGGER.warn("Invalid value set for first of the week. Considering the default value as: " |
| + CarbonCommonConstants.CARBON_TIMESERIES_FIRST_DAY_OF_WEEK_DEFAULT); |
| firstDayOfWeek = |
| DaysOfWeekEnum.valueOf(CarbonCommonConstants.CARBON_TIMESERIES_FIRST_DAY_OF_WEEK_DEFAULT) |
| .getOrdinal(); |
| } |
| calenderThreadLocal.get().setFirstDayOfWeek(firstDayOfWeek); |
| } |
| } |