private static XmlTag findSpecialTagIn(
      final XmlTag[] tags,
      final String specialName,
      final String name,
      final XmlTag rootTag,
      final XmlNSDescriptorImpl descriptor,
      final HashSet<XmlTag> visited) {
    for (XmlTag tag : tags) {
      if (equalsToSchemaName(tag, specialName)) {
        String attribute = tag.getAttributeValue("name");

        if (name.equals(attribute)
            || name.indexOf(":") >= 0 && name.substring(name.indexOf(":") + 1).equals(attribute)) {
          return tag;
        }
      } else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME)
          || (equalsToSchemaName(tag, IMPORT_TAG_NAME)
              && rootTag
                  .getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(name))
                  .equals(tag.getAttributeValue("namespace")))) {
        final String schemaLocation = tag.getAttributeValue("schemaLocation");

        if (schemaLocation != null) {
          final XmlFile xmlFile =
              XmlUtil.findNamespaceByLocation(rootTag.getContainingFile(), schemaLocation);

          if (xmlFile != null) {
            final XmlDocument document = xmlFile.getDocument();
            if (document != null) {
              final XmlTag rTag =
                  findSpecialTag(name, specialName, document.getRootTag(), descriptor, visited);

              if (rTag != null) return rTag;
            }
          }
        }
      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
        XmlTag rTag =
            findSpecialTagIn(tag.getSubTags(), specialName, name, rootTag, descriptor, visited);
        if (rTag != null) return rTag;

        final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag);
        if (nsDescriptor != null) {
          final XmlTag redefinedRootTag =
              ((XmlDocument) nsDescriptor.getDeclaration()).getRootTag();

          rTag =
              findSpecialTagIn(
                  redefinedRootTag.getSubTags(),
                  specialName,
                  name,
                  redefinedRootTag,
                  nsDescriptor,
                  visited);
          if (rTag != null) return rTag;
        }
      }
    }

    return null;
  }
  private TypeDescriptor doFindIn(
      final XmlTag[] tags,
      final String name,
      final String namespace,
      final Pair<QNameKey, XmlTag> pair,
      final XmlTag rootTag,
      final Set<XmlTag> visited) {
    for (final XmlTag tag : tags) {
      if (equalsToSchemaName(tag, "complexType")) {
        if (name == null) {
          CachedValue<TypeDescriptor> value = createAndPutTypesCachedValue(tag, pair);
          return value.getValue();
        }

        String nameAttribute = tag.getAttributeValue("name");

        if (isSameName(name, namespace, nameAttribute)) {
          CachedValue<TypeDescriptor> cachedValue = createAndPutTypesCachedValue(tag, pair);
          return cachedValue.getValue();
        }
      } else if (equalsToSchemaName(tag, "simpleType")) {

        if (name == null) {
          CachedValue<TypeDescriptor> value = createAndPutTypesCachedValueSimpleType(tag, pair);
          return value.getValue();
        }

        String nameAttribute = tag.getAttributeValue("name");

        if (isSameName(name, namespace, nameAttribute)) {
          CachedValue<TypeDescriptor> cachedValue = createAndPutTypesCachedValue(tag, pair);
          return cachedValue.getValue();
        }
      } else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME)
          || (equalsToSchemaName(tag, IMPORT_TAG_NAME)
              && (namespace == null || !namespace.equals(getDefaultNamespace())))) {
        final String schemaLocation = tag.getAttributeValue("schemaLocation");
        if (schemaLocation != null) {
          final XmlFile xmlFile =
              XmlUtil.findNamespaceByLocation(rootTag.getContainingFile(), schemaLocation);

          if (xmlFile != null) {
            final XmlDocument document = xmlFile.getDocument();

            if (document != null) {

              final CachedValue<TypeDescriptor> value =
                  CachedValuesManager.getManager(tag.getProject())
                      .createCachedValue(
                          new CachedValueProvider<TypeDescriptor>() {
                            public Result<TypeDescriptor> compute() {
                              final String currentName = tag.getAttributeValue("name");

                              if ((currentName != null
                                      && !currentName.equals(
                                          XmlUtil.findLocalNameByQualifiedName(name)))
                                  || !xmlFile.isValid()
                                  || xmlFile.getDocument() == null) {
                                myTypesMap.remove(pair);
                                return new Result<TypeDescriptor>(null);
                              }

                              final XmlDocument document = xmlFile.getDocument();
                              final XmlNSDescriptorImpl nsDescriptor =
                                  findNSDescriptor(tag, document);

                              if (nsDescriptor == null) {
                                myTypesMap.remove(pair);
                                return new Result<TypeDescriptor>(null);
                              }

                              final XmlTag rTag = document.getRootTag();

                              final TypeDescriptor complexTypeDescriptor =
                                  nsDescriptor.findTypeDescriptorImpl(
                                      rTag, name, namespace, visited);
                              return new Result<TypeDescriptor>(complexTypeDescriptor, rTag);
                            }
                          },
                          false);

              if (value.getValue() != null) {
                myTypesMap.put(pair, value);
                return value.getValue();
              }
            }
          }
        }
      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
        final XmlTag[] subTags = tag.getSubTags();
        TypeDescriptor descriptor = doFindIn(subTags, name, namespace, pair, rootTag, visited);
        if (descriptor != null) return descriptor;

        final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag);
        if (nsDescriptor != null) {
          final XmlTag redefinedRootTag =
              ((XmlDocument) nsDescriptor.getDeclaration()).getRootTag();
          descriptor =
              doFindIn(
                  redefinedRootTag.getSubTags(), name, namespace, pair, redefinedRootTag, visited);
          if (descriptor != null) return descriptor;
        }
      }
    }
    return null;
  }