@Override
 public <T extends Definition> Source<T> getSource(DefDescriptor<T> descriptor) {
   DefRegistry<T> reg = getRegistryFor(descriptor);
   if (reg != null) {
     return reg.getSource(descriptor);
   }
   return null;
 }
  @Override
  public <D extends Definition> boolean exists(DefDescriptor<D> descriptor) {
    boolean cacheable;

    if (defs.get(descriptor) != null) {
      return true;
    }
    DefRegistry<D> reg = getRegistryFor(descriptor);
    if (reg == null) {
      return false;
    }
    cacheable = isCacheable(reg);
    if (cacheable) {
      //
      // Try our various caches.
      //
      Boolean val = existsCache.getIfPresent(descriptor);
      if (val != null && val.booleanValue()) {
        return true;
      }
      Optional<?> opt = defsCache.getIfPresent(descriptor);
      if (opt != null) {
        //
        // We cache here.
        //
        if (opt.isPresent()) {
          existsCache.put(descriptor, Boolean.TRUE);
          return true;
        } else {
          existsCache.put(descriptor, Boolean.FALSE);
          return false;
        }
      }
    }
    boolean regExists = reg.exists(descriptor);
    if (cacheable) {
      Boolean cacheVal = Boolean.valueOf(regExists);
      existsCache.put(descriptor, cacheVal);
    }
    return regExists;
  }
  @Override
  public Set<DefDescriptor<?>> find(DescriptorFilter matcher) {
    final String filterKey = matcher.toString();
    Set<DefRegistry<?>> registries = delegateRegistries.getRegistries(matcher);
    Set<DefDescriptor<?>> matched = Sets.newHashSet();

    for (DefRegistry<?> reg : registries) {
      //
      // This could be a little dangerous, but unless we force all of our
      // registries to implement find, this is necessary.
      //
      if (reg.hasFind()) {
        Set<DefDescriptor<?>> registryResults = null;

        if (reg.isCacheable()) {
          // cache results per registry
          String cacheKey = filterKey + "|" + reg.toString();
          registryResults = descriptorFilterCache.getIfPresent(cacheKey);
          if (registryResults == null) {
            registryResults = reg.find(matcher);
            descriptorFilterCache.put(cacheKey, registryResults);
          }
        } else {
          registryResults = reg.find(matcher);
        }

        matched.addAll(registryResults);
      }
    }
    if (localDescs != null) {
      for (DefDescriptor<? extends Definition> desc : localDescs) {
        if (matcher.matchDescriptor(desc)) {
          matched.add(desc);
        }
      }
    }

    return matched;
  }
  /**
   * Fill a compiling def for a descriptor.
   *
   * <p>This makes sure that we can get a registry for a given def, then tries to get the def from
   * the global cache, if that fails, it retrieves from the registry, and marks the def as locally
   * built.
   *
   * @param compiling the current compiling def (if there is one).
   * @throws QuickFixException if validateDefinition caused a quickfix.
   */
  private <D extends Definition> boolean fillCompilingDef(
      CompilingDef<D> compiling, AuraContext context) throws QuickFixException {
    assert compiling.def == null;
    {
      //
      // First, check our local cached defs to see if we have a fully compiled version.
      // in this case, we don't care about caching, since we are done.
      //
      @SuppressWarnings("unchecked")
      D localDef = (D) defs.get(compiling.descriptor);
      if (localDef != null) {
        compiling.def = localDef;
        compiling.built = !localDef.isValid();
        if (compiling.built) {
          localDef.validateDefinition();
        }
        return true;
      }
    }

    //
    // If there is no local cache, we must first check to see if there is a registry, as we may not
    // have
    // a registry (depending on configuration). In the case that we don't find one, we are done
    // here.
    //
    DefRegistry<D> registry = getRegistryFor(compiling.descriptor);
    if (registry == null) {
      defs.put(compiling.descriptor, null);
      return false;
    }

    //
    // Now, check if we can cache the def later, as we won't have the registry to check at a later
    // time.
    // If we can cache, look it up in the cache. If we find it, we have a built definition.
    //
    if (isCacheable(registry)) {
      compiling.cacheable = true;

      @SuppressWarnings("unchecked")
      Optional<D> opt = (Optional<D>) defsCache.getIfPresent(compiling.descriptor);
      if (opt != null) {
        D cachedDef = opt.orNull();

        if (cachedDef != null) {
          @SuppressWarnings("unchecked")
          DefDescriptor<D> canonical = (DefDescriptor<D>) cachedDef.getDescriptor();

          compiling.def = cachedDef;
          compiling.descriptor = canonical;
          compiling.built = false;
          defs.put(canonical, cachedDef);
          return true;
        } else {
          return false;
        }
      }
    }

    //
    // The last case. This is our first compile or the def is uncacheable.
    // In this case, we make sure that the initial validation is called, and put
    // the def in the non-validated set.
    //
    compiling.def = registry.getDef(compiling.descriptor);
    if (compiling.def == null) {
      return false;
    }
    @SuppressWarnings("unchecked")
    DefDescriptor<D> canonical = (DefDescriptor<D>) compiling.def.getDescriptor();
    compiling.descriptor = canonical;

    // cc.loggingService.incrementNum(LoggingService.DEF_COUNT);
    // FIXME: setting the current namespace on the context seems
    // extremely hackish
    context.setCurrentNamespace(canonical.getNamespace());
    compiling.def.validateDefinition();
    compiling.built = true;
    defs.put(canonical, compiling.def);
    return true;
  }
 @Override
 public <D extends Definition> Set<DefDescriptor<D>> find(DefDescriptor<D> matcher) {
   Set<DefDescriptor<D>> matched;
   if (matcher.getNamespace().equals("*")) {
     matched = new LinkedHashSet<DefDescriptor<D>>();
     String qualifiedNamePattern = null;
     switch (matcher.getDefType()) {
       case CONTROLLER:
       case TESTSUITE:
       case MODEL:
       case RENDERER:
       case HELPER:
       case STYLE:
       case TYPE:
       case PROVIDER:
       case SECURITY_PROVIDER:
         qualifiedNamePattern = "%s://%s.%s";
         break;
       case ATTRIBUTE:
       case LAYOUT:
       case LAYOUT_ITEM:
       case TESTCASE:
       case APPLICATION:
       case COMPONENT:
       case INTERFACE:
       case EVENT:
       case DOCUMENTATION:
       case LAYOUTS:
       case NAMESPACE:
       case THEME:
         qualifiedNamePattern = "%s://%s:%s";
         break;
       case ACTION:
         // TODO: FIXME
         throw new AuraRuntimeException("Find on ACTION defs not supported.");
     }
     for (String namespace : delegateRegistries.getAllNamespaces()) {
       String qualifiedName =
           String.format(
               qualifiedNamePattern,
               matcher.getPrefix() != null ? matcher.getPrefix() : "*",
               namespace,
               matcher.getName() != null ? matcher.getName() : "*");
       @SuppressWarnings("unchecked")
       DefDescriptor<D> namespacedMatcher =
           (DefDescriptor<D>)
               DefDescriptorImpl.getInstance(
                   qualifiedName, matcher.getDefType().getPrimaryInterface());
       DefRegistry<D> registry = getRegistryFor(namespacedMatcher);
       if (registry != null) {
         matched.addAll(registry.find(namespacedMatcher));
       }
     }
   } else {
     matched = getRegistryFor(matcher).find(matcher);
   }
   if (localDescs != null) {
     DescriptorFilter filter = new DescriptorFilter(matcher.getQualifiedName());
     for (DefDescriptor<? extends Definition> desc : localDescs) {
       if (filter.matchDescriptor(desc)) {
         @SuppressWarnings("unchecked")
         DefDescriptor<D> localDesc = (DefDescriptor<D>) desc;
         matched.add(localDesc);
       }
     }
   }
   return matched;
 }
 private boolean isCacheable(DefRegistry<?> reg) {
   return useCache && reg.isCacheable();
 }