All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.eBusx.util.TimerRequest Maven / Gradle / Ivy

//
// Copyright 2012, 2013, 2015, 2016, 2019, 2020 Charles W. Rapp
//
// 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 net.sf.eBusx.util;

import com.google.common.base.Strings;
import java.io.Serializable;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import net.sf.eBus.messages.ELocalOnly;
import net.sf.eBus.messages.EReplyInfo;
import net.sf.eBus.messages.ERequestMessage;
import net.sf.eBus.util.Validator;

/**
 * Send this request to schedule a timer task. Each timer request
 * must have a unique name, that is, no two timer requests
 * currently running must have the same name. Timer
 * requests come in four kinds:
 * 
    *
  1. *
    TimerRequest.builder()
     *            .timerName("name")
     *            .time(Instant)
     *            .build()
    * a one-shot timer scheduled to expire on a given date and * time. *
  2. *
  3. *
    TimerRequest.builder()
     *            .timerName("name")
     *            .delay(long)
     *            .build()
    * a one-shot timer scheduled to expire after the specified * millisecond delay. *
  4. *
  5. *
    TimerRequest.builder()
     *            .timerName("name")
     *            .time(Instant)
     *            .period(long)
     *            .fixedRate(boolean)
     *            .build()
    * a repeating timer which first expires on a given date and * time and after that on a periodic millisecond rate. If the * {@code fixedRate} parameter is {@code true}, then the * timer is scheduled using * {@link java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, Date, long)}. * Otherwise, the timer is scheduled using * {@link java.util.Timer#schedule(java.util.TimerTask, Date, long)}. *
  6. *
  7. *
    TimerRequest.builder()
     *            .timerName("name")
     *            .delay(long)
     *            .period(long)
     *            .fixedRate(boolean)
     *            .build()
    * a repeating timer which first expires after a specified * millisecond delay and then on a periodic millisecond rate. * if {@code fixedRate} parameter is {@code true}, then the * timer is scheduled using * {@link java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, Date, long)}. * Otherwise, the timer is scheduled using * {@link java.util.Timer#schedule(java.util.TimerTask, Date, long)}. *
  8. *
* * @author Charles Rapp */ @EReplyInfo (replyMessageClasses = {TimerReply.class}) @ELocalOnly public final class TimerRequest extends ERequestMessage implements Serializable { //--------------------------------------------------------------- // Member data. // //----------------------------------------------------------- // Constants. // /** * Serialization version identifier. */ private static final long serialVersionUID = 0x050200L; //----------------------------------------------------------- // Locals. // /** * The requestor-assigned name for this timer request. */ public final String timerName; /** * If this timer is to expire at a given time, then set this * value. Otherwise, set to {@code null} and specify a * {@link #delay}. */ public final Instant time; /** * If this timer is to expire after a millisecond delay, then * set this value. Otherwise, set to zero and specify a * {@link #time}. */ public final long delay; /** * If this timer is repeating, then set this millisecond * period. Otherwise, set to zero for a one shot timer. */ public final long period; /** * If {@code true}, then repeating timers are run using fixed * rate scheduling. * @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, Date, long) * @see java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long, long) */ public final boolean fixedRate; //--------------------------------------------------------------- // Member methods. // //----------------------------------------------------------- // Constructors. // /** * Creates a timer request based on the builder * configuration. * @param builder contains request configuration. */ private TimerRequest(final Builder builder) { super (builder); this.timerName = builder.mTimerName; this.time = builder.mTime; this.delay = builder.mDelay; this.period = builder.mPeriod; this.fixedRate = builder.mFixedRate; } // end of TimerRequest(Builder) // // end of Constructors. //----------------------------------------------------------- //----------------------------------------------------------- // Object Method Overrides. // /** * Returns a textual representation of this timer request * message. * @return the request message as text. */ @Override public String toString() { final StringBuilder retval = new StringBuilder(); retval.append(super.toString()) .append("\n timer expires "); // Is this a time-based expiration? if (time != null) { // Yes. final DateTimeFormatter format = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM); retval.append(format.format(time)); } // No, this is a millisecond delay expiration. else { retval.append("in") .append(delay) .append( " milliseconds"); } // Does this timer have a repeating period? if (period > 0L) { // Yes. retval.append(", repeating every ") .append(period) .append(" milliseconds."); } // No. else { retval.append('.'); } return (retval.toString()); } // end of toString() // // end of Object Method Overrides. //----------------------------------------------------------- /** * Returns a timer request builder instance. * @return message builder instance. */ public static Builder builder() { return (new Builder()); } // end of builder() //--------------------------------------------------------------- // Inner classes. // /** * {@code TimerRequest} builder. A {@code Builder} instance * is obtained by calling {@link TimerRequest#builder()}. */ public static final class Builder extends ERequestMessage.Builder { //----------------------------------------------------------- // Member data. // //------------------------------------------------------- // Locals. // private String mTimerName; private Instant mTime; private long mDelay; private long mPeriod; private boolean mFixedRate; //----------------------------------------------------------- // Member methods. // //------------------------------------------------------- // Constructors. // private Builder() { super (TimerRequest.class); mDelay = Long.MIN_VALUE; mPeriod = 0L; this.subject(ETimer.TIMER_SUBJECT); } // end of Builder() // // end of Constructors. //------------------------------------------------------- //------------------------------------------------------- // Builder Method Overrides. // /** * Returns a new {@code TimerRequest} instance based on * the builder's current configuration. This method is * called only after the builder configuration is * successfully validated. * @return new {@code TimerRequest} instance. */ @Override protected TimerRequest buildImpl() { return (new TimerRequest(this)); } // end of buildImpl() /** * Validates current builder configuration prior to * building the {@code TimerRequest} instance. A valid * configuration requires that: *
    *
  • * timer name is set and *
  • *
  • * either time or delay set but not both. *
  • *
* @param problems add configuration problems to this * {@code Validator}. * @return {@code problems} to allow for * {@code Validator} method chaining. */ @Override protected Validator validate(final Validator problems) { // The following parameter combinations are allowed: // + Time only, // + Time and period, // + Delay only, and // + Delay and period. // This means that either the time or the delay must // be set. return (super.validate(problems) .requireNotNull(mTimerName, "timerName") .requireTrue( (v1, v2) -> (v1 != null || v2 >= 0L), mTime, mDelay, "time", "delay", "either time or delay must be set") .requireTrue( (v1, v2) -> (v1 == null || v2 < 0L), mTime, mDelay, "time", "delay", "time and delay parameters cannot both be set")); } // end of validate(Validator) // // end of Builder Method Overrides. //------------------------------------------------------- //------------------------------------------------------- // Set Methods. // /** * Sets the timer name. * @param name timer name. * @return {@code this TimerReply} builder. * @throws IllegalArgumentException * if {@code name} is {@code null} or empty. */ public Builder timerName(final String name) { if (Strings.isNullOrEmpty(name)) { throw ( new IllegalArgumentException( "name is null or empty")); } mTimerName = name; return (this); } // end of timerName(String) public Builder time(final Instant time) { if (time == null) { throw (new NullPointerException("time is null")); } if ((Instant.now()).compareTo(time) > 0) { throw ( new IllegalArgumentException( "time in the past")); } mTime = time; return (this); } // end of time(Instant) public Builder delay(final long delay) { if (delay < 0L) { throw ( new IllegalArgumentException( "delay < zero")); } mDelay = delay; return (this); } // end of delay(long) public Builder period(final long period) { if (period <= 0L) { throw ( new IllegalArgumentException( "period <= zero")); } mPeriod = period; return (this); } // end of period(long) public Builder fixedRate(final boolean flag) { mFixedRate = flag; return (this); } // end of fixedRate(boolean) // // end of Set Methods. //------------------------------------------------------- } // end of class Builder } // end of class TimerRequest




© 2015 - 2024 Weber Informatics LLC | Privacy Policy