package com.fasterxml.jackson.databind.util; import java.lang.reflect.Array; import java.util.*; /** * Helper class that contains set of distinct builders for different * arrays of primitive values. It also provides trivially simple * reuse scheme, which assumes that caller knows not to use instances * concurrently (which works ok with primitive arrays since they can * not contain other non-primitive types). */ public final class ArrayBuilders { BooleanBuilder _booleanBuilder = null; // note: no need for char[] builder, assume they are Strings ByteBuilder _byteBuilder = null; ShortBuilder _shortBuilder = null; IntBuilder _intBuilder = null; LongBuilder _longBuilder = null; FloatBuilder _floatBuilder = null; DoubleBuilder _doubleBuilder = null; public ArrayBuilders() { } public BooleanBuilder getBooleanBuilder() { if (_booleanBuilder == null) { _booleanBuilder = new BooleanBuilder(); } return _booleanBuilder; } public ByteBuilder getByteBuilder() { if (_byteBuilder == null) { _byteBuilder = new ByteBuilder(); } return _byteBuilder; } public ShortBuilder getShortBuilder() { if (_shortBuilder == null) { _shortBuilder = new ShortBuilder(); } return _shortBuilder; } public IntBuilder getIntBuilder() { if (_intBuilder == null) { _intBuilder = new IntBuilder(); } return _intBuilder; } public LongBuilder getLongBuilder() { if (_longBuilder == null) { _longBuilder = new LongBuilder(); } return _longBuilder; } public FloatBuilder getFloatBuilder() { if (_floatBuilder == null) { _floatBuilder = new FloatBuilder(); } return _floatBuilder; } public DoubleBuilder getDoubleBuilder() { if (_doubleBuilder == null) { _doubleBuilder = new DoubleBuilder(); } return _doubleBuilder; } /* /********************************************************** /* Impl classes /********************************************************** */ public final static class BooleanBuilder extends PrimitiveArrayBuilder<boolean[]> { public BooleanBuilder() { } @Override public final boolean[] _constructArray(int len) { return new boolean[len]; } } public final static class ByteBuilder extends PrimitiveArrayBuilder<byte[]> { public ByteBuilder() { } @Override public final byte[] _constructArray(int len) { return new byte[len]; } } public final static class ShortBuilder extends PrimitiveArrayBuilder<short[]> { public ShortBuilder() { } @Override public final short[] _constructArray(int len) { return new short[len]; } } public final static class IntBuilder extends PrimitiveArrayBuilder<int[]> { public IntBuilder() { } @Override public final int[] _constructArray(int len) { return new int[len]; } } public final static class LongBuilder extends PrimitiveArrayBuilder<long[]> { public LongBuilder() { } @Override public final long[] _constructArray(int len) { return new long[len]; } } public final static class FloatBuilder extends PrimitiveArrayBuilder<float[]> { public FloatBuilder() { } @Override public final float[] _constructArray(int len) { return new float[len]; } } public final static class DoubleBuilder extends PrimitiveArrayBuilder<double[]> { public DoubleBuilder() { } @Override public final double[] _constructArray(int len) { return new double[len]; } } /* /********************************************************** /* Static helper methods /********************************************************** */ public static <T> HashSet<T> arrayToSet(T[] elements) { HashSet<T> result = new HashSet<T>(); if (elements != null) { for (T elem : elements) { result.add(elem); } } return result; } public static <T> ArrayList<T> arrayToList(T[] elements) { ArrayList<T> result = new ArrayList<T>(); if (elements != null) { for (T elem : elements) { result.add(elem); } } return result; } public static <T> HashSet<T> setAndArray(Set<T> set, T[] elements) { HashSet<T> result = new HashSet<T>(); if (set != null) { result.addAll(set); } if (elements != null) { for (T value : elements) { result.add(value); } } return result; } /** * Helper method for adding specified element to a List, but also * considering case where the List may not have been yet constructed * (that is, null is passed instead). * * @param list List to add to; may be null to indicate that a new * List is to be constructed * @param element Element to add to list * * @return List in which element was added; either <code>list</code> * (if it was not null), or a newly constructed List. */ public static <T> List<T> addToList(List<T> list, T element) { if (list == null) { list = new ArrayList<T>(); } list.add(element); return list; } /** * Helper method for constructing a new array that contains specified * element followed by contents of the given array. No checking is done * to see if element being inserted is duplicate. */ public static <T> T[] insertInList(T[] array, T element) { int len = array.length; @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len+1); if (len > 0) { System.arraycopy(array, 0, result, 1, len); } result[0] = element; return result; } /** * Helper method for constructing a new array that contains specified * element followed by contents of the given array but never contains * duplicates. * If element already existed, one of two things happens: if the element * was already the first one in array, array is returned as is; but * if not, a new copy is created in which element has moved as the head. */ @SuppressWarnings("unchecked") public static <T> T[] insertInListNoDup(T[] array, T element) { final int len = array.length; // First: see if the element already exists for (int ix = 0; ix < len; ++ix) { if (array[ix] == element) { // if at head already, return as is if (ix == 0) { return array; } // otherwise move things around T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len); System.arraycopy(array, 0, result, 1, ix); array[0] = element; return result; } } // but if not, allocate new array, move T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len+1); if (len > 0) { System.arraycopy(array, 0, result, 1, len); } result[0] = element; return result; } /** * Helper method for exposing contents of arrays using a read-only iterator */ public static <T> Iterator<T> arrayAsIterator(T[] array) { return new ArrayIterator<T>(array); } public static <T> Iterable<T> arrayAsIterable(T[] array) { return new ArrayIterator<T>(array); } /* /********************************************************** /* Helper classes /********************************************************** */ /** * Iterator implementation used to efficiently expose contents of an * Array as read-only iterator. */ private final static class ArrayIterator<T> implements Iterator<T>, Iterable<T> { private final T[] _array; private int _index; public ArrayIterator(T[] array) { _array = array; _index = 0; } // @Override public boolean hasNext() { return _index < _array.length; } // @Override public T next() { if (_index >= _array.length) { throw new NoSuchElementException(); } return _array[_index++]; } // @Override public void remove() { throw new UnsupportedOperationException(); } // @Override public Iterator<T> iterator() { return this; } } }