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

io.hyperfoil.core.steps.SetAction Maven / Gradle / Ivy

There is a newer version: 0.27.1
Show newest version
package io.hyperfoil.core.steps;

import java.util.Objects;
import java.util.stream.Stream;

import org.kohsuke.MetaInfServices;

import io.hyperfoil.api.config.BenchmarkDefinitionException;
import io.hyperfoil.api.config.InitFromParam;
import io.hyperfoil.api.config.Name;
import io.hyperfoil.api.session.Access;
import io.hyperfoil.api.session.Action;
import io.hyperfoil.api.session.ResourceUtilizer;
import io.hyperfoil.api.session.Session;
import io.hyperfoil.core.session.IntVar;
import io.hyperfoil.core.session.ObjectVar;
import io.hyperfoil.core.session.SessionFactory;
import io.hyperfoil.function.SerializableConsumer;
import io.hyperfoil.function.SerializableFunction;

public class SetAction implements Action, ResourceUtilizer {
   private final Access var;
   private final SerializableFunction valueSupplier;

   public SetAction(String var, SerializableFunction valueSupplier) {
      this.var = SessionFactory.access(var);
      this.valueSupplier = valueSupplier;
   }

   @Override
   public void run(Session session) {
      var.setObject(session, valueSupplier.apply(session));
   }

   @Override
   public void reserve(Session session) {
      var.declareObject(session);
      ResourceUtilizer.reserve(session, valueSupplier);
   }

   /**
    * Set variable in session to certain value.
    */
   @MetaInfServices(Action.Builder.class)
   @Name("set")
   public static class Builder implements InitFromParam, Action.Builder {
      private String var;
      private Object value;
      private ObjectArrayBuilder objectArray;
      private IntArrayBuilder intArray;

      public Builder() {
      }

      /**
       * @param param Use var <- value.
       * @return Self.
       */
      @Override
      public Builder init(String param) {
         int sep = param.indexOf("<-");
         if (sep < 0) {
            throw new BenchmarkDefinitionException("Invalid inline definition '" + param + "': should be 'var <- value'");
         }
         this.var = param.substring(0, sep).trim();
         Object value = param.substring(sep + 2).trim();
         this.value = value;
         return this;
      }

      /**
       * Variable name.
       *
       * @param var Variable name.
       * @return Self.
       */
      public Builder var(String var) {
         this.var = var;
         return this;
      }

      /**
       * String value.
       *
       * @param value Value.
       * @return Self.
       */
      public Builder value(String value) {
         this.value = value;
         return this;
      }

      /**
       * Set variable to an (unset) object array.
       *
       * @return Builder.
       */
      public ObjectArrayBuilder objectArray() {
         return objectArray = new ObjectArrayBuilder(this);
      }

      /**
       * Set variable to an (unset) integer array.
       *
       * @return Builder.
       */
      public IntArrayBuilder intArray() {
         return intArray = new IntArrayBuilder(this);
      }

      @Override
      public SetAction build() {
         if (var == null) {
            throw new BenchmarkDefinitionException("Variable name was not set!");
         }
         if (Stream.of(value, objectArray, intArray).filter(Objects::nonNull).count() != 1) {
            throw new BenchmarkDefinitionException("Must set exactly on of: value, objectArray, intArray");
         }
         if (value != null) {
            Object myValue = value;
            return new SetAction(var, s -> myValue);
         } else if (objectArray != null) {
            return new SetAction(var, objectArray.build());
         } else {
            return new SetAction(var, intArray.build());
         }
      }
   }

   private static class ValueResource implements Session.Resource {
      private T object;

      public ValueResource(T o) {
         this.object = o;
      }
   }

   private static class ValueSupplier implements SerializableFunction, Session.ResourceKey>, ResourceUtilizer {
      private final SerializableFunction supplier;
      private final SerializableConsumer reset;

      private ValueSupplier(SerializableFunction supplier, SerializableConsumer reset) {
         this.supplier = supplier;
         this.reset = reset;
      }

      @Override
      public Object apply(Session session) {
         T object = session.getResource(this).object;
         reset.accept(object);
         return object;
      }

      @Override
      public void reserve(Session session) {
         session.declareResource(this, new ValueResource<>(supplier.apply(session)));
      }
   }

   public abstract static class BaseArrayBuilder> {
      protected final Builder parent;
      protected int size;

      BaseArrayBuilder(Builder parent) {
         this.parent = parent;
      }

      /**
       * Size of the array.
       *
       * @param size Array size.
       * @return Self.
       */
      @SuppressWarnings("unchecked")
      public S size(int size) {
         this.size = size;
         return (S) this;
      }

      public Builder end() {
         return parent;
      }

      protected int ensurePositiveSize() {
         if (size <= 0) {
            throw new BenchmarkDefinitionException("Size must be positive!");
         }
         return size;
      }

      protected static void resetArray(Session.Var[] array) {
         for (int i = 0; i < array.length; ++i) {
            array[i].unset();
         }
      }
   }

   /**
    * Creates object arrays to be stored in the session.
    */
   public static class ObjectArrayBuilder extends BaseArrayBuilder {

      public ObjectArrayBuilder(Builder parent) {
         super(parent);
      }

      private ValueSupplier build() {
         // prevent capturing this object reference in the lambda
         int mySize = ensurePositiveSize();
         return new ValueSupplier<>(session -> ObjectVar.newArray(session, mySize), BaseArrayBuilder::resetArray);
      }
   }

   /**
    * Creates integer arrays to be stored in the session.
    */
   public static class IntArrayBuilder extends BaseArrayBuilder {
      public IntArrayBuilder(Builder parent) {
         super(parent);
      }

      private ValueSupplier build() {
         // prevent capturing this object reference in the lambda
         int mySize = ensurePositiveSize();
         return new ValueSupplier<>(session -> IntVar.newArray(session, mySize), BaseArrayBuilder::resetArray);
      }
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy