protected final Map<String, CachedValue<XmlNSDescriptor>> initNSDescriptorsMap() {
   Map<String, CachedValue<XmlNSDescriptor>> map = myNSDescriptorsMap;
   if (map == null) {
     RecursionGuard.StackStamp stamp = ourGuard.markStack();
     map = computeNsDescriptorMap();
     if (stamp.mayCacheNow()) {
       myNSDescriptorsMap = map;
     }
   }
   return map;
 }
  @Nullable
  private BidirectionalMap<String, String> initNamespaceMaps(PsiElement parent) {
    BidirectionalMap<String, String> map = myNamespaceMap;

    if (map == null) {
      RecursionGuard.StackStamp stamp = ourGuard.markStack();
      map = computeNamespaceMap(parent);
      if (stamp.mayCacheNow()) {
        myNamespaceMap = map;
      }
    }

    return map;
  }
  @NotNull
  public String getNamespaceByPrefix(String prefix) {
    final PsiElement parent = getParent();
    LOG.assertTrue(parent.isValid());
    BidirectionalMap<String, String> map = initNamespaceMaps(parent);
    if (map != null) {
      final String ns = map.get(prefix);
      if (ns != null) return ns;
    }
    if (parent instanceof XmlTag) return ((XmlTag) parent).getNamespaceByPrefix(prefix);
    // The prefix 'xml' is by definition bound to the namespace name
    // http://www.w3.org/XML/1998/namespace. It MAY, but need not, be declared
    if (XML_NS_PREFIX.equals(prefix)) return XmlUtil.XML_NAMESPACE_URI;

    if (prefix.length() > 0 && !hasNamespaceDeclarations() && getNamespacePrefix().equals(prefix)) {
      // When there is no namespace declarations then qualified names should be just used in dtds
      // this implies that we may have "" namespace prefix ! (see last paragraph in Namespaces in
      // Xml, Section 5)

      String result =
          ourGuard.doPreventingRecursion(
              "getNsByPrefix",
              true,
              new Computable<String>() {
                @Override
                public String compute() {
                  final String nsFromEmptyPrefix = getNamespaceByPrefix("");
                  final XmlNSDescriptor nsDescriptor = getNSDescriptor(nsFromEmptyPrefix, false);
                  final XmlElementDescriptor descriptor =
                      nsDescriptor != null
                          ? nsDescriptor.getElementDescriptor(XmlTagImpl.this)
                          : null;
                  final String nameFromRealDescriptor =
                      descriptor != null
                              && descriptor.getDeclaration() != null
                              && descriptor.getDeclaration().isPhysical()
                          ? descriptor.getName()
                          : "";
                  if (nameFromRealDescriptor.equals(getName())) return nsFromEmptyPrefix;
                  return XmlUtil.EMPTY_URI;
                }
              });
      if (result != null) {
        return result;
      }
    }
    return XmlUtil.EMPTY_URI;
  }
  @NotNull
  public String getNamespace() {
    String cachedNamespace = myCachedNamespace;
    final long curModCount = getManager().getModificationTracker().getModificationCount();
    if (cachedNamespace != null && myModCount == curModCount) {
      return cachedNamespace;
    }
    RecursionGuard.StackStamp stamp = ourGuard.markStack();
    cachedNamespace = getNamespaceByPrefix(getNamespacePrefix());
    if (!stamp.mayCacheNow()) {
      return cachedNamespace;
    }

    myCachedNamespace = cachedNamespace;
    myModCount = curModCount;
    return cachedNamespace;
  }
  public XmlElementDescriptor getDescriptor() {
    final long curModCount = getManager().getModificationTracker().getModificationCount();
    long curExtResourcesModCount =
        ExternalResourceManagerEx.getInstanceEx().getModificationCount(getProject());
    if (myDescriptorModCount != curModCount || myExtResourcesModCount != curExtResourcesModCount) {
      if (myExtResourcesModCount != curExtResourcesModCount) {
        myNSDescriptorsMap = null;
      }
      RecursionGuard.StackStamp stamp = ourGuard.markStack();
      XmlElementDescriptor descriptor = computeElementDescriptor();
      if (!stamp.mayCacheNow()) {
        return descriptor;
      }

      myCachedDescriptor = descriptor;
      myDescriptorModCount = curModCount;
      myExtResourcesModCount = curExtResourcesModCount;
    }
    return myCachedDescriptor;
  }