• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.util;
2 
3 import java.lang.reflect.Array;
4 import java.util.*;
5 
6 /**
7  * Helper class that contains set of distinct builders for different
8  * arrays of primitive values. It also provides trivially simple
9  * reuse scheme, which assumes that caller knows not to use instances
10  * concurrently (which works ok with primitive arrays since they can
11  * not contain other non-primitive types).
12  * Also note that instances are not thread safe; the intent is that
13  * a builder is constructed on per-call (deserialization) basis.
14  */
15 public final class ArrayBuilders
16 {
17     private BooleanBuilder _booleanBuilder = null;
18 
19     // note: no need for char[] builder, assume they are Strings
20 
21     private ByteBuilder _byteBuilder = null;
22     private ShortBuilder _shortBuilder = null;
23     private IntBuilder _intBuilder = null;
24     private LongBuilder _longBuilder = null;
25 
26     private FloatBuilder _floatBuilder = null;
27     private DoubleBuilder _doubleBuilder = null;
28 
ArrayBuilders()29     public ArrayBuilders() { }
30 
getBooleanBuilder()31     public BooleanBuilder getBooleanBuilder()
32     {
33         if (_booleanBuilder == null) {
34             _booleanBuilder = new BooleanBuilder();
35         }
36         return _booleanBuilder;
37     }
38 
getByteBuilder()39     public ByteBuilder getByteBuilder()
40     {
41         if (_byteBuilder == null) {
42             _byteBuilder = new ByteBuilder();
43         }
44         return _byteBuilder;
45     }
getShortBuilder()46     public ShortBuilder getShortBuilder()
47     {
48         if (_shortBuilder == null) {
49             _shortBuilder = new ShortBuilder();
50         }
51         return _shortBuilder;
52     }
getIntBuilder()53     public IntBuilder getIntBuilder()
54     {
55         if (_intBuilder == null) {
56             _intBuilder = new IntBuilder();
57         }
58         return _intBuilder;
59     }
getLongBuilder()60     public LongBuilder getLongBuilder()
61     {
62         if (_longBuilder == null) {
63             _longBuilder = new LongBuilder();
64         }
65         return _longBuilder;
66     }
67 
getFloatBuilder()68     public FloatBuilder getFloatBuilder()
69     {
70         if (_floatBuilder == null) {
71             _floatBuilder = new FloatBuilder();
72         }
73         return _floatBuilder;
74     }
getDoubleBuilder()75     public DoubleBuilder getDoubleBuilder()
76     {
77         if (_doubleBuilder == null) {
78             _doubleBuilder = new DoubleBuilder();
79         }
80         return _doubleBuilder;
81     }
82 
83     /*
84     /**********************************************************
85     /* Impl classes
86     /**********************************************************
87      */
88 
89     public final static class BooleanBuilder
90         extends PrimitiveArrayBuilder<boolean[]>
91     {
BooleanBuilder()92         public BooleanBuilder() { }
93         @Override
_constructArray(int len)94         public final boolean[] _constructArray(int len) { return new boolean[len]; }
95     }
96 
97     public final static class ByteBuilder
98         extends PrimitiveArrayBuilder<byte[]>
99     {
ByteBuilder()100         public ByteBuilder() { }
101         @Override
_constructArray(int len)102         public final byte[] _constructArray(int len) { return new byte[len]; }
103     }
104     public final static class ShortBuilder
105         extends PrimitiveArrayBuilder<short[]>
106     {
ShortBuilder()107         public ShortBuilder() { }
108         @Override
_constructArray(int len)109         public final short[] _constructArray(int len) { return new short[len]; }
110     }
111     public final static class IntBuilder
112         extends PrimitiveArrayBuilder<int[]>
113     {
IntBuilder()114         public IntBuilder() { }
115         @Override
_constructArray(int len)116         public final int[] _constructArray(int len) { return new int[len]; }
117     }
118     public final static class LongBuilder
119         extends PrimitiveArrayBuilder<long[]>
120     {
LongBuilder()121         public LongBuilder() { }
122         @Override
_constructArray(int len)123         public final long[] _constructArray(int len) { return new long[len]; }
124     }
125 
126     public final static class FloatBuilder
127         extends PrimitiveArrayBuilder<float[]>
128     {
FloatBuilder()129         public FloatBuilder() { }
130         @Override
_constructArray(int len)131         public final float[] _constructArray(int len) { return new float[len]; }
132     }
133     public final static class DoubleBuilder
134         extends PrimitiveArrayBuilder<double[]>
135     {
DoubleBuilder()136         public DoubleBuilder() { }
137         @Override
_constructArray(int len)138         public final double[] _constructArray(int len) { return new double[len]; }
139     }
140 
141     /*
142     /**********************************************************
143     /* Static helper methods
144     /**********************************************************
145      */
146 
147     /**
148      * Helper method used for constructing simple value comparator used for
149      * comparing arrays for content equality.
150      *<p>
151      * Note: current implementation is not optimized for speed; if performance
152      * ever becomes an issue, it is possible to construct much more efficient
153      * typed instances (one for Object[] and sub-types; one per primitive type).
154      *
155      * @since 2.2 Moved from earlier <code>Comparators</code> class
156      */
getArrayComparator(final Object defaultValue)157     public static Object getArrayComparator(final Object defaultValue)
158     {
159         final int length = Array.getLength(defaultValue);
160         final Class<?> defaultValueType = defaultValue.getClass();
161         return new Object() {
162             @Override
163             public boolean equals(Object other) {
164                 if (other == this) return true;
165                 if (!ClassUtil.hasClass(other, defaultValueType)) {
166                     return false;
167                 }
168                 if (Array.getLength(other) != length) return false;
169                 // so far so good: compare actual equality; but only shallow one
170                 for (int i = 0; i < length; ++i) {
171                     Object value1 = Array.get(defaultValue, i);
172                     Object value2 = Array.get(other, i);
173                     if (value1 == value2) continue;
174                     if (value1 != null) {
175                         if (!value1.equals(value2)) {
176                             return false;
177                         }
178                     }
179                 }
180                 return true;
181             }
182         };
183     }
184 
185     public static <T> HashSet<T> arrayToSet(T[] elements)
186     {
187         if (elements != null) {
188             int len = elements.length;
189             HashSet<T> result = new HashSet<T>(len);
190             for (int i = 0; i < len; ++i) {
191                 result.add(elements[i]);
192             }
193             return result;
194         }
195         return new HashSet<T>();
196     }
197 
198     /**
199      * Helper method for constructing a new array that contains specified
200      * element followed by contents of the given array but never contains
201      * duplicates.
202      * If element already existed, one of two things happens: if the element
203      * was already the first one in array, array is returned as is; but
204      * if not, a new copy is created in which element has moved as the head.
205      */
206     @SuppressWarnings("unchecked")
207     public static <T> T[] insertInListNoDup(T[] array, T element)
208     {
209         final int len = array.length;
210 
211         // First: see if the element already exists
212         for (int ix = 0; ix < len; ++ix) {
213             if (array[ix] == element) {
214                 // if at head already, return as is
215                 if (ix == 0) {
216                     return array;
217                 }
218                 // otherwise move things around
219                 T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len);
220                 System.arraycopy(array, 0, result, 1, ix);
221                 result[0] = element;
222                 ++ix;
223                 int left = len - ix;
224                 if (left > 0) {
225                 	System.arraycopy(array, ix, result, ix, left);
226                 }
227                 return result;
228             }
229         }
230 
231         // but if not, allocate new array, move
232         T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len+1);
233         if (len > 0) {
234             System.arraycopy(array, 0, result, 1, len);
235         }
236         result[0] = element;
237         return result;
238     }
239 }
240