1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package com.rapiddweller.benerator.factory;
28
29 import com.rapiddweller.benerator.Generator;
30 import com.rapiddweller.benerator.GeneratorProvider;
31 import com.rapiddweller.benerator.NonNullGenerator;
32 import com.rapiddweller.benerator.sample.ConstantGenerator;
33 import com.rapiddweller.benerator.wrapper.AlternativeGenerator;
34 import com.rapiddweller.benerator.wrapper.ConcatenatingGenerator;
35 import com.rapiddweller.benerator.wrapper.WrapperFactory;
36 import com.rapiddweller.common.CharSet;
37 import com.rapiddweller.common.CollectionUtil;
38 import com.rapiddweller.common.ConfigurationError;
39 import com.rapiddweller.format.regex.Choice;
40 import com.rapiddweller.format.regex.Factor;
41 import com.rapiddweller.format.regex.Group;
42 import com.rapiddweller.format.regex.Quantifier;
43 import com.rapiddweller.format.regex.RegexChar;
44 import com.rapiddweller.format.regex.RegexCharClass;
45 import com.rapiddweller.format.regex.RegexParser;
46 import com.rapiddweller.format.regex.RegexPart;
47 import com.rapiddweller.format.regex.RegexString;
48 import com.rapiddweller.format.regex.Sequence;
49 import com.rapiddweller.model.data.Uniqueness;
50
51 import java.util.Objects;
52
53
54
55
56
57
58
59
60 public class RegexGeneratorFactory {
61
62
63
64
65
66
67
68
69 public static NonNullGenerator<String> create(String pattern, GeneratorFactory factory) {
70 return create(pattern, 0, null, Uniqueness.NONE, factory);
71 }
72
73
74
75
76
77
78
79
80
81
82
83 public static NonNullGenerator<String> create(String pattern, int minLength, Integer maxLength,
84 Uniqueness uniqueness, GeneratorFactory factory) {
85 if (pattern == null) {
86 throw new IllegalArgumentException("Not a regular expression: null");
87 }
88 RegexPart regex = new RegexParser().parseRegex(pattern);
89 return createFromObject(regex, minLength, maxLength, uniqueness, factory);
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103
104 static NonNullGenerator<String> createFromObject(RegexPart part, int minLength, Integer maxLength,
105 Uniqueness uniqueness, GeneratorFactory factory) {
106 if (part instanceof Factor) {
107 return createFromFactor((Factor) part, minLength, maxLength, uniqueness, factory);
108 } else {
109 return createFromObject(part, 1, 1, minLength, maxLength, uniqueness, factory);
110 }
111 }
112
113 private static NonNullGenerator<String> createFromFactor(Factor part, int minLength, Integer maxLength,
114 Uniqueness uniqueness, GeneratorFactory factory) {
115 Quantifier quantifier = part.getQuantifier();
116 int minQuant = quantifier.getMin();
117 Integer maxQuant = quantifier.getMax();
118 RegexPart atom = part.getAtom();
119 return createFromObject(atom, minQuant, maxQuant, minLength, maxLength, uniqueness, factory);
120 }
121
122 private static NonNullGenerator<String> createFromObject(RegexPart object, int minQuant, Integer maxQuant,
123 int minLength, Integer maxLength, Uniqueness uniqueness, GeneratorFactory factory) {
124 if (object instanceof Factor) {
125 return createFromFactor((Factor) object, minLength, maxLength, uniqueness, factory);
126 } else if (object instanceof RegexChar) {
127 return createFromCharacter(((RegexChar) object).getChar(), minQuant, maxQuant, minLength, maxLength,
128 uniqueness.isUnique(), factory);
129 } else if (object instanceof RegexCharClass) {
130 return createCharSetGenerator(((RegexCharClass) object).getCharSet(), minQuant, maxQuant, minLength, maxLength,
131 uniqueness, factory);
132 } else if (object instanceof Sequence) {
133 return createFromSequence((Sequence) object, minQuant, maxQuant, minLength, maxLength, uniqueness, factory);
134 } else if (object instanceof Group) {
135 return createFromGroup((Group) object, minQuant, maxQuant, minLength, maxLength, uniqueness, factory);
136 } else if (object instanceof Choice) {
137 return createFromChoice((Choice) object, minQuant, maxQuant, minLength, maxLength, uniqueness, factory);
138 } else if (object instanceof RegexString) {
139 return WrapperFactory.asNonNullGenerator(factory.createSingleValueGenerator(
140 ((RegexString) object).getString(), uniqueness.isUnique()));
141 } else if (object == null) {
142 return WrapperFactory.asNonNullGenerator(new ConstantGenerator<>(null, String.class));
143 } else {
144 throw new UnsupportedOperationException("Unsupported regex part type: " + object.getClass().getName());
145 }
146 }
147
148 @SuppressWarnings("unchecked")
149 private static NonNullGenerator<String> createFromSequence(Sequence sequence, int minCount, Integer maxCount,
150 int minLength, Integer maxLength, Uniqueness uniqueness, GeneratorFactory factory) {
151 RegexPart[] parts = sequence.getFactors();
152 Generator<String>[] componentGenerators = createComponentGenerators(
153 parts, maxLength, maxLength, uniqueness, factory);
154 Generator<String[]> partGenerator = factory.createCompositeArrayGenerator(
155 String.class, componentGenerators, uniqueness);
156 return WrapperFactory.asNonNullGenerator(new ConcatenatingGenerator(partGenerator));
157 }
158
159
160
161
162
163
164
165
166
167
168
169 @SuppressWarnings("rawtypes")
170 static NonNullGenerator[] createComponentGenerators(RegexPart[] parts, Integer maxComponentLength,
171 Integer maxTotalLength, Uniqueness uniqueness, GeneratorFactory factory) {
172 NonNullGenerator<?>[] components = new NonNullGenerator<?>[parts.length];
173 Integer remainingLength = maxTotalLength;
174 for (int i = 0; i < parts.length; i++) {
175 RegexPart part = parts[i];
176 Integer componentLength = part.maxLength();
177 if (componentLength != null && maxComponentLength != null) {
178 componentLength = Math.min(componentLength, maxComponentLength);
179 }
180 if (componentLength != null && remainingLength != null) {
181 componentLength = Math.min(componentLength, remainingLength);
182 }
183 components[i] = createFromObject(part, part.minLength(), componentLength, uniqueness, factory);
184 if (remainingLength != null) {
185 remainingLength -= part.minLength();
186 if (remainingLength < 0) {
187 throw new ConfigurationError("Remaining length is negative: " + remainingLength);
188 }
189 }
190 }
191 return components;
192 }
193
194 @SuppressWarnings({"unchecked", "rawtypes"})
195 private static NonNullGenerator<String> createFromChoice(
196 final Choice choice, final int minCount, final int maxCount, final int minLength, final Integer maxLength,
197 final Uniqueness uniqueness, final GeneratorFactory factory) {
198 final RegexPart[] alternatives = choice.getAlternatives();
199 GeneratorProvider<String> generatorProvider = () -> {
200 final Generator[] altGens = createComponentGenerators(
201 alternatives, maxLength, null, uniqueness, factory);
202 return new AlternativeGenerator<String>(String.class, altGens);
203 };
204 return factory.createCompositeStringGenerator(generatorProvider, minCount, maxCount, uniqueness);
205 }
206
207 private static NonNullGenerator<String> createFromGroup(
208 final Group group, final int minCount, final Integer maxCount,
209 final int minLength, final Integer maxLength,
210 final Uniqueness uniqueness, final GeneratorFactory factory) {
211 GeneratorProvider<String> partGeneratorProvider = () -> createFromObject(group.getRegex(), minLength, maxLength, uniqueness, factory);
212 return factory.createCompositeStringGenerator(partGeneratorProvider, minCount, maxCount, uniqueness);
213 }
214
215 private static NonNullGenerator<String> createFromCharacter(char c, int minCount, Integer maxCount,
216 int minLength, Integer maxLength, boolean unique, GeneratorFactory factory) {
217 DefaultsProvider defaultsProvider = factory.getDefaultsProvider();
218 int minReps = max(minLength, minCount, defaultsProvider.defaultMinLength());
219 int maxReps = min(maxLength, maxCount, defaultsProvider.defaultMaxLength());
220 return factory.createStringGenerator(CollectionUtil.toSet(c), minReps, maxReps, 1, null, (unique ? Uniqueness.ORDERED : Uniqueness.NONE));
221 }
222
223 private static NonNullGenerator<String> createCharSetGenerator(
224 CharSet charSet, int minCount, Integer maxCount, int minLength, Integer maxLength,
225 Uniqueness uniqueness, GeneratorFactory factory) {
226 int min = Math.max(minCount, minLength);
227 Integer max = maxCount;
228 if (max == null) {
229 max = maxLength;
230 } else if (maxLength != null) {
231 max = Math.min(max, maxLength);
232 }
233 if (max == null) {
234 max = factory.getDefaultsProvider().defaultMaxLength();
235 }
236 return factory.createStringGenerator(charSet.getSet(), min, max, 1, null, uniqueness);
237 }
238
239 private static int min(Integer v1, Integer v2, int defaultValue) {
240 if (v1 != null) {
241 if (v2 != null) {
242 return Math.min(v1, v2);
243 } else {
244 return v1;
245 }
246 } else {
247 return Objects.requireNonNullElse(v2, defaultValue);
248 }
249 }
250
251 private static int max(Integer v1, Integer v2, int defaultValue) {
252 if (v1 != null) {
253 if (v2 != null) {
254 return Math.max(v1, v2);
255 } else {
256 return v1;
257 }
258 } else {
259 return Objects.requireNonNullElse(v2, defaultValue);
260 }
261 }
262
263 }