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.GeneratorContext;
30  import com.rapiddweller.benerator.InvalidGeneratorSetupException;
31  import com.rapiddweller.benerator.NonNullGenerator;
32  import com.rapiddweller.benerator.util.AbstractNonNullGenerator;
33  import org.apache.logging.log4j.LogManager;
34  import org.apache.logging.log4j.Logger;
35  
36  /**
37   * Combines the output of a 'slow' generator (e.g. a remote hiGenerator)
38   * with quickly generated numbers in a range: value = hi * maxLo + local.
39   *
40   * @author Volker Bergmann
41   * @since 0.3.04
42   */
43  public class HiLoGenerator extends AbstractNonNullGenerator<Long> {
44  
45    private static final Logger logger = LogManager.getLogger(HiLoGenerator.class);
46  
47    /**
48     * The constant DEFAULT_MAX_LO.
49     */
50    protected static final int DEFAULT_MAX_LO = 100;
51  
52    /**
53     * The Max lo.
54     */
55    protected int maxLo;
56  
57    private int lo;
58    private Long hi;
59  
60    /**
61     * The Hi generator.
62     */
63    protected NonNullGenerator<Long> hiGenerator;
64  
65    // constructors ----------------------------------------------------------------------------------------------------
66  
67    /**
68     * Instantiates a new Hi lo generator.
69     */
70    public HiLoGenerator() {
71      this(new IncrementGenerator(), DEFAULT_MAX_LO);
72    }
73  
74    /**
75     * Instantiates a new Hi lo generator.
76     *
77     * @param maxLo the max lo
78     */
79    public HiLoGenerator(int maxLo) {
80      this(new IncrementGenerator(), DEFAULT_MAX_LO);
81    }
82  
83    /**
84     * Instantiates a new Hi lo generator.
85     *
86     * @param hiGenerator the hi generator
87     * @param maxLo       the max lo
88     */
89    public HiLoGenerator(NonNullGenerator<Long> hiGenerator, int maxLo) {
90      this.hiGenerator = hiGenerator;
91      setMaxLo(maxLo);
92      resetMembers();
93    }
94  
95    // properties ------------------------------------------------------------------------------------
96  
97    /**
98     * Sets hi generator.
99     *
100    * @param hiGenerator the hi generator
101    */
102   public void setHiGenerator(NonNullGenerator<Long> hiGenerator) {
103     this.hiGenerator = hiGenerator;
104   }
105 
106   /**
107    * Gets max lo.
108    *
109    * @return the maxLo
110    */
111   public int getMaxLo() {
112     return maxLo;
113   }
114 
115   /**
116    * Sets max lo.
117    *
118    * @param maxLo the maxLo to set
119    */
120   public void setMaxLo(int maxLo) {
121     if (maxLo <= 0) {
122       throw new IllegalArgumentException("maxLo must be greater than 0, was: " + maxLo);
123     }
124     this.maxLo = maxLo;
125   }
126 
127   // Generator interface -------------------------------------------------------------------
128 
129   @Override
130   public Class<Long> getGeneratedType() {
131     return Long.class;
132   }
133 
134   @Override
135   public synchronized void init(GeneratorContext context) {
136     assertNotInitialized();
137     if (hiGenerator == null) {
138       throw new InvalidGeneratorSetupException("hiGenerator", "is null");
139     }
140     hiGenerator.init(context);
141     resetMembers();
142     super.init(context);
143   }
144 
145   @Override
146   public synchronized Long generate() {
147     assertInitialized();
148     if (hi == -1 || lo >= maxLo) {
149       hi = hiGenerator.generate();
150       if (hi == null) {
151         return null;
152       }
153       logger.debug("fetched new hi value: {}", hi);
154       lo = 0;
155     } else {
156       lo++;
157     }
158     return hi * (maxLo + 1) + lo;
159   }
160 
161   @Override
162   public void reset() {
163     hiGenerator.reset();
164     resetMembers();
165     super.reset();
166   }
167 
168   @Override
169   public void close() {
170     hiGenerator.close();
171     super.close();
172   }
173 
174   @Override
175   public boolean isThreadSafe() {
176     return hiGenerator.isThreadSafe();
177   }
178 
179   @Override
180   public boolean isParallelizable() {
181     return hiGenerator.isParallelizable();
182   }
183 
184   @Override
185   public String toString() {
186     return getClass().getSimpleName() + '[' + maxLo + ',' + hiGenerator + ']';
187   }
188 
189   private void resetMembers() {
190     this.lo = -1;
191     this.hi = -1L;
192   }
193 
194 }