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

org.perfcake.message.sequence.NumberSequence Maven / Gradle / Ivy

/*
 * -----------------------------------------------------------------------\
 * PerfCake
 *  
 * Copyright (C) 2010 - 2016 the original author or authors.
 *  
 * 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.perfcake.message.sequence;

import org.perfcake.PerfCakeException;

import java.util.Properties;

/**
 * Simple sequence of numbers.
 * Can go in both directions, can specify boundaries and a step.
 *
 * @author Martin Večeřa
 */
public class NumberSequence implements Sequence {

   /**
    * Beginning of the sequence.
    */
   private long start = 0;

   /**
    * Last number of the sequence.
    */
   private long end = Long.MIN_VALUE;

   /**
    * Step in the sequence.
    */
   private long step = 1;

   /**
    * Current sequence value.
    */
   private long value = 0;

   /**
    * True when we should cycle over from the beginning when we reached the end.
    */
   private boolean cycle = true;

   @Override
   public final synchronized void publishNext(final String sequenceId, final Properties values) {
      final long res = value;
      final boolean internalCycle = isCycle();

      long newValue = value + step;

      if (step > 0) {
         if (newValue < value && end > Long.MIN_VALUE) { // overflow
            if (!internalCycle) {
               newValue = Long.MAX_VALUE;
            }
         }

         value = newValue;

         if (end > Long.MIN_VALUE && value > end) {
            if (internalCycle) {
               value = start;
            } else {
               value = end;
            }
         }
      } else {
         if (newValue > value && end < Long.MAX_VALUE) { // underflow
            if (!internalCycle) {
               newValue = Long.MIN_VALUE;
            }
         }

         value = newValue;

         if (end < Long.MAX_VALUE && value < end) {
            if (internalCycle) {
               value = start;
            } else {
               value = end;
            }
         }

      }

      values.setProperty(sequenceId, Long.toString(res));
   }

   @Override
   public synchronized void reset() throws PerfCakeException {
      value = getStart();
   }

   /**
    * Gets the beginning of the sequence.
    *
    * @return The beginning of the sequence.
    */
   public long getStart() {
      return start;
   }

   /**
    * Sets the beginning of the sequence.
    *
    * @param start
    *       The beginning of the sequence.
    * @return Instance of this to support fluent API.
    */
   public NumberSequence setStart(final long start) {
      this.start = start;
      return this;
   }

   /**
    * Gets the last value in the sequence.
    *
    * @return The last value in the sequence.
    */
   public long getEnd() {
      return end;
   }

   /**
    * Sets the last value in the sequence.
    * Set to {@link Long#MIN_VALUE} in case of positive steps (or to {@link Long#MAX_VALUE} in case of negative steps) to disable check of the last value in the interval.
    *
    * @param end
    *       The last value in the sequence.
    * @return Instance of this to support fluent API.
    */
   public NumberSequence setEnd(final long end) {
      this.end = end;
      return this;
   }

   /**
    * Gets the step size.
    *
    * @return The step size.
    */
   public long getStep() {
      return step;
   }

   /**
    * Sets the step size. If the check for the last value of the interval is disabled, this configuration is preserved even for step with negative numbers.
    *
    * @param step
    *       The step size.
    * @return Instance of this to support fluent API.
    */
   public NumberSequence setStep(final long step) {
      if (step < 0 && end == Long.MIN_VALUE) {
         end = Long.MAX_VALUE;
      } else if (step > 0 && end == Long.MAX_VALUE) {
         end = Long.MIN_VALUE;
      }

      this.step = step;
      return this;
   }

   /**
    * Determines whether the sequence cycles around (starts from the beginning after reaching the last value).
    *
    * @return True if and only if the sequence cycles around.
    */
   public boolean isCycle() {
      return cycle;
   }

   /**
    * Specifies whether the sequence cycles around (starts from the beginning after reaching the last value).
    *
    * @param cycle
    *       True to allow the sequence to cycle around.
    * @return Instance of this to support fluent API.
    */
   public NumberSequence setCycle(final boolean cycle) {
      this.cycle = cycle;
      return this;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy