Resolve object style references as simple references

Addresses DiUS/java-faker#148

If the yml contains an object style reference like Address.street_title which doesn't
resolve to a method name on Address, then try 'address.street_title' as a last ditch effort
which is probably how it should be encoded in the yml anyhow.
This commit is contained in:
Trever Shick
2016-10-30 12:00:14 -04:00
committed by Pascal Schumacher
parent f7f499681d
commit de89bf740b
2 changed files with 33 additions and 11 deletions
@@ -59,7 +59,7 @@ public class FakeValuesService {
for (int i=0;i< locales.size();i++) {
final Locale l = locales.get(i);
final StringBuilder filename = new StringBuilder(l.getLanguage());
final StringBuilder filename = new StringBuilder(language(l));
if (!"".equals(l.getCountry())) {
filename.append("-").append(l.getCountry());
}
@@ -83,6 +83,17 @@ public class FakeValuesService {
this.fakeValuesMaps = Collections.unmodifiableList(all);
}
/**
* If you new up a locale with "he", it gets converted to "iw" which is old.
* This addresses that unfortunate condition.
*/
private String language(Locale l) {
if (l.getLanguage().equals("iw")) {
return "he";
}
return l.getLanguage();
}
/**
* @return the embedded faker: clause from the loaded Yml by the localeName, so .yml > en-us: > faker:
*/
@@ -178,6 +189,9 @@ public class FakeValuesService {
if (o == null) return defaultIfNull;
if (o instanceof List) {
List<String> values = (List<String>) o;
if (values.size() == 0) {
return defaultIfNull;
}
return values.get(randomService.nextInt(values.size()));
} else {
return (String) o;
@@ -407,6 +421,15 @@ public class FakeValuesService {
resolved = resolveFakerObjectAndMethod(root, directive, args);
}
// 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
// thru 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 refernce ->
// class.method_name (lowercase)
if (resolved == null && isDotDirective(directive)) {
resolved = safeFetch(simpleDirective.toLowerCase(), null);
}
return resolved;
}
@@ -453,22 +476,21 @@ public class FakeValuesService {
String fakerMethodName = classAndMethod[0].replaceAll("_", "");
MethodAndCoercedArgs fakerAccessor = accessor(faker, fakerMethodName, Collections.<String>emptyList());
if (fakerAccessor == null) {
throw new RuntimeException("Can't find top level faker object named " + fakerMethodName + ".");
log.fine("Can't find top level faker object named " + fakerMethodName + ".");
return null;
}
Object objectWithMethodToInvoke = fakerAccessor.invoke(faker);
String nestedMethodName = classAndMethod[1].replaceAll("_", "");
final MethodAndCoercedArgs accessor = accessor(objectWithMethodToInvoke, classAndMethod[1].replaceAll("_", ""), args);
if (accessor == null) {
throw new RuntimeException("Can't find method on "
+ objectWithMethodToInvoke.getClass().getSimpleName()
+ " called " + nestedMethodName + ".");
log.fine("Can't find method on "
+ objectWithMethodToInvoke.getClass().getSimpleName()
+ " called " + nestedMethodName + ".");
}
return string(accessor.invoke(objectWithMethodToInvoke));
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
log.fine(e.getMessage());
return null;
}
}
@@ -209,13 +209,13 @@ public class FakeValuesServiceTest extends AbstractFakerTest {
@Test
public void expressionWithInvalidFakerObject() {
expressionShouldFailWith("#{ObjectNotOnFaker.methodName}",
"Can't find top level faker object named ObjectNotOnFaker.");
"Unable to resolve #{ObjectNotOnFaker.methodName} directive.");
}
@Test
public void expressionWithValidFakerObjectButInvalidMethod() {
expressionShouldFailWith("#{Name.nonExistentMethod}",
"Can't find method on Name called nonExistentMethod.");
"Unable to resolve #{Name.nonExistentMethod} directive.");
}
/**
@@ -229,7 +229,7 @@ public class FakeValuesServiceTest extends AbstractFakerTest {
@Test
public void expressionWithValidFakerObjectValidMethodInvalidArgs() {
expressionShouldFailWith("#{Number.number_between 'x','y'}",
"Can't find method on Number called numberbetween.");
"Unable to resolve #{Number.number_between 'x','y'} directive.");
}
/**