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

objectos.way.Util Maven / Gradle / Ivy

Go to download

Objectos Way allows you to build full-stack web applications using only Java.

The newest version!
/*
 * Copyright (C) 2023-2024 Objectos Software LTDA.
 *
 * 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 objectos.way;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SequencedMap;
import java.util.Set;

/**
 * The Objectos Util main class.
 */
public final class Util {

  /**
   * An empty zero-length {@code byte} array instance.
   */
  public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];

  /**
   * An empty zero-length {@code int} array instance.
   */
  public static final int[] EMPTY_INT_ARRAY = new int[0];

  /**
   * An empty zero-length {@code Object} array instance.
   */
  public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];

  static final int DEFAULT_CAPACITY = 10;

  /**
   * From ArraysSupport.SOFT_MAX_ARRAY_LENGTH
   */
  static final int JVM_SOFT_LIMIT = Integer.MAX_VALUE - 8;

  private static final int BYTE_MASK = 0xFF;

  private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();

  private static final int HEX_MASK = 0xf;

  private Util() {}

  static  List createList() {
    return new UtilList<>();
  }

  static  Map createMap() {
    return new UtilMap<>();
  }

  static  SequencedMap createSequencedMap() {
    return new UtilSequencedMap<>();
  }

  static  Set createSet() {
    return new UtilSet<>();
  }

  /**
   * Copies the values of the array into a larger one (if necessary) so that a
   * value can be inserted at the required index. More formally:
   *
   * 

* If the {@code requiredIndex} is smaller than {@code 0} then an * {@link java.lang.IllegalArgumentException} is thrown. * *

* If the {@code requiredIndex} is smaller than {@code array.length} then the * array is not copied and is returned unchanged. * *

* If the {@code requiredIndex} is equal to or is greater than * {@code array.length} then: * *

    *
  1. a new {@code byte} array instance is created. The length of the new * array is guaranteed to be greater than {@code requiredIndex};
  2. *
  3. all values from the original array are copied into the new array so * that, for all valid indices in the original array, the new array contains * an identical value for the same index; and
  4. *
  5. the new array instance is returned.
  6. *
* *

* A typical usage is: * *

   * byte b = readByte();
   * array = ByteArrays.growIfNecessary(array, currentIndex);
   * array[currentIndex++] = b;
* * @param array * the array instance to be copied if necessary * @param requiredIndex * the index where a value is to be inserted * * @return the {@code array} instance itself or a larger copy of the * original * * @throws IllegalArgumentException * if {@code requiredIndex < 0} */ public static byte[] growIfNecessary(byte[] array, int requiredIndex) { Check.argument(requiredIndex >= 0, "requiredIndex cannot be negative"); var length = array.length; if (requiredIndex < length) { return array; } var newLength = arrayLength(length, requiredIndex); var result = new byte[newLength]; System.arraycopy(array, 0, result, 0, length); return result; } /** * Copies the values of the array into a larger one (if necessary) so that a * value can be inserted at the required index. More formally: * *

* If the {@code requiredIndex} is smaller than {@code 0} then an * {@link java.lang.IllegalArgumentException} is thrown. * *

* If the {@code requiredIndex} is smaller than {@code array.length} then the * array is not copied and is returned unchanged. * *

* If the {@code requiredIndex} is equal to or is greater than * {@code array.length} then: * *

    *
  1. a new {@code int} array instance is created. The length of the new * array is guaranteed to be greater than {@code requiredIndex};
  2. *
  3. all values from the original array are copied into the new array so * that, for all valid indices in the original array, the new array contains * an identical value for the same index; and
  4. *
  5. the new array instance is returned.
  6. *
* *

* A typical usage is: * *

   * int i = computeInt();
   * array = IntArrays.growIfNecessary(array, currentIndex);
   * array[currentIndex++] = i;
* * @param array * the array instance to be copied if necessary * @param requiredIndex * the index where a value is to be inserted * * @return the {@code array} instance itself or a larger copy of the * original * * @throws IllegalArgumentException * if {@code requiredIndex < 0} */ public static int[] growIfNecessary(int[] array, int requiredIndex) { Check.argument(requiredIndex >= 0, "requiredIndex cannot be negative"); var length = array.length; if (requiredIndex < length) { return array; } var newLength = arrayLength(length, requiredIndex); var result = new int[newLength]; System.arraycopy(array, 0, result, 0, length); return result; } /** * Copies the values of the array into a larger one (if necessary) so that a * value can be inserted at the required index. More formally: * *

* If the {@code requiredIndex} is smaller than {@code 0} then an * {@link java.lang.IllegalArgumentException} is thrown. * *

* If the {@code requiredIndex} is smaller than {@code array.length} then the * array is not copied and is returned unchanged. * *

* If the {@code requiredIndex} is equal to or is greater than * {@code array.length} then: * *

    *
  1. a new array instance is created. The resulting array is of exactly the * same class as the original array. The length of the new * array is guaranteed to be greater than {@code requiredIndex};
  2. *
  3. all values from the original array are copied into the new array so * that, for all valid indices in the original array, the new array contains * an identical value for the same index; and
  4. *
  5. the new array instance is returned.
  6. *
* *

* A typical usage is: * *

   * Foo foo = computeFoo();
   * array = ObjectArrays.growIfNecessary(array, currentIndex);
   * array[currentIndex++] = foo;
* * @param * the type of the objects in the array * @param array * the array instance to be copied if necessary * @param requiredIndex * the index where a value is to be inserted * * @return the {@code array} instance itself or a larger copy of the * original * * @throws IllegalArgumentException * if {@code requiredIndex < 0} */ public static T[] growIfNecessary(T[] array, int requiredIndex) { Check.argument(requiredIndex >= 0, "requiredIndex cannot be negative"); var length = array.length; if (requiredIndex < length) { return array; } var newLength = arrayLength(length, requiredIndex); return Arrays.copyOf(array, newLength); } /** * Joins the string representation of each of the elements of the specified * collection separated by the specified {@code delimiter}. * * @param coll * the collection containing the elements * @param delimiter * the separator to use between each element's string representation * * @return a new string resulting from joining together the elements * separated by the specified {@code delimiter} */ static String join(Collection coll, String delimiter) { if (coll instanceof UtilList list) { return list.join(delimiter); } else { throw new UnsupportedOperationException(); } } /** * Returns a string representation of the array in hexadecimal. * *

* The returned string is formed by concatenating the hexadecimal * representation of each byte value from the array in order. Therefore, * the returned string length is double the length of the array. * *

* The following characters are used as hexadecimal digits: * *

0123456789abcdef
* * @param array * the array to be converted. * * @return the string representation of the array in hexadecimal. * * @throws NullPointerException * if {@code array} is null */ public static String toHexString(byte[] array) { Check.notNull(array, "array == null"); var length = array.length; switch (length) { case 0: return ""; default: return toHexStringNonEmpty(array, 0, length); } } static List toUnmodifiableList(List list) { if (list instanceof UtilList impl) { return impl.toUnmodifiableList(); } else { throw new UnsupportedOperationException(); } } static Map toUnmodifiableMap(Map map) { if (map instanceof UtilMap impl) { return impl.toUnmodifiableMap(); } else { throw new UnsupportedOperationException(); } } private static String toHexStringNonEmpty(byte[] array, int offset, int length) { var result = new char[length * 2]; for (int i = 0, j = 0; i < length; i++) { var b = array[offset + i] & BYTE_MASK; result[j++] = HEX_CHARS[b >>> 4]; result[j++] = HEX_CHARS[b & HEX_MASK]; } return new String(result); } static int arrayLength(int length, int requiredIndex) { var halfLength = length >> 1; var newLength = length + halfLength; if (requiredIndex < newLength) { return newLength; } else { return growArrayLength0(requiredIndex); } } static int growBy(int length, int ammount) { int half = length >> 1; int delta = Math.max(ammount, half); int newLength = length + delta; return grow0(length, newLength); } static int growByOne(int length) { int half = length >> 1; int newLength = length + half; return grow0(length, newLength); } private static int grow0(int length, int newLength) { if (newLength > 0 && newLength <= JVM_SOFT_LIMIT) { return newLength; } if (length != JVM_SOFT_LIMIT) { return JVM_SOFT_LIMIT; } throw new OutOfMemoryError( """ Cannot allocate array: exceeds JVM soft limit. length = %,14d limit = %,14d """.formatted(length + 1, JVM_SOFT_LIMIT) ); } private static int growArrayLength0(int requiredIndex) { var minLength = requiredIndex + 1; var halfLength = minLength >> 1; var newLength = minLength + halfLength; if (0 < newLength && newLength <= JVM_SOFT_LIMIT) { return newLength; } else { return growArrayLength1(minLength); } } private static int growArrayLength1(int minLength) { if (minLength < 0) { throw new OutOfMemoryError("Array size already at maximum"); } if (minLength <= JVM_SOFT_LIMIT) { return JVM_SOFT_LIMIT; } return Integer.MAX_VALUE; } static Map parsePropertiesMap(String string) { Map builder; builder = createMap(); String[] lines; lines = string.split("\n"); for (String line : lines) { if (line.isBlank()) { continue; } int colon; colon = line.indexOf(':'); if (colon < 0) { throw new IllegalArgumentException( "The colon character ':' was not found in the line listed below:\n\n" + line + "\n" ); } String key; key = line.substring(0, colon); String value; value = line.substring(colon + 1); builder.put(key.trim(), value.trim()); } return toUnmodifiableMap(builder); } /** * An {@link java.util.Iterator} implementation that does not support the * remove operation. * * @param the type of the elements in this iterator */ static abstract class UnmodifiableIterator implements Iterator { /** * Sole constructor. */ protected UnmodifiableIterator() {} /** * This operation is not supported. * *

* This method performs no operation other than throw an * {@link UnsupportedOperationException}. * * @throws UnsupportedOperationException * always */ @Override public final void remove() { throw new UnsupportedOperationException(); } } /** * An unmodifiable view of a map's keys, values or entries. All of the mutator * methods throw an {@link UnsupportedOperationException} when invoked. * * @param the type of the elements in this view */ static abstract class UnmodifiableView extends UtilBaseCollection implements Set { protected UnmodifiableView() {} /** * This operation is not supported. * *

* This method performs no operation other than throw an * {@link UnsupportedOperationException}. * * @param e * ignored (the operation is not supported) * * @return this method does not return as it always throw an exception * * @throws UnsupportedOperationException * always */ @Override public final boolean add(E e) { throw new UnsupportedOperationException(); } /** * This operation is not supported. * *

* This method performs no operation other than throw an * {@link UnsupportedOperationException}. * * @param c * ignored (the operation is not supported) * * @return this method does not return as it always throw an exception * * @throws UnsupportedOperationException * always */ @Override public final boolean addAll(Collection c) { throw new UnsupportedOperationException(); } /** * This operation is not supported. * *

* This method performs no operation other than throw an * {@link UnsupportedOperationException}. * * @throws UnsupportedOperationException * always */ @Override public final void clear() { throw new UnsupportedOperationException(); } /** *

* Compares the specified object with this view for equality. Returns * {@code true} if and only if * *

    *
  • the specified object is also a {@link Collection};
  • *
  • both collections have same size; and
  • *
  • each element in this view is also present in the specified * collection.
  • *
* * @param obj * the object to be compared for equality with this view * * @return {@code true} if the specified object is equal to this view */ @Override public final boolean equals(Object obj) { return obj == this || obj instanceof Collection that && equals0(that); } @Override public Object[] toArray() { throw new UnsupportedOperationException("Implement me"); } @Override public T[] toArray(T[] a) { throw new UnsupportedOperationException("Implement me"); } private boolean equals0(Collection that) { var size = size(); if (size != that.size()) { return false; } var iter = iterator(); while (iter.hasNext()) { var o = iter.next(); if (!that.contains(o)) { return false; } } return true; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy