content: package com.konsol.beatstream.web.rest;
  
  import static org.assertj.core.api.Assertions.assertThat;
  
  import java.lang.reflect.Method;
  import java.math.BigDecimal;
  import java.time.ZonedDateTime;
  import java.time.format.DateTimeParseException;
  import org.hamcrest.Description;
  import org.hamcrest.TypeSafeDiagnosingMatcher;
  import org.hamcrest.TypeSafeMatcher;
  import org.springframework.cglib.proxy.Enhancer;
  import org.springframework.cglib.proxy.MethodInterceptor;
  import org.springframework.cglib.proxy.MethodProxy;
  import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
  import org.springframework.format.support.DefaultFormattingConversionService;
  import org.springframework.format.support.FormattingConversionService;
  
  /**
   * Utility class for testing REST controllers.
   */
  public final class TestUtil {
  
      /**
       * Create a byte array with a specific size filled with specified data.
       *
       * @param size the size of the byte array.
       * @param data the data to put in the byte array.
       * @return the JSON byte array.
       */
      public static byte[] createByteArray(int size, String data) {
          byte[] byteArray = new byte[size];
          for (int i = 0; i < size; i++) {
              byteArray[i] = Byte.parseByte(data, 2);
          }
          return byteArray;
      }
  
      /**
       * A matcher that tests that the examined string represents the same instant as the reference datetime.
       */
      public static class ZonedDateTimeMatcher extends TypeSafeDiagnosingMatcher<String> {
  
          private final ZonedDateTime date;
  
          public ZonedDateTimeMatcher(ZonedDateTime date) {
              this.date = date;
          }
  
          @Override
          protected boolean matchesSafely(String item, Description mismatchDescription) {
              try {
                  if (!date.isEqual(ZonedDateTime.parse(item))) {
                      mismatchDescription.appendText("was ").appendValue(item);
                      return false;
                  }
                  return true;
              } catch (DateTimeParseException e) {
                  mismatchDescription.appendText("was ").appendValue(item).appendText(", which could not be parsed as a ZonedDateTime");
                  return false;
              }
          }
  
          @Override
          public void describeTo(Description description) {
              description.appendText("a String representing the same Instant as ").appendValue(date);
          }
      }
  
      /**
       * Creates a matcher that matches when the examined string represents the same instant as the reference datetime.
       *
       * @param date the reference datetime against which the examined string is checked.
       */
      public static ZonedDateTimeMatcher sameInstant(ZonedDateTime date) {
          return new ZonedDateTimeMatcher(date);
      }
  
      /**
       * A matcher that tests that the examined number represents the same value - it can be Long, Double, etc - as the reference BigDecimal.
       */
      public static class NumberMatcher extends TypeSafeMatcher<Number> {
  
          final BigDecimal value;
  
          public NumberMatcher(BigDecimal value) {
              this.value = value;
          }
  
          @Override
          public void describeTo(Description description) {
              description.appendText("a numeric value is ").appendValue(value);
          }
  
          @Override
          protected boolean matchesSafely(Number item) {
              BigDecimal bigDecimal = asDecimal(item);
              return bigDecimal != null && value.compareTo(bigDecimal) == 0;
          }
  
          private static BigDecimal asDecimal(Number item) {
              if (item == null) {
                  return null;
              }
              if (item instanceof BigDecimal) {
                  return (BigDecimal) item;
              } else if (item instanceof Long) {
                  return BigDecimal.valueOf((Long) item);
              } else if (item instanceof Integer) {
                  return BigDecimal.valueOf((Integer) item);
              } else if (item instanceof Double) {
                  return BigDecimal.valueOf((Double) item);
              } else if (item instanceof Float) {
                  return BigDecimal.valueOf((Float) item);
              } else {
                  return BigDecimal.valueOf(item.doubleValue());
              }
          }
      }
  
      /**
       * Creates a matcher that matches when the examined number represents the same value as the reference BigDecimal.
       *
       * @param number the reference BigDecimal against which the examined number is checked.
       */
      public static NumberMatcher sameNumber(BigDecimal number) {
          return new NumberMatcher(number);
      }
  
      /**
       * Verifies the equals/hashcode contract on the domain object.
       */
      public static <T> void equalsVerifier(Class<T> clazz) throws Exception {
          T domainObject1 = clazz.getConstructor().newInstance();
          assertThat(domainObject1.toString()).isNotNull();
          assertThat(domainObject1).isEqualTo(domainObject1);
          assertThat(domainObject1).hasSameHashCodeAs(domainObject1);
          // Test with an instance of another class
          Object testOtherObject = new Object();
          assertThat(domainObject1).isNotEqualTo(testOtherObject);
          assertThat(domainObject1).isNotEqualTo(null);
          // Test with an instance of the same class
          T domainObject2 = clazz.getConstructor().newInstance();
          assertThat(domainObject1).isNotEqualTo(domainObject2);
          // HashCodes are equals because the objects are not persisted yet
          assertThat(domainObject1).hasSameHashCodeAs(domainObject2);
      }
  
      /**
       * Create a {@link FormattingConversionService} which use ISO date format, instead of the localized one.
       * @return the {@link FormattingConversionService}.
       */
      public static FormattingConversionService createFormattingConversionService() {
          DefaultFormattingConversionService dfcs = new DefaultFormattingConversionService();
          DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
          registrar.setUseIsoFormat(true);
          registrar.registerFormatters(dfcs);
          return dfcs;
      }
  
      @SuppressWarnings("unchecked")
      public static <T> T createUpdateProxyForBean(T update, T original) {
          Enhancer e = new Enhancer();
          e.setSuperclass(original.getClass());
          e.setCallback(
              new MethodInterceptor() {
                  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                      Object val = update.getClass().getMethod(method.getName(), method.getParameterTypes()).invoke(update, args);
                      if (val == null) {
                          return original.getClass().getMethod(method.getName(), method.getParameterTypes()).invoke(original, args);
                      }
                      return val;
                  }
              }
          );
          return (T) e.create();
      }
  
      private TestUtil() {}
  }
  