EnglishWordsInstance.java
/*
* Copyright (c) 2020, Stein Eldar Johnsen
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package net.morimekta.testing.text;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.ThreadLocalRandom.current;
/**
* This is a very light-weight version of fairy, which just generates
* simple pseudo-sentences in repeated SVO patterns.
*/
class EnglishWordsInstance {
public String noun() {
return requireNonNull(nouns.get(current().nextInt(nouns.size())));
}
public String thing() {
if (current().nextBoolean()) {
return adjective() + " " + noun();
}
return noun();
}
public String adjective() {
return requireNonNull(adjectives.get(current().nextInt(adjectives.size())));
}
public String verb() {
return requireNonNull(verbs.get(current().nextInt(verbs.size())));
}
public String word() {
return requireNonNull(words.get(current().nextInt(words.size())));
}
public String sentence(int minLength) {
StringBuilder sentence = new StringBuilder();
while (sentence.length() < minLength) {
if (sentence.length() > 0) {
sentence.append(", and ")
.append(thing());
} else {
sentence.append(capitalize(thing()));
}
sentence.append(" ")
.append(verb())
.append(" ")
.append(thing());
}
return sentence.toString();
}
public String paragraph(int sentences) {
return IntStream.range(0, sentences)
.sequential()
.map(i -> current().nextInt(50) + 20)
.mapToObj(this::sentence)
.collect(Collectors.joining(". ")) + ".";
}
public String cicero() {
return cicero;
}
public String loremIpsum() {
return loremIpsum;
}
public String loremIpsumOneline() {
return loremIpsumOneline;
}
// --- Protected ---
static EnglishWordsInstance getInstance() {
return INSTANCE.updateAndGet(i -> {
if (i == null) {
i = new EnglishWordsInstance();
}
return i;
});
}
// --- Private ---
private static final System.Logger LOGGER =
System.getLogger(EnglishWordsInstance.class.getName());
private static final AtomicReference<EnglishWordsInstance> INSTANCE =
new AtomicReference<>();
private final List<String> nouns;
private final List<String> adjectives;
private final List<String> verbs;
private final List<String> words;
private final String loremIpsum;
private final String loremIpsumOneline;
private final String cicero;
private EnglishWordsInstance() {
try (InputStream in = requireNonNull(
EnglishWordsInstance.class.getResourceAsStream("/net/morimekta/testing/text/words.txt"),
"in == null");
InputStreamReader reader = new InputStreamReader(in, UTF_8);
BufferedReader bufferedReader = new BufferedReader(reader);
Stream<String> lines = requireNonNull(bufferedReader.lines(), "line == null")) {
List<String> nounsB = new ArrayList<>();
List<String> adjectivesB = new ArrayList<>();
List<String> verbsB = new ArrayList<>();
List<String> wordsB = new ArrayList<>();
lines.forEach(line -> {
String[] word = line.split(" ", 3);
if (word.length != 3 || word[0].isEmpty()) {
return;
} else if (word[2].contains("adjective")) {
adjectivesB.add(word[0]);
} else if (word[2].contains("verb")) {
verbsB.add(word[0]);
} else if (word[2].contains("noun")) {
nounsB.add(word[0]);
}
wordsB.add(word[0]);
});
nouns = List.copyOf(nounsB);
adjectives = List.copyOf(adjectivesB);
verbs = List.copyOf(verbsB);
words = List.copyOf(wordsB);
} catch (IOException e) {
LOGGER.log(System.Logger.Level.ERROR, "Failed to load words: " + e.getMessage(), e);
throw new UncheckedIOException(e.getMessage(), e);
}
try (InputStream in = requireNonNull(
EnglishWordsInstance.class.getResourceAsStream("/net/morimekta/testing/text/cicero.txt"),
"in == null");
InputStreamReader reader = new InputStreamReader(in, UTF_8);
StringWriter writer = new StringWriter()) {
reader.transferTo(writer);
cicero = writer.toString();
} catch (IOException e) {
LOGGER.log(System.Logger.Level.ERROR, "Failed to load cicero: " + e.getMessage(), e);
throw new UncheckedIOException(e.getMessage(), e);
}
try (InputStream in = requireNonNull(
EnglishWordsInstance.class.getResourceAsStream("/net/morimekta/testing/text/loremipsum.txt"),
"in == null");
InputStreamReader reader = new InputStreamReader(in, UTF_8);
StringWriter writer = new StringWriter()) {
reader.transferTo(writer);
loremIpsum = writer.toString();
loremIpsumOneline = loremIpsum.replaceAll("\n", " ").trim();
} catch (IOException e) {
LOGGER.log(System.Logger.Level.ERROR, "Failed to load lorem ipsum: " + e.getMessage(), e);
throw new UncheckedIOException(e.getMessage(), e);
}
}
private static String capitalize(String word) {
return word.substring(0, 1).toUpperCase(Locale.US) + word.substring(1);
}
}