PatternRandomField.java
package de.slothsoft.random.types;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import de.slothsoft.random.RandomField;
/**
* A field where you define a pattern and have a couple of random field to fill the
* pattern with.
*
* @author Stef Schulz
* @since 2.1.0
*/
public class PatternRandomField implements RandomField {
private final Map<String, RandomField> components = new HashMap<>();
private String pattern;
private double nullProbability;
/**
* Default constructor.
*
* @param pattern the pattern to fill
* @see #addComponent(String, RandomField)
*/
public PatternRandomField(String pattern) {
this.pattern = Objects.requireNonNull(pattern);
}
@Override
public String nextValue() {
if (RND.nextDouble() < this.nullProbability) {
return null;
}
String result = this.pattern;
for (final Entry<String, RandomField> component : this.components.entrySet()) {
final String key = component.getKey();
int index = result.indexOf(key);
while (index >= 0) {
final Object value = component.getValue().nextValue();
final String valueAsString = value == null ? "" : value.toString();
result = result.substring(0, index) + valueAsString + result.substring(index + key.length());
index = result.indexOf(key);
}
}
return result;
}
/**
* Adds a component that can be accessed by {@link #nextValue()}.
*
* @param key the key that is replaced "as is"
* @param randomField the random field to replace this key with
*/
public void addComponent(String key, RandomField randomField) {
this.components.put(key, randomField);
}
/**
* Adds components that can be accessed by {@link #nextValue()}.
*
* @param addedComponents with keys and random fields
* @see #addComponent(String, RandomField)
*/
public void addComponents(Map<String, RandomField> addedComponents) {
this.components.putAll(addedComponents);
}
/**
* Removes a component that can be accessed by {@link #nextValue()}.
*
* @param key the key that is replaced "as is"
*/
public void removeComponent(String key) {
this.components.remove(key);
}
/**
* Removes components that can be accessed by {@link #nextValue()}.
*
* @param keys the keys
* @see #removeComponent(String)
*/
public void removeComponents(Set<String> keys) {
keys.forEach(this::removeComponent);
}
/**
* Returns the pattern with keys that get replaced during {@link #nextValue()}.
*
* @return the pattern
*/
public String getPattern() {
return this.pattern;
}
/**
* Sets the pattern with keys that get replaced during {@link #nextValue()}.
*
* @param newPattern the pattern
* @return this instance
*/
public PatternRandomField pattern(String newPattern) {
setPattern(newPattern);
return this;
}
/**
* Sets the pattern with keys that get replaced during {@link #nextValue()}.
*
* @param pattern the pattern
*/
public void setPattern(String pattern) {
this.pattern = Objects.requireNonNull(pattern);
}
/**
* Returns the probability for this field returning null. If the value is 0 then no
* {@link #nextValue()} is null, if it is 1 then every {@link #nextValue()} is null.
*
* @return the probability between 0 and 1
*/
public double getNullProbability() {
return this.nullProbability;
}
/**
* Sets the probability for this field returning null. If the value is 0 then no
* {@link #nextValue()} is null, if it is 1 then every {@link #nextValue()} is null.
*
* @param newNullProbability the probability between 0 and 1
* @return this instance
*/
public PatternRandomField nullProbability(double newNullProbability) {
setNullProbability(newNullProbability);
return this;
}
/**
* Sets the probability for this field returning null. If the value is 0 then no
* {@link #nextValue()} is null, if it is 1 then every {@link #nextValue()} is null.
*
* @param nullProbability the probability between 0 and 1
*/
public void setNullProbability(double nullProbability) {
if (nullProbability < 0 || nullProbability > 1) {
throw new IllegalArgumentException("Null probability must be between 0 and 1!");
}
this.nullProbability = nullProbability;
}
}