/*
* Copyright (c) 2014 Ngewi Fet <ngewif@gmail.com>
*
* Licensed 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.gnucash.android.ui.util;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.format.Time;
import com.codetroopers.betterpickers.recurrencepicker.EventRecurrence;
import org.gnucash.android.model.PeriodType;
import org.gnucash.android.model.Recurrence;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
/**
* Parses {@link EventRecurrence}s to generate
* {@link org.gnucash.android.model.ScheduledAction}s
*
* @author Ngewi Fet <ngewif@gmail.com>
*/
public class RecurrenceParser {
//these are time millisecond constants which are used for scheduled actions.
//they may not be calendar accurate, but they serve the purpose for scheduling approximate time for background service execution
public static final long SECOND_MILLIS = 1000;
public static final long MINUTE_MILLIS = 60 * SECOND_MILLIS;
public static final long HOUR_MILLIS = 60 * MINUTE_MILLIS;
public static final long DAY_MILLIS = 24 * HOUR_MILLIS;
public static final long WEEK_MILLIS = 7 * DAY_MILLIS;
public static final long MONTH_MILLIS = 30 * DAY_MILLIS;
public static final long YEAR_MILLIS = 12 * MONTH_MILLIS;
/**
* Parse an {@link EventRecurrence} into a {@link Recurrence} object
* @param eventRecurrence EventRecurrence object
* @return Recurrence object
*/
public static Recurrence parse(EventRecurrence eventRecurrence){
if (eventRecurrence == null)
return null;
PeriodType periodType;
switch(eventRecurrence.freq){
case EventRecurrence.HOURLY:
periodType = PeriodType.HOUR;
break;
case EventRecurrence.DAILY:
periodType = PeriodType.DAY;
break;
case EventRecurrence.WEEKLY:
periodType = PeriodType.WEEK;
break;
case EventRecurrence.MONTHLY:
periodType = PeriodType.MONTH;
break;
case EventRecurrence.YEARLY:
periodType = PeriodType.YEAR;
break;
default:
periodType = PeriodType.MONTH;
break;
}
int interval = eventRecurrence.interval == 0 ? 1 : eventRecurrence.interval; //bug from betterpickers library sometimes returns 0 as the interval
Recurrence recurrence = new Recurrence(periodType);
recurrence.setMultiplier(interval);
parseEndTime(eventRecurrence, recurrence);
recurrence.setByDays(parseByDay(eventRecurrence.byday));
if (eventRecurrence.startDate != null)
recurrence.setPeriodStart(new Timestamp(eventRecurrence.startDate.toMillis(false)));
return recurrence;
}
/**
* Parses the end time from an EventRecurrence object and sets it to the <code>scheduledEvent</code>.
* The end time is specified in the dialog either by number of occurrences or a date.
* @param eventRecurrence Event recurrence pattern obtained from dialog
* @param recurrence Recurrence event to set the end period to
*/
private static void parseEndTime(EventRecurrence eventRecurrence, Recurrence recurrence) {
if (eventRecurrence.until != null && eventRecurrence.until.length() > 0) {
Time endTime = new Time();
endTime.parse(eventRecurrence.until);
recurrence.setPeriodEnd(new Timestamp(endTime.toMillis(false)));
} else if (eventRecurrence.count > 0){
recurrence.setPeriodEnd(eventRecurrence.count);
}
}
/**
* Parses an array of byDay values to return a list of days of week
* constants from {@link Calendar}.
*
* <p>Currently only supports byDay values for weeks.</p>
*
* @param byDay Array of byDay values
* @return list of days of week constants from Calendar.
*/
private static @NonNull List<Integer> parseByDay(@Nullable int[] byDay) {
if (byDay == null) {
return Collections.emptyList();
}
List<Integer> byDaysList = new ArrayList<>(byDay.length);
for (int day : byDay) {
byDaysList.add(EventRecurrence.day2CalendarDay(day));
}
return byDaysList;
}
}