/*
* Copyright (c) 2008, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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.wso2.carbon.billing.core.scheduler.scheduleHelpers;
import org.wso2.carbon.billing.core.BillingException;
import org.wso2.carbon.billing.core.jdbc.DataAccessObject;
import org.wso2.carbon.billing.core.scheduler.ScheduleHelper;
import org.wso2.carbon.billing.core.scheduler.SchedulerContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
public class MonthlyScheduleHelper implements ScheduleHelper {
private static final Log log = LogFactory.getLog(MonthlyScheduleHelper.class);
private static final String DAY_TO_TRIGGER_ON_KEY = "dayToTriggerOn";
private static final String HOUR_TO_TRIGGER_ON_KEY = "hourToTriggerOn";
private static final String MINUTE_TO_TRIGGER_ON_KEY = "minuteToTriggerOn";
private static final String CRON_KEY = "cron";
private static final String TIME_ZONE_KEY = "timeZone";
private static final String DEFAULT_TIMEZONE = "GMT-8:00";
int dayToTriggerOn;
int hourToTriggerOn;
int minuteToTriggerOn;
String cron;
TimeZone timeZone;
public void init(Map<String, String> triggerCalculatorConfig) throws BillingException {
String timeZoneStr = triggerCalculatorConfig.get(TIME_ZONE_KEY);
if (timeZoneStr == null) {
timeZoneStr = DEFAULT_TIMEZONE;
}
timeZone = TimeZone.getTimeZone(timeZoneStr);
//Timezone is important when comparing dates in sql queries
DataAccessObject.TIMEZONE = timeZoneStr;
String dayToTriggerOnStr = triggerCalculatorConfig.get(DAY_TO_TRIGGER_ON_KEY);
try {
dayToTriggerOn = Integer.parseInt(dayToTriggerOnStr);
} catch (NumberFormatException e) {
String msg = "The trigger on field currently support only numbers. " + "" +
"Invalid dayToTriggerOn " + dayToTriggerOnStr + ".";
log.error(msg, e);
throw new BillingException(msg, e);
}
String hourToTriggerOnStr = triggerCalculatorConfig.get(HOUR_TO_TRIGGER_ON_KEY);
try {
hourToTriggerOn = Integer.parseInt(hourToTriggerOnStr);
} catch (NumberFormatException e) {
String msg = "The trigger on field currently support only numbers. " +
"Invalid hourToTriggerOn " + hourToTriggerOnStr + ".";
log.error(msg, e);
throw new BillingException(msg, e);
}
String minuteToTriggerOnStr = triggerCalculatorConfig.get(MINUTE_TO_TRIGGER_ON_KEY);
try{
minuteToTriggerOn = Integer.parseInt(minuteToTriggerOnStr);
}catch (NumberFormatException e){
String msg = "The trigger on field currently support only numbers. " +
"Invalid minuteToTriggerOn " + minuteToTriggerOnStr + ".";
log.error(msg, e);
throw new BillingException(msg, e);
}
cron = triggerCalculatorConfig.get(CRON_KEY);
log.debug("Cron string: " + cron);
}
public void invoke(SchedulerContext schedulerContext) throws BillingException {
// getting the next trigger interval
long currentTime = new Date().getTime();
invoke(schedulerContext, currentTime);
}
public void invoke(SchedulerContext schedulerContext, long currentTime) {
// getting the next trigger interval
schedulerContext.setNextTriggerInterval(getNextTriggerInterval(currentTime));
schedulerContext.setCurrentDurationStart(getCurrentDurationStart(currentTime));
schedulerContext.setCurrentDurationEnd(getCurrentDurationEnd(currentTime));
schedulerContext.setDurationString(getMonthString(currentTime));
schedulerContext.setCronString(cron);
}
private long getNextTriggerInterval(long currentTime) {
Calendar nextTriggerDate = Calendar.getInstance(timeZone);
nextTriggerDate.setTimeInMillis(currentTime);
nextTriggerDate.set(Calendar.DAY_OF_MONTH, dayToTriggerOn);
nextTriggerDate.set(Calendar.HOUR_OF_DAY, hourToTriggerOn);
nextTriggerDate.set(Calendar.MINUTE, minuteToTriggerOn);
nextTriggerDate.set(Calendar.SECOND, 0);
Calendar now = Calendar.getInstance(timeZone);
now.setTimeInMillis(currentTime);
if(now.after(nextTriggerDate)){
nextTriggerDate.add(Calendar.MONTH, 1);
}
long nextToTriggerTime = nextTriggerDate.getTimeInMillis();
return nextToTriggerTime - currentTime;
}
private long getCurrentDurationStart(long currentTime) {
// starting building a calendar from the current calendar
Calendar newCalendar = Calendar.getInstance(timeZone);
newCalendar.setTimeInMillis(currentTime);
newCalendar.add(Calendar.MONTH, -1);
newCalendar.set(Calendar.DAY_OF_MONTH, dayToTriggerOn);
newCalendar.set(Calendar.HOUR_OF_DAY, hourToTriggerOn);
newCalendar.set(Calendar.MINUTE, 0);
newCalendar.set(Calendar.SECOND, 0);
long currentDurationStart = newCalendar.getTimeInMillis();
return currentDurationStart;
}
private long getCurrentDurationEnd(long currentTime) {
// starting building a calendar from the current calendar
Calendar newCalendar = Calendar.getInstance(timeZone);
newCalendar.setTimeInMillis(currentTime);
newCalendar.set(Calendar.DAY_OF_MONTH, dayToTriggerOn);
newCalendar.set(Calendar.HOUR_OF_DAY, hourToTriggerOn);
newCalendar.set(Calendar.MINUTE, minuteToTriggerOn);
newCalendar.set(Calendar.SECOND, 0);
// and then we are reducing one second to go to the end of the period
newCalendar.add(Calendar.SECOND, -1);
long currentDurationEnd = newCalendar.getTimeInMillis();
return currentDurationEnd;
}
private String getMonthString(long currentTime) {
Calendar calendar = Calendar.getInstance(timeZone);
calendar.setTimeInMillis(currentTime);
calendar.add(Calendar.MONTH, -1);
int currentMonth = calendar.get(Calendar.MONTH);
String[] monthArr = new DateFormatSymbols().getMonths();
String month = monthArr[currentMonth];
return calendar.get(Calendar.YEAR) + "-" + month;
}
}