}
@SuppressWarnings("unchecked")
@Override
public Wrapper find(String name, final Object[] scopes) {
Wrapper wrapper = null;
final int length = scopes.length;
List<Guard> guards = new ArrayList<Guard>(scopes.length);
// Simple guard to break if the number of scopes at this call site have changed
guards.add(createDepthGuard(length));
NEXT:
for (int i = length - 1; i >= 0; i--) {
Object scope = scopes[i];
if (scope == null) continue;
// Make sure that the current scope is the same class
guards.add(createClassGuard(i, scope));
List<Wrapper> wrappers = null;
int dotIndex;
String subname = name;
// Try and find a wrapper using the simple name
wrapper = findWrapper(i, null, guards, scope, subname);
if (wrapper != null) {
break;
}
// If there is dot notation, start evaluating it
while ((dotIndex = subname.indexOf('.')) != -1) {
final String lookup = subname.substring(0, dotIndex);
subname = subname.substring(dotIndex + 1);
// This is used for lookups but otherwise always succeeds
guards.add(createDotGuard(i, scope, lookup));
List<Guard> wrapperGuard = new ArrayList<Guard>(1);
wrapperGuard.add(createClassGuard(0, scope));
wrapper = findWrapper(0, null, wrapperGuard, scope, lookup);
if (wrappers == null) wrappers = new ArrayList<Wrapper>();
if (wrapper != null) {
// We need to dig into a scope when dot notation shows up
wrappers.add(wrapper);
try {
// Pull out the next level
scope = coerce(wrapper.call(new Object[]{scope}));
} catch (GuardException e) {
throw new AssertionError(e);
}
} else {
// Failed to find a wrapper for the next dot