001/*
002 * Copyright © 2025 CUI-OpenSource-Software (info@cuioss.de)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package de.cuioss.test.generator.impl;
017
018import de.cuioss.test.generator.Generators;
019import de.cuioss.test.generator.TypedGenerator;
020
021import static java.util.Objects.requireNonNull;
022
023/**
024 * Provides generators for arrays of all Java primitive types.
025 * Each generator creates arrays of random length (1-128 elements) with random values
026 * appropriate for the primitive type.
027 * 
028 * <p>Available generators:</p>
029 * <ul>
030 *   <li>{@link #BOOLEAN} - boolean[] arrays with random true/false values</li>
031 *   <li>{@link #BYTE} - byte[] arrays with random byte values</li>
032 *   <li>{@link #CHAR} - char[] arrays with random character values</li>
033 *   <li>{@link #SHORT} - short[] arrays with random short values</li>
034 *   <li>{@link #INTEGER} - int[] arrays with random integer values</li>
035 *   <li>{@link #LONG} - long[] arrays with random long values</li>
036 *   <li>{@link #FLOAT} - float[] arrays with random float values</li>
037 *   <li>{@link #DOUBLE} - double[] arrays with random double values</li>
038 * </ul>
039 * 
040 * <p><em>Example usage:</em></p>
041 * <pre>
042 * // Generate arrays of different primitive types
043 * boolean[] booleans = (boolean[]) PrimitiveArrayGenerators.BOOLEAN.next();
044 * int[] integers = (int[]) PrimitiveArrayGenerators.INTEGER.next();
045 * 
046 * // Get a generator for a specific primitive type
047 * var generator = PrimitiveArrayGenerators.resolveForType(int.class);
048 * int[] moreIntegers = (int[]) generator.next();
049 * </pre>
050 * 
051 * <p>Implementation notes:</p>
052 * <ul>
053 *   <li>All generators are thread-safe</li>
054 *   <li>Array size is randomly chosen between 1 and 128 elements</li>
055 *   <li>Values are generated using the corresponding primitive generators from {@link Generators}</li>
056 * </ul>
057 *
058 * @author Oliver Wolff
059 * @see Generators
060 */
061public enum PrimitiveArrayGenerators {
062
063    /** Provides booleans */
064    BOOLEAN {
065
066        @Override
067        public Object next() {
068            final int size = sizeGenerator.next();
069            final var generator = Generators.booleans();
070            final var array = new boolean[size];
071            for (var index = 0; index < size; index++) {
072                array[index] = generator.next();
073            }
074            return array;
075        }
076
077        @Override
078        public Class<?> getType() {
079            return boolean.class;
080        }
081    },
082    /** Provides bytes */
083    BYTE {
084
085        @Override
086        public Object next() {
087            final int size = sizeGenerator.next();
088            final var generator = Generators.bytes();
089            final var array = new byte[size];
090            for (var index = 0; index < size; index++) {
091                array[index] = generator.next();
092            }
093            return array;
094        }
095
096        @Override
097        public Class<?> getType() {
098            return byte.class;
099        }
100    },
101    /** Provides chars */
102    CHAR {
103
104        @Override
105        public Object next() {
106            final int size = sizeGenerator.next();
107            final var generator = Generators.characters();
108            final var array = new char[size];
109            for (var index = 0; index < size; index++) {
110                array[index] = generator.next();
111            }
112            return array;
113        }
114
115        @Override
116        public Class<?> getType() {
117            return char.class;
118        }
119    },
120    /** Provides shorts */
121    SHORT {
122
123        @Override
124        public Object next() {
125            final int size = sizeGenerator.next();
126            final TypedGenerator<Short> generator = new ShortObjectGenerator();
127            final var array = new short[size];
128            for (var index = 0; index < size; index++) {
129                array[index] = generator.next();
130            }
131            return array;
132        }
133
134        @Override
135        public Class<?> getType() {
136            return short.class;
137        }
138    },
139    /** Provides integers */
140    INTEGER {
141
142        @Override
143        public Object next() {
144            final int size = sizeGenerator.next();
145            final var generator = Generators.integers();
146            final var array = new int[size];
147            for (var index = 0; index < size; index++) {
148                array[index] = generator.next();
149            }
150            return array;
151        }
152
153        @Override
154        public Class<?> getType() {
155            return int.class;
156        }
157    },
158    /** Provides longs */
159    LONG {
160
161        @Override
162        public Object next() {
163            final int size = sizeGenerator.next();
164            final var generator = Generators.longs();
165            final var array = new long[size];
166            for (var index = 0; index < size; index++) {
167                array[index] = generator.next();
168            }
169            return array;
170        }
171
172        @Override
173        public Class<?> getType() {
174            return long.class;
175        }
176    },
177    /** Provides floats */
178    FLOAT {
179
180        @Override
181        public Object next() {
182            final int size = sizeGenerator.next();
183            final TypedGenerator<Float> generator = new FloatObjectGenerator();
184            final var array = new float[size];
185            for (var index = 0; index < size; index++) {
186                array[index] = generator.next();
187            }
188            return array;
189        }
190
191        @Override
192        public Class<?> getType() {
193            return float.class;
194        }
195    },
196    /** Provides doubles */
197    DOUBLE {
198
199        @Override
200        public Object next() {
201            final int size = sizeGenerator.next();
202            final var generator = Generators.doubles();
203            final var array = new double[size];
204            for (var index = 0; index < size; index++) {
205                array[index] = generator.next();
206            }
207            return array;
208        }
209
210        @Override
211        public Class<?> getType() {
212            return double.class;
213        }
214    };
215
216    private static final TypedGenerator<Integer> sizeGenerator = Generators.integers(1, 128);
217
218    /**
219     * @return an primitive array of the configured type, with the sizes 1-128
220     */
221    public abstract Object next();
222
223    /**
224     * @return the type of the primitive
225     */
226    public abstract Class<?> getType();
227
228    /**
229     * Returns a {@link PrimitiveArrayGenerators} for the given primitive type.
230     *
231     * @param primitiveType must not be null and a primitive type.
232     * @return the found {@link PrimitiveArrayGenerators} or throws an
233     *         {@link IllegalStateException} if none could be found
234     */
235    public static PrimitiveArrayGenerators resolveForType(final Class<?> primitiveType) {
236        requireNonNull(primitiveType);
237        if (!primitiveType.isPrimitive()) {
238            throw new IllegalArgumentException("You must provide a primitive type, given: " + primitiveType);
239        }
240        for (final PrimitiveArrayGenerators generator : PrimitiveArrayGenerators.values()) {
241            if (primitiveType.equals(generator.getType())) {
242                return generator;
243            }
244        }
245        throw new IllegalStateException("No generator registered for type " + primitiveType);
246    }
247
248}