/**
* 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.apache.aurora.scheduler.cron.quartz;
import java.text.ParseException;
import java.util.List;
import java.util.TimeZone;
import com.google.common.base.Joiner;
import com.google.common.collect.ContiguousSet;
import com.google.common.collect.DiscreteDomain;
import com.google.common.collect.Lists;
import com.google.common.collect.Range;
import org.apache.aurora.scheduler.base.JobKeys;
import org.apache.aurora.scheduler.cron.CrontabEntry;
import org.apache.aurora.scheduler.storage.entities.IJobKey;
import org.quartz.CronExpression;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.TriggerBuilder;
import static java.util.Objects.requireNonNull;
/**
* Utilities for converting Aurora datatypes to Quartz datatypes.
*/
final class Quartz {
private Quartz() {
// Utility class.
}
/**
* Convert an Aurora CrontabEntry to a Quartz CronExpression.
*/
static CronExpression cronExpression(CrontabEntry entry, TimeZone timeZone) {
String dayOfMonth;
if (entry.hasWildcardDayOfMonth()) {
dayOfMonth = "?"; // special quartz token meaning "don't care"
} else {
dayOfMonth = entry.getDayOfMonthAsString();
}
String dayOfWeek;
if (entry.hasWildcardDayOfWeek() && !entry.hasWildcardDayOfMonth()) {
dayOfWeek = "?";
} else {
List<Integer> daysOfWeek = Lists.newArrayList();
for (Range<Integer> range : entry.getDayOfWeek().asRanges()) {
for (int i : ContiguousSet.create(range, DiscreteDomain.integers())) {
daysOfWeek.add(i + 1); // Quartz has an off-by-one with what the "standard" defines.
}
}
dayOfWeek = Joiner.on(",").join(daysOfWeek);
}
String rawCronExpresion = String.join(
" ",
"0",
entry.getMinuteAsString(),
entry.getHourAsString(),
dayOfMonth,
entry.getMonthAsString(),
dayOfWeek);
CronExpression cronExpression;
try {
cronExpression = new CronExpression(rawCronExpresion);
} catch (ParseException e) {
throw new RuntimeException(e);
}
cronExpression.setTimeZone(timeZone);
return cronExpression;
}
/**
* Convert a Quartz JobKey to an Aurora IJobKey.
*/
static IJobKey auroraJobKey(JobKey jobKey) {
return JobKeys.parse(jobKey.getName());
}
/**
* Convert an Aurora IJobKey to a Quartz JobKey.
*/
static JobKey jobKey(IJobKey jobKey) {
return JobKey.jobKey(JobKeys.canonicalString(jobKey));
}
static CronTrigger cronTrigger(CrontabEntry schedule, TimeZone timeZone) {
return TriggerBuilder.newTrigger()
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression(schedule, timeZone)))
.withDescription(schedule.toString())
.build();
}
static JobDetail jobDetail(IJobKey jobKey, Class<? extends Job> jobClass) {
requireNonNull(jobKey);
requireNonNull(jobClass);
return JobBuilder.newJob(jobClass)
.withIdentity(jobKey(jobKey))
.build();
}
static CrontabEntry crontabEntry(CronTrigger cronTrigger) {
return CrontabEntry.parse(cronTrigger.getDescription());
}
}