Skip to content

Commit

Permalink
[refactoring] make fetchObject return the needed type
Browse files Browse the repository at this point in the history
Instead of `Object`, method fetchObject() now returns `T`.
So clients of fetchObject() don't need to cast it to needed type.
  • Loading branch information
asolntsev committed Aug 23, 2024
1 parent 523e722 commit 12453ad
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 48 deletions.
19 changes: 8 additions & 11 deletions src/main/java/net/datafaker/providers/base/Company.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import net.datafaker.internal.helper.FakerIDN;
import net.datafaker.internal.helper.LazyEvaluated;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static java.util.stream.Collectors.joining;

/**
* @since 0.8.0
*/
Expand Down Expand Up @@ -39,25 +40,23 @@ public String buzzword() {
}

private List<String> loadBuzzwords() {
List<List<String>> buzzwordLists = (List<List<String>>) faker.fakeValuesService().fetchObject("company.buzzwords", faker.getContext());
List<List<String>> buzzwordLists = faker.fakeValuesService().fetchObject("company.buzzwords", faker.getContext());
return buzzwordLists.stream().flatMap(Collection::stream).toList();
}

/**
* Generate a buzzword-laden catch phrase.
*/
public String catchPhrase() {
@SuppressWarnings("unchecked")
List<List<String>> catchPhraseLists = (List<List<String>>) faker.fakeValuesService().fetchObject("company.buzzwords", faker.getContext());
List<List<String>> catchPhraseLists = faker.fakeValuesService().fetchObject("company.buzzwords", faker.getContext());
return joinSampleOfEachList(catchPhraseLists);
}

/**
* When a straight answer won't do, BS to the rescue!
*/
public String bs() {
@SuppressWarnings("unchecked")
List<List<String>> buzzwordLists = (List<List<String>>) faker.fakeValuesService().fetchObject("company.bs", faker.getContext());
List<List<String>> buzzwordLists = faker.fakeValuesService().fetchObject("company.bs", faker.getContext());
return joinSampleOfEachList(buzzwordLists);
}

Expand Down Expand Up @@ -93,10 +92,8 @@ private String domainSuffix() {
}

private String joinSampleOfEachList(List<List<String>> listOfLists) {
List<String> words = new ArrayList<>();
for (List<String> list : listOfLists) {
words.add(list.get(faker.random().nextInt(list.size())));
}
return String.join(" ", words);
return listOfLists.stream()
.map(list -> faker.options().nextElement(list))
.collect(joining(" "));
}
}
1 change: 0 additions & 1 deletion src/main/java/net/datafaker/service/FakeValues.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
Expand Down
24 changes: 11 additions & 13 deletions src/main/java/net/datafaker/service/FakeValuesService.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ public class FakeValuesService {

private final Map<RegExpContext, ValueResolver> REGEXP2SUPPLIER_MAP = new CopyOnWriteMap<>(HashMap::new);

public FakeValuesService() {
}

public void updateFakeValuesInterfaceMap(List<SingletonLocale> locales) {
for (final SingletonLocale l : locales) {
fakeValuesInterfaceMap.computeIfAbsent(l, this::getCachedFakeValue);
Expand Down Expand Up @@ -197,7 +194,7 @@ public String toString() {
* If the retrieved value is an slash encoded regular expression such as {@code /[a-b]/} then
* the regex will be converted to a regexify expression and returned (ex. {@code #regexify '[a-b]'})
* <p>
* Otherwise it will just return the value as a string.
* Otherwise, it will just return the value as a string.
*
* @param key the key to fetch from the YML structure.
* @param defaultIfNull the value to return if the fetched value is null
Expand Down Expand Up @@ -229,7 +226,8 @@ public String safeFetch(String key, FakerContext context, String defaultIfNull)
* @param key key contains path to an object. Path segment is separated by
* dot. E.g. name.first_name
*/
public Object fetchObject(String key, FakerContext context) {
@SuppressWarnings("unchecked")
public <T> T fetchObject(String key, FakerContext context) {
Object result = null;
final List<SingletonLocale> localeChain = context.getLocaleChain();
final boolean hasMoreThanOneLocales = localeChain.size() > 1;
Expand All @@ -240,7 +238,7 @@ public Object fetchObject(String key, FakerContext context) {
}
Map<String, Object> stringObjectMap = key2fetchedObject.get(sLocale);
if (stringObjectMap != null && (result = stringObjectMap.get(key)) != null) {
return result;
return (T) result;
}
}

Expand All @@ -267,7 +265,7 @@ public Object fetchObject(String key, FakerContext context) {
Object curResult = key2fetchedObject.getOrDefault(local2Add, Collections.emptyMap())
.get(key);
if (curResult != null) {
return result;
return (T) result;
}
key2fetchedObject.updateNestedValue(local2Add, MAP_STRING_OBJECT_SUPPLIER, key, result);
}
Expand Down Expand Up @@ -299,7 +297,7 @@ public Object fetchObject(String key, FakerContext context) {
sb = new StringBuilder();
}
sb.append(itemStr, start, startWord);
sb.append(WordUtils.capitalize(path[0]) + "." + toJavaNames(itemStr.substring(startWord, j), true) + "}");
sb.append(WordUtils.capitalize(path[0])).append(".").append(toJavaNames(itemStr.substring(startWord, j), true)).append("}");
start = j + 1;
}
}
Expand All @@ -311,7 +309,7 @@ public Object fetchObject(String key, FakerContext context) {
}
}
}
return result;
return (T) result;
}


Expand Down Expand Up @@ -638,7 +636,7 @@ public String jsona(String... fieldExpressions) {
}

/**
* processes a expression in the style #{X.y} using the current objects as the 'current' location
* processes expression in the style #{X.y} using the current objects as the 'current' location
* within the yml file (or the {@link BaseFaker} object hierarchy as it were).
* <p>
* #{Address.streetName} would get resolved to {@link BaseFaker#address()}'s {@link Address#streetName()}
Expand Down Expand Up @@ -772,7 +770,7 @@ private Object resExp(String directive, String[] args, Object current, ProviderR
return res;
}
if (res instanceof List) {
Iterator<ValueResolver> it = ((List) res).iterator();
Iterator<ValueResolver> it = ((List<ValueResolver>) res).iterator();
while (it.hasNext()) {
Object valueResolver = it.next();
Object value;
Expand Down Expand Up @@ -855,7 +853,7 @@ private Object resolveExpression(String directive, String[] args, Object current
// last ditch effort. Due to Ruby's dynamic nature, something like 'Address.street_title' will resolve
// because 'street_title' is a dynamic method on the Address object. We can't do this in Java so we go
// through the normal resolution above, but if we will can't resolve it, we once again do a 'safeFetch' as we
// did first but FIRST we change the Object reference Class.method_name with a yml style internal reference ->
// did first, but FIRST we change the Object reference Class.method_name with a yml style internal reference ->
// class.method_name (lowercase)
if (dotIndex >= 0) {
final String key = javaNameToYamlName(simpleDirective);
Expand All @@ -868,7 +866,7 @@ private Object resolveExpression(String directive, String[] args, Object current

/**
* @param expression input expression
* @return true if s is non null and is a slash delimited regex (ex. {@code /[ab]/})
* @return true if s is non-null and is a slash delimited regex (ex. {@code /[ab]/})
*/
private boolean isSlashDelimitedRegex(String expression) {
return expression != null && expression.startsWith("/") && expression.endsWith("/");
Expand Down
26 changes: 10 additions & 16 deletions src/test/java/net/datafaker/integration/MostSpecificLocaleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import net.datafaker.service.FakeValuesService;
import net.datafaker.service.FakerContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;
Expand All @@ -17,28 +16,23 @@
*/
class MostSpecificLocaleTest {

private FakerContext en;
private FakerContext en_US;

@BeforeEach
void setupFakers() {
en = new FakerContext(new Locale("en"), null);
en_US = new FakerContext(new Locale("en", "US"), null);
}
private final FakerContext en = new FakerContext(new Locale("en"), null);
private final FakerContext en_US = new FakerContext(new Locale("en", "US"), null);

@Test
@SuppressWarnings("unchecked")
void resolvesTheMostSpecificLocale() {
FakeValuesService fakeValuesService = new FakeValuesService();
fakeValuesService.updateFakeValuesInterfaceMap(en.getLocaleChain());
final List<String> enDefaultCountries = (List<String>) fakeValuesService.fetchObject("address.default_country", en);
fakeValuesService = new FakeValuesService();
fakeValuesService.updateFakeValuesInterfaceMap(en_US.getLocaleChain());
final List<String> enUsDefaultCountries = (List<String>) fakeValuesService.fetchObject("address.default_country", en_US);
List<String> enDefaultCountries = fakeValuesService(en).fetchObject("address.default_country", en);
List<String> enUsDefaultCountries = fakeValuesService(en_US).fetchObject("address.default_country", en_US);

assertThat(enDefaultCountries).hasSize(1);
assertThat(enUsDefaultCountries).hasSize(3);

assertThat(enDefaultCountries).as("the default country for en is not en_US").isNotEqualTo(enUsDefaultCountries);
}

private static FakeValuesService fakeValuesService(FakerContext context) {
FakeValuesService service = new FakeValuesService();
service.updateFakeValuesInterfaceMap(context.getLocaleChain());
return service;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@ protected T getFaker() {
return (T) new BaseFaker();
}

@SuppressWarnings("unchecked")
protected List<String> getBaseList(String key) {
return (List<String>) faker.fakeValuesService().fetchObject(key, faker.getContext());
return faker.fakeValuesService().fetchObject(key, faker.getContext());
}

@ParameterizedTest(name = "{0}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import net.datafaker.providers.base.AbstractProvider;
import net.datafaker.providers.base.BaseFaker;
import net.datafaker.providers.base.BaseProviders;

import org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.RepeatedTest;
Expand All @@ -15,7 +14,6 @@
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;

import java.io.IOException;
Expand All @@ -35,7 +33,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.anyInt;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
Expand Down Expand Up @@ -78,12 +76,13 @@ void fetchShouldReturnValue() {

@Test
void fetchObjectShouldReturnValue() {
assertThat((Iterable<?>) fakeValuesService.fetchObject("property.dummy", mockedFaker.getContext())).isEqualTo(List.of("x", "y", "z"));
List<String> dummy = fakeValuesService.fetchObject("property.dummy", mockedFaker.getContext());
assertThat(dummy).isEqualTo(List.of("x", "y", "z"));
}

@Test
void safeFetchShouldReturnValueInList() {
doReturn(0).when(randomService).nextInt(Mockito.anyInt());
doReturn(0).when(randomService).nextInt(anyInt());
assertThat(fakeValuesService.safeFetch("property.dummy", mockedFaker.getContext(), null)).isEqualTo("x");
}

Expand Down

0 comments on commit 12453ad

Please sign in to comment.