WordGeneratorConfigUtil.java
package de.slothsoft.random.types.wordgen;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.CharBuffer;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
/**
* A util class for handy methods surrounding the {@link WordGeneratorConfig}.
*
* @author Stef Schulz
* @since 2.1.0
*/
public final class WordGeneratorConfigUtil {
static class ConfigProperties extends Properties {
private static final long serialVersionUID = 210296994033180536L;
@Override
public Set<Object> keySet() {
return Collections.unmodifiableSet(new TreeSet<>(super.keySet()));
}
@Override
public Set<Map.Entry<Object, Object>> entrySet() {
final Set<Map.Entry<Object, Object>> set1 = super.entrySet();
final Set<Map.Entry<Object, Object>> set2 = new LinkedHashSet<>(set1.size());
final Iterator<Map.Entry<Object, Object>> iterator = set1.stream()
.sorted((o1, o2) -> o1.getKey().toString().compareTo(o2.getKey().toString())).iterator();
while (iterator.hasNext()) {
set2.add(iterator.next());
}
return set2;
}
@Override
public synchronized Enumeration<Object> keys() {
return Collections.enumeration(new TreeSet<>(super.keySet()));
}
}
private static final String PROP_SUPPORTED_CHARACTERS = "supportedCharacters";
private static final String PROP_STANDARD_WORD_LENGTH = "standardWordLength";
private static final String PREFIX_LETTER_ = "letter.";
private static final String SUFFIX_PROBABILITY = ".probability";
/**
* Loads the config from an input stream.
*
* @param stream a stream
* @return read config
* @throws IOException for all kinds of exceptions
*/
public static WordGeneratorConfig loadConfig(InputStream stream) throws IOException {
final Properties props = new Properties();
props.load(stream);
final char[] supportedCharacters = ((String) props.getOrDefault(PROP_SUPPORTED_CHARACTERS,
DefaultWordGeneratorConfig.DEFAULT_SUPPORTED_CHARACTERS)).toCharArray();
final Letter[] supportedLetters = CharBuffer.wrap(supportedCharacters).chars()
.mapToObj(c -> createLetter(props, (char) c)).toArray(Letter[]::new);
final DefaultWordGeneratorConfig result = new DefaultWordGeneratorConfig();
result.setSupportedLetters(supportedLetters);
result.setStandardWordLength(Double.parseDouble((String) props.getOrDefault(PROP_STANDARD_WORD_LENGTH,
String.valueOf(DefaultWordGeneratorConfig.DEFAULT_STANDARD_WORD_LENGTH))));
return result;
}
private static Letter createLetter(Properties props, char c) {
final double probability = Double.parseDouble((String) props
.getOrDefault(PREFIX_LETTER_ + c + SUFFIX_PROBABILITY, String.valueOf(Letter.DEFAULT_PROBABILITY)));
return new Letter(c).probability(probability);
}
/**
* Stores the config to an output stream.
*
* @param stream a stream
* @param config to be stored
* @throws IOException for all kinds of exceptions
*/
public static void storeConfig(OutputStream stream, WordGeneratorConfig config) throws IOException {
final char[] supportedCharacters = config.getSupportedCharacters();
final ConfigProperties props = new ConfigProperties();
props.setProperty(PROP_SUPPORTED_CHARACTERS, new String(supportedCharacters));
for (final char c : supportedCharacters) {
props.setProperty(PREFIX_LETTER_ + c + SUFFIX_PROBABILITY, String.valueOf(config.getProbability(c)));
}
props.setProperty(PROP_STANDARD_WORD_LENGTH, String.valueOf(config.getStandardWordLength()));
props.store(stream, null);
}
/**
* Helper method for implementing {@link #hashCode()}.
*
* @param thisObject a config
* @return a hashcode
*/
static int generateHashCode(WordGeneratorConfig thisObject) {
final long temp = Double.doubleToLongBits(thisObject.getStandardWordLength());
return 31 * (int) (temp ^ (temp >>> 32)) + Arrays.hashCode(thisObject.getSupportedCharacters());
}
/**
* Helper method for implementing {@link #equals(Object)}.
*
* @param thisObject a config
* @param obj another config
* @return true if equal
*/
static boolean areEqual(WordGeneratorConfig thisObject, Object obj) {
if (thisObject == obj) return true;
if (obj == null) return false;
if (thisObject.getClass() != obj.getClass()) return false;
final WordGeneratorConfig that = (DefaultWordGeneratorConfig) obj;
if (Double.doubleToLongBits(thisObject.getStandardWordLength()) != Double
.doubleToLongBits(that.getStandardWordLength()))
return false;
if (!Arrays.equals(thisObject.getSupportedCharacters(), that.getSupportedCharacters())) return false;
return true;
}
private WordGeneratorConfigUtil() {
// hide me
}
}