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.distribution.sequence;
28
29 import com.rapiddweller.benerator.Generator;
30 import com.rapiddweller.benerator.InvalidGeneratorSetupException;
31 import com.rapiddweller.benerator.NonNullGenerator;
32 import com.rapiddweller.benerator.distribution.Sequence;
33 import com.rapiddweller.benerator.wrapper.SkipGeneratorProxy;
34 import com.rapiddweller.benerator.wrapper.WrapperFactory;
35 import com.rapiddweller.common.BeanUtil;
36 import com.rapiddweller.common.ConfigurationError;
37 import com.rapiddweller.common.MathUtil;
38 import com.rapiddweller.common.NumberUtil;
39 import com.rapiddweller.common.converter.NumberToNumberConverter;
40
41 import java.math.BigDecimal;
42
43 import static com.rapiddweller.common.NumberUtil.toDouble;
44 import static com.rapiddweller.common.NumberUtil.toInteger;
45 import static com.rapiddweller.common.NumberUtil.toLong;
46
47
48
49
50
51
52
53
54
55 public class RandomWalkSequence extends Sequence {
56
57 private static final BigDecimal ONE = BigDecimal.ONE;
58 private static final BigDecimal MINUS_ONE = BigDecimal.ZERO.subtract(ONE);
59
60 private static final boolean DEFAULT_BUFFERED = false;
61 private final boolean buffered;
62 private BigDecimal initial;
63 private BigDecimal minStep;
64 private BigDecimal maxStep;
65
66
67
68
69
70
71 public RandomWalkSequence() {
72 this(MINUS_ONE, ONE);
73 }
74
75
76
77
78
79
80
81 public RandomWalkSequence(BigDecimal minStep, BigDecimal maxStep) {
82 this(minStep, maxStep, null);
83 }
84
85
86
87
88
89
90
91
92 public RandomWalkSequence(BigDecimal minStep, BigDecimal maxStep, BigDecimal initial) {
93 this(minStep, maxStep, initial, DEFAULT_BUFFERED);
94 }
95
96
97
98
99
100
101
102
103
104 public RandomWalkSequence(BigDecimal minStep, BigDecimal maxStep, BigDecimal initial, boolean buffered) {
105 this.minStep = minStep;
106 this.maxStep = maxStep;
107 this.initial = initial;
108 this.buffered = buffered;
109 }
110
111
112
113
114
115
116 public void setMinStep(BigDecimal minStep) {
117 this.minStep = minStep;
118 }
119
120
121
122
123
124
125 public void setMaxStep(BigDecimal maxStep) {
126 this.maxStep = maxStep;
127 }
128
129
130
131
132
133
134 public void setInitial(BigDecimal initial) {
135 this.initial = initial;
136 }
137
138
139
140
141 @Override
142 public <T extends Number> NonNullGenerator<T> createNumberGenerator(Class<T> numberType, T min, T max, T granularity, boolean unique) {
143 if (max == null) {
144 max = NumberUtil.maxValue(numberType);
145 }
146 NonNullGenerator<? extends Number> base;
147 if (BeanUtil.isIntegralNumberType(numberType)) {
148 base = createLongGenerator(toLong(min), toLong(max), toLong(granularity), unique);
149 } else {
150 base = createDoubleGenerator(toDouble(min), toDouble(max), toDouble(granularity), unique);
151 }
152 return WrapperFactory.asNonNullNumberGeneratorOfType(numberType, base, min, granularity);
153 }
154
155 @Override
156 public <T> Generator<T> applyTo(Generator<T> source, boolean unique) {
157 if (buffered || MathUtil.between(0L, toLong(minStep), toLong(maxStep))) {
158 return super.applyTo(source, unique);
159 } else {
160 return applySkipGenerator(source, unique);
161 }
162 }
163
164 private <T> Generator<T> applySkipGenerator(Generator<T> source, boolean unique) {
165 int minStepI = toInteger(minStep);
166 if (unique && minStepI <= 0) {
167 throw new ConfigurationError("Cannot generate unique values when minStep=" + minStep);
168 }
169 return new SkipGeneratorProxy<>(source, minStepI, toInteger(maxStep));
170 }
171
172
173
174 private <T> NonNullGenerator<? extends Number> createDoubleGenerator(double min, double max, double granularity, boolean unique) {
175 if (unique && MathUtil.rangeIncludes(0., min, max)) {
176
177 throw new InvalidGeneratorSetupException("Cannot guarantee uniqueness for [min=" + min + ",max=" + max + "]");
178 }
179 return new RandomWalkDoubleGenerator(
180 toDouble(min), toDouble(max), toDouble(granularity), toDouble(minStep), toDouble(maxStep));
181 }
182
183 private <T> NonNullGenerator<? extends Number> createLongGenerator(long min, long max, long granularity, boolean unique) {
184 if (unique && MathUtil.rangeIncludes(0, min, max)) {
185
186 throw new InvalidGeneratorSetupException("Cannot guarantee uniqueness for [min=" + min + ",max=" + max + "]");
187 }
188 return new RandomWalkLongGenerator(
189 min, max, toLong(granularity), toLong(initial(min, max, Long.class)), toLong(minStep), toLong(maxStep));
190 }
191
192 private <T extends Number> T initial(T min, T max, Class<T> numberType) {
193 if (initial != null) {
194 return NumberToNumberConverter.convert(initial, numberType);
195 }
196 if (minStep.doubleValue() > 0) {
197 return min;
198 }
199 if (maxStep.doubleValue() > 0) {
200 return NumberToNumberConverter.convert((min.doubleValue() + max.doubleValue()) / 2, numberType);
201 } else {
202 return max;
203 }
204 }
205
206 }