org.eclipse.gyrex.jobs.internal.schedules.ScheduleEntryImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.gyrex.jobs.internal.schedules.ScheduleEntryImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2011, 2013 AGETO Service GmbH and others.
 * All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 *
 * Contributors:
 *     Gunnar Wagenknecht - initial API and implementation
 *     Mike Tschierschke - improvements due working on https://bugs.eclipse.org/bugs/show_bug.cgi?id=344467
 *******************************************************************************/
package org.eclipse.gyrex.jobs.internal.schedules;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import org.eclipse.gyrex.common.identifiers.IdHelper;
import org.eclipse.gyrex.jobs.internal.scheduler.Schedule;
import org.eclipse.gyrex.jobs.schedules.IScheduleEntry;
import org.eclipse.gyrex.jobs.schedules.manager.IScheduleEntryWorkingCopy;

import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;

import org.apache.commons.lang.StringUtils;

import org.quartz.CronExpression;

/**
 *
 */
public class ScheduleEntryImpl implements IScheduleEntry, IScheduleEntryWorkingCopy {

    private static final char SEPARATOR_CHAR = ',';

    private static final String PARAMETER = "parameter";

    private static final String JOB_TYPE_ID = "jobTypeId";
    private static final String CRON_EXPRESSION = "cronExpression";
    private static final String ENABLED = "enabled";
    private static final String PRECEDING_ENTRIES = "precedingEntries";
    private static final String QUEUE_ID = "queueId";

    private static void setIfNotNullOrRemoveIfNull(final Preferences node, final String key, final String value) {
        if (value != null) {
            node.put(key, value);
        } else {
            node.remove(key);
        }
    }

    public static void validateCronExpression(final String expression) throws IllegalArgumentException {
        final String[] tokens = StringUtils.split(expression);
        if ((tokens.length < 5) || (tokens.length > 6))
            throw new IllegalArgumentException(
                    "A cron expression must consist of five to six tokens (<Minute> <Hour> <Day_of_the_Month> <Month_of_the_Year> <Day_of_the_Week> <Year>).");

        if (CronExpression.isValidExpression(Schedule.asQuartzCronExpression(expression)))
            return;

        try {
            new CronExpression(Schedule.asQuartzCronExpression(expression));

            // no exception but still invalid
            throw new IllegalArgumentException("invalid cron expression: " + expression);
        } catch (final ParseException e) {
            throw new IllegalArgumentException(e.getMessage(), e);
        }
    }

    private final String id;
    private ScheduleImpl schedule;
    private boolean enabled;
    private String cronExpression;
    private String jobTypeId;
    private Map<String, String> jobParamater;
    private String queueId;

    private Collection<String> precedingEntries;

    /**
     * Creates a new instance.
     * 
     * @param id
     * @param schedule
     */
    public ScheduleEntryImpl(final String id, final ScheduleImpl schedule) {
        this.schedule = schedule;
        if (!IdHelper.isValidId(id))
            throw new IllegalArgumentException("invalid entry id");
        this.id = id;
        enabled = true; // default is enabled (backwards compatibility)
    }

    @Override
    public String getCronExpression() {
        return cronExpression;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public String getJobId() {
        return schedule.getId().concat("__entry__").concat(id);
    }

    @Override
    public Map<String, String> getJobParameter() {
        if (null != jobParamater)
            return Collections.unmodifiableMap(jobParamater);
        return Collections.emptyMap();
    }

    @Override
    public String getJobTypeId() {
        return jobTypeId;
    }

    @Override
    public Collection<String> getPrecedingEntries() {
        final Collection<String> ids = precedingEntries;
        if (ids == null)
            return Collections.emptyList();

        return Collections.unmodifiableCollection(ids);
    }

    @Override
    public String getQueueId() {
        return queueId;
    }

    @Override
    public ScheduleImpl getSchedule() {
        return schedule;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    void load(final Preferences node) throws BackingStoreException {
        try {
            setJobTypeId(node.get(JOB_TYPE_ID, null));
            setEnabled(node.getBoolean(ENABLED, true /* default true (backwards compatibility) */));
            if (node.nodeExists(PARAMETER)) {
                final Preferences paramNode = node.node(PARAMETER);
                final String[] keys = paramNode.keys();
                jobParamater = new HashMap<String, String>(keys.length);
                for (final String key : keys) {
                    jobParamater.put(key, paramNode.get(key, null));
                }
            }
            final String expression = node.get(CRON_EXPRESSION, null);
            if (expression != null) {
                setCronExpression(expression);
            }
            setQueueId(node.get(QUEUE_ID, null));
            setPrecedingEntries(StringUtils.split(node.get(PRECEDING_ENTRIES, null), SEPARATOR_CHAR));
        } catch (final IllegalArgumentException e) {
            throw new BackingStoreException(String.format("Unable to load entry '%s'. %s", id, e.getMessage()), e);
        }
    }

    void saveWithoutFlush(final Preferences node) throws BackingStoreException {
        // ensure required values are set
        setJobTypeId(jobTypeId);

        node.put(JOB_TYPE_ID, jobTypeId);
        node.putBoolean(ENABLED, enabled);

        if ((null != jobParamater) && !jobParamater.isEmpty()) {
            final Preferences paramNode = node.node(PARAMETER);
            // remove obsolete keys
            for (final String key : paramNode.keys()) {
                if (StringUtils.isBlank(jobParamater.get(key))) {
                    paramNode.remove(key);
                }
            }
            // add updated/new paramas
            for (final String key : jobParamater.keySet()) {
                final String value = jobParamater.get(key);
                if (StringUtils.isNotBlank(value)) {
                    paramNode.put(key, value);
                }
            }
        } else if (node.nodeExists(PARAMETER)) {
            node.node(PARAMETER).removeNode();
        }

        if (cronExpression != null) {
            node.put(CRON_EXPRESSION, cronExpression);
        } else {
            node.remove(CRON_EXPRESSION);
        }

        setIfNotNullOrRemoveIfNull(node, CRON_EXPRESSION, cronExpression);
        setIfNotNullOrRemoveIfNull(node, QUEUE_ID, queueId);
        setIfNotNullOrRemoveIfNull(node, PRECEDING_ENTRIES, StringUtils.join(precedingEntries, SEPARATOR_CHAR));
    }

    @Override
    public void setCronExpression(final String cronExpression) {
        if (StringUtils.isNotBlank(cronExpression)) {
            validateCronExpression(cronExpression);
        }

        this.cronExpression = cronExpression;
    }

    /**
     * Sets the enabled flag.
     * 
     * @param enabled
     *            the enabled flag to set
     */
    @Override
    public void setEnabled(final boolean enabled) {
        this.enabled = enabled;
    }

    @Override
    public void setJobParameter(final Map<String, String> jobParameter) {
        // wrap map (to create a clone)
        jobParamater = null != jobParameter ? new HashMap<String, String>(jobParameter) : null;
    }

    @Override
    public void setJobTypeId(final String jobTypeId) {
        if (!IdHelper.isValidId(jobTypeId))
            throw new IllegalArgumentException("invalid type id");
        this.jobTypeId = jobTypeId;
    }

    @Override
    public void setPrecedingEntries(final String... scheduleEntryIds) throws IllegalArgumentException {
        if ((scheduleEntryIds == null) || (scheduleEntryIds.length == 0)) {
            precedingEntries = null;
        } else {
            final ArrayList<String> list = new ArrayList<>(scheduleEntryIds.length);

            for (int i = 0; i < scheduleEntryIds.length; i++) {
                if (!IdHelper.isValidId(scheduleEntryIds[i]))
                    throw new IllegalArgumentException(
                            "invalid schedule entry id at index " + i + ": " + scheduleEntryIds[i]);
                list.add(scheduleEntryIds[i]);
            }
            // check for loops
            final LinkedList<String> sequence = new LinkedList<>();
            sequence.add(id);
            ScheduleImpl.checkExecutionSequenceForLoops(this, sequence, list);

            // set
            precedingEntries = list;
        }

    }

    @Override
    public void setQueueId(final String queueId) throws IllegalArgumentException {
        if ((queueId != null) && !IdHelper.isValidId(queueId))
            throw new IllegalArgumentException("invalide queue id: " + queueId);
        this.queueId = queueId;

    }

    public void setSchedule(final ScheduleImpl schedule) {
        this.schedule = schedule;
    }

    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder();
        builder.append("ScheduleEntryImpl [id=").append(id).append(", cronExpression=").append(cronExpression)
                .append(", jobProviderId=").append(jobTypeId).append(", jobParamater=").append(jobParamater)
                .append("]");
        return builder.toString();
    }
}