View Javadoc
1   /*
2    * (c) Copyright 2006-2020 by rapiddweller GmbH & Volker Bergmann. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, is permitted under the terms of the
6    * GNU General Public License.
7    *
8    * For redistributing this software or a derivative work under a license other
9    * than the GPL-compatible Free Software License as defined by the Free
10   * Software Foundation or approved by OSI, you must first obtain a commercial
11   * license to this software product from rapiddweller GmbH & Volker Bergmann.
12   *
13   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14   * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
15   * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
17   * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24   * POSSIBILITY OF SUCH DAMAGE.
25   */
26  
27  package com.rapiddweller.benerator.primitive;
28  
29  import com.rapiddweller.benerator.Generator;
30  import com.rapiddweller.benerator.GeneratorContext;
31  import com.rapiddweller.benerator.NonNullGenerator;
32  import com.rapiddweller.benerator.distribution.Distribution;
33  import com.rapiddweller.benerator.factory.GeneratorFactory;
34  import com.rapiddweller.benerator.wrapper.NonNullGeneratorProxy;
35  import com.rapiddweller.common.Filter;
36  import com.rapiddweller.common.LocaleUtil;
37  import com.rapiddweller.common.StringUtil;
38  import com.rapiddweller.common.filter.FilterUtil;
39  import com.rapiddweller.format.regex.RegexParser;
40  import com.rapiddweller.model.data.Uniqueness;
41  
42  import java.util.ArrayList;
43  import java.util.HashSet;
44  import java.util.Locale;
45  import java.util.Set;
46  
47  /**
48   * {@link String} {@link Generator} which offers a wide range of options for generating strings.<br/><br/>
49   * Created: 31.07.2011 07:15:05
50   *
51   * @author Volker Bergmann
52   * @since 0.7.0
53   */
54  public class StringGenerator extends NonNullGeneratorProxy<String> {
55  
56    private String charSet;
57    private Locale locale;
58    private boolean unique;
59    private boolean ordered;
60    private String prefix;
61    /**
62     * The Min initial.
63     */
64    Character minInitial;
65    private String suffix;
66    private int minLength;
67    private int maxLength;
68    private int lengthGranularity;
69    private Distribution lengthDistribution;
70  
71    private NonNullGenerator<Character> minInitialGenerator;
72  
73    /**
74     * Instantiates a new String generator.
75     */
76    public StringGenerator() {
77      this("\\w", LocaleUtil.getFallbackLocale(), false, false, null, null, null, 1, 8, 1, null);
78    }
79  
80    /**
81     * Instantiates a new String generator.
82     *
83     * @param charSet            the char set
84     * @param locale             the locale
85     * @param unique             the unique
86     * @param ordered            the ordered
87     * @param prefix             the prefix
88     * @param minInitial         the min initial
89     * @param suffix             the suffix
90     * @param minLength          the min length
91     * @param maxLength          the max length
92     * @param lengthGranularity  the length granularity
93     * @param lengthDistribution the length distribution
94     */
95    public StringGenerator(String charSet, Locale locale, boolean unique,
96                           boolean ordered, String prefix, Character minInitial,
97                           String suffix, int minLength, int maxLength, int lengthGranularity,
98                           Distribution lengthDistribution) {
99      super(String.class);
100     this.charSet = charSet;
101     this.locale = locale;
102     this.unique = unique;
103     this.ordered = ordered;
104     this.prefix = prefix;
105     this.minInitial = minInitial;
106     this.suffix = suffix;
107     this.minLength = minLength;
108     this.maxLength = maxLength;
109     this.lengthGranularity = lengthGranularity;
110     this.lengthDistribution = lengthDistribution;
111   }
112 
113   /**
114    * Gets char set.
115    *
116    * @return the char set
117    */
118   public String getCharSet() {
119     return charSet;
120   }
121 
122   /**
123    * Sets char set.
124    *
125    * @param charSet the char set
126    */
127   public void setCharSet(String charSet) {
128     this.charSet = charSet;
129   }
130 
131   /**
132    * Gets locale.
133    *
134    * @return the locale
135    */
136   public Locale getLocale() {
137     return locale;
138   }
139 
140   /**
141    * Sets locale.
142    *
143    * @param locale the locale
144    */
145   public void setLocale(Locale locale) {
146     this.locale = locale;
147   }
148 
149   /**
150    * Is unique boolean.
151    *
152    * @return the boolean
153    */
154   public boolean isUnique() {
155     return unique;
156   }
157 
158   /**
159    * Sets unique.
160    *
161    * @param unique the unique
162    */
163   public void setUnique(boolean unique) {
164     this.unique = unique;
165   }
166 
167   /**
168    * Is ordered boolean.
169    *
170    * @return the boolean
171    */
172   public boolean isOrdered() {
173     return ordered;
174   }
175 
176   /**
177    * Sets ordered.
178    *
179    * @param ordered the ordered
180    */
181   public void setOrdered(boolean ordered) {
182     this.ordered = ordered;
183   }
184 
185   /**
186    * Gets prefix.
187    *
188    * @return the prefix
189    */
190   public String getPrefix() {
191     return prefix;
192   }
193 
194   /**
195    * Sets prefix.
196    *
197    * @param prefix the prefix
198    */
199   public void setPrefix(String prefix) {
200     this.prefix = prefix;
201   }
202 
203   /**
204    * Gets min initial.
205    *
206    * @return the min initial
207    */
208   public Character getMinInitial() {
209     return minInitial;
210   }
211 
212   /**
213    * Sets min initial.
214    *
215    * @param minInitial the min initial
216    */
217   public void setMinInitial(Character minInitial) {
218     this.minInitial = minInitial;
219   }
220 
221   /**
222    * Gets suffix.
223    *
224    * @return the suffix
225    */
226   public String getSuffix() {
227     return suffix;
228   }
229 
230   /**
231    * Sets suffix.
232    *
233    * @param suffix the suffix
234    */
235   public void setSuffix(String suffix) {
236     this.suffix = suffix;
237   }
238 
239   /**
240    * Gets min length.
241    *
242    * @return the min length
243    */
244   public int getMinLength() {
245     return minLength;
246   }
247 
248   /**
249    * Sets min length.
250    *
251    * @param minLength the min length
252    */
253   public void setMinLength(int minLength) {
254     this.minLength = minLength;
255   }
256 
257   /**
258    * Gets max length.
259    *
260    * @return the max length
261    */
262   public int getMaxLength() {
263     return maxLength;
264   }
265 
266   /**
267    * Sets max length.
268    *
269    * @param maxLength the max length
270    */
271   public void setMaxLength(int maxLength) {
272     this.maxLength = maxLength;
273   }
274 
275   /**
276    * Gets length granularity.
277    *
278    * @return the length granularity
279    */
280   public int getLengthGranularity() {
281     return lengthGranularity;
282   }
283 
284   /**
285    * Sets length granularity.
286    *
287    * @param lengthGranularity the length granularity
288    */
289   public void setLengthGranularity(int lengthGranularity) {
290     this.lengthGranularity = lengthGranularity;
291   }
292 
293   /**
294    * Gets length distribution.
295    *
296    * @return the length distribution
297    */
298   public Distribution getLengthDistribution() {
299     return lengthDistribution;
300   }
301 
302   /**
303    * Sets length distribution.
304    *
305    * @param lengthDistribution the length distribution
306    */
307   public void setLengthDistribution(Distribution lengthDistribution) {
308     this.lengthDistribution = lengthDistribution;
309   }
310 
311   @Override
312   public boolean isParallelizable() {
313     return super.isParallelizable() && (minInitialGenerator == null || minInitialGenerator.isParallelizable());
314   }
315 
316   @Override
317   public boolean isThreadSafe() {
318     return super.isThreadSafe() && (minInitialGenerator == null || minInitialGenerator.isThreadSafe());
319   }
320 
321   @Override
322   public synchronized void init(GeneratorContext context) {
323     Set<Character> chars = new RegexParser(locale).parseSingleChar(charSet).getCharSet().getSet();
324     GeneratorFactory factory = context.getGeneratorFactory();
325     if (minInitial != null) {
326       Filter<Character> initialFilter = candidate -> (candidate >= minInitial);
327       Set<Character> initialSet = new HashSet<>(FilterUtil.filter(new ArrayList<>(chars), initialFilter));
328       this.minInitialGenerator = factory.createCharacterGenerator(initialSet);
329       this.minInitialGenerator.init(context);
330     }
331     Generator<String> source = factory.createStringGenerator(chars, minLength, maxLength,
332         lengthGranularity, lengthDistribution, Uniqueness.instance(unique, ordered));
333     setSource(source);
334     super.init(context);
335   }
336 
337   @Override
338   public String generate() {
339     assertInitialized();
340     StringBuilder builder = new StringBuilder();
341     String base = super.generate();
342     if (base == null) {
343       return null;
344     }
345     if (!StringUtil.isEmpty(prefix)) {
346       builder.append(prefix);
347       base = base.substring(prefix.length());
348     }
349     if (minInitialGenerator != null) {
350       builder.append(minInitialGenerator.generate());
351       base = base.substring(1);
352     }
353     if (!StringUtil.isEmpty(suffix)) {
354       base = base.substring(0, base.length() - suffix.length());
355       builder.append(base).append(suffix);
356     } else {
357       builder.append(base);
358     }
359     return builder.toString();
360   }
361 
362   @Override
363   public void reset() {
364     if (minInitialGenerator != null) {
365       minInitialGenerator.reset();
366     }
367     super.reset();
368   }
369 
370 }