private void checkDuplicateAttribute(XmlTag tag, final XmlAttribute attribute) {
    if (skipValidation(tag)) {
      return;
    }

    final XmlAttribute[] attributes = tag.getAttributes();
    final PsiFile containingFile = tag.getContainingFile();
    final XmlExtension extension =
        containingFile instanceof XmlFile
            ? XmlExtension.getExtension(containingFile)
            : XmlExtension.DEFAULT_EXTENSION;
    for (XmlAttribute tagAttribute : attributes) {
      ProgressManager.checkCanceled();
      if (attribute != tagAttribute
          && Comparing.strEqual(attribute.getName(), tagAttribute.getName())) {
        final String localName = attribute.getLocalName();

        if (extension.canBeDuplicated(tagAttribute))
          continue; // multiple import attributes are allowed in jsp directive

        HighlightInfo highlightInfo =
            HighlightInfo.createHighlightInfo(
                getTagProblemInfoType(tag),
                XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(
                    SourceTreeToPsiMap.psiElementToTree(attribute)),
                XmlErrorMessages.message("duplicate.attribute", localName));
        addToResults(highlightInfo);

        IntentionAction intentionAction = new RemoveAttributeIntentionFix(localName, attribute);

        QuickFixAction.registerQuickFixAction(highlightInfo, intentionAction);
      }
    }
  }
  public static List<DomElement> getDefinedChildren(
      @NotNull final DomElement parent, final boolean tags, final boolean attributes) {
    if (parent instanceof MergedObject) {
      final SmartList<DomElement> result = new SmartList<>();
      parent.acceptChildren(
          new DomElementVisitor() {
            @Override
            public void visitDomElement(final DomElement element) {
              if (hasXml(element)) {
                result.add(element);
              }
            }
          });
      return result;
    }

    ProgressManager.checkCanceled();

    if (parent instanceof GenericAttributeValue) return Collections.emptyList();

    if (parent instanceof DomFileElement) {
      final DomFileElement element = (DomFileElement) parent;
      return tags ? Arrays.asList(element.getRootElement()) : Collections.<DomElement>emptyList();
    }

    final XmlElement xmlElement = parent.getXmlElement();
    if (xmlElement instanceof XmlTag) {
      XmlTag tag = (XmlTag) xmlElement;
      final DomManager domManager = parent.getManager();
      final SmartList<DomElement> result = new SmartList<>();
      if (attributes) {
        for (final XmlAttribute attribute : tag.getAttributes()) {
          if (!attribute.isValid()) {
            LOG.error("Invalid attr: parent.valid=" + tag.isValid());
            continue;
          }
          GenericAttributeValue element = domManager.getDomElement(attribute);
          if (checkHasXml(attribute, element)) {
            ContainerUtil.addIfNotNull(result, element);
          }
        }
      }
      if (tags) {
        for (final XmlTag subTag : tag.getSubTags()) {
          if (!subTag.isValid()) {
            LOG.error("Invalid subtag: parent.valid=" + tag.isValid());
            continue;
          }
          DomElement element = domManager.getDomElement(subTag);
          if (checkHasXml(subTag, element)) {
            ContainerUtil.addIfNotNull(result, element);
          }
        }
      }
      return result;
    }
    return Collections.emptyList();
  }
  @NotNull
  static List<XmlAttribute> getExtractableAttributes(@NotNull XmlTag viewTag) {
    final List<XmlAttribute> extractableAttributes = new ArrayList<XmlAttribute>();

    for (XmlAttribute attribute : viewTag.getAttributes()) {
      if (canBeExtracted(attribute)) {
        extractableAttributes.add(attribute);
      }
    }
    return extractableAttributes;
  }
 private static void addAttributesBefore(XmlTag tag, List<Pair<String, String>> attr2value) {
   XmlAttribute firstAttribute = ArrayUtil.getFirstElement(tag.getAttributes());
   XmlElementFactory factory = XmlElementFactory.getInstance(tag.getProject());
   for (Pair<String, String> pair : attr2value) {
     XmlAttribute xmlAttribute = factory.createXmlAttribute(pair.first, "");
     if (firstAttribute != null) {
       tag.addBefore(xmlAttribute, firstAttribute);
     } else {
       tag.add(xmlAttribute);
     }
   }
 }
  private static void inlineSingleTag(
      XmlTag includeTag, XmlTag includeParentTag, XmlTag layoutRootTag) {
    final Map<String, String> attributesToAdd = new HashMap<String, String>();

    for (XmlAttribute attribute : includeTag.getAttributes()) {
      final String namespace = attribute.getNamespace();

      if (SdkConstants.NS_RESOURCES.equals(namespace)) {
        attributesToAdd.put(attribute.getLocalName(), attribute.getValue());
      }
    }
    final XmlTag newTag = (XmlTag) includeTag.replace(layoutRootTag.copy());
    final List<XmlAttribute> toDelete = new ArrayList<XmlAttribute>();

    for (XmlAttribute attribute : newTag.getAttributes()) {
      if (attribute.isNamespaceDeclaration()) {
        final String localName = attribute.getLocalName();
        final String prefix = localName.equals(attribute.getName()) ? "" : localName;
        final String namespace = attribute.getValue();

        if (includeParentTag != null
            && namespace.equals(includeParentTag.getNamespaceByPrefix(prefix))) {
          toDelete.add(attribute);
        }
      }
    }

    for (XmlAttribute attribute : toDelete) {
      attribute.delete();
    }

    for (Map.Entry<String, String> entry : attributesToAdd.entrySet()) {
      final String localName = entry.getKey();
      final String value = entry.getValue();
      newTag.setAttribute(localName, SdkConstants.NS_RESOURCES, value);
    }
    CodeStyleManager.getInstance(newTag.getManager()).reformat(newTag);
  }
  private static void inlineMultiTags(
      XmlTag includeTag, XmlTag includeTagParent, XmlTag mergeTag, Project project)
      throws AndroidRefactoringErrorException {
    final Map<String, String> namespacesFromParent =
        includeTagParent.getLocalNamespaceDeclarations();
    final Map<String, String> namespacesToAddToParent = new HashMap<String, String>();
    final Map<String, String> namespacesToAddToEachTag = new HashMap<String, String>();

    for (Map.Entry<String, String> entry : mergeTag.getLocalNamespaceDeclarations().entrySet()) {
      final String prefix = entry.getKey();
      final String namespace = entry.getValue();
      final String declaredNamespace = namespacesFromParent.get(prefix);

      if (declaredNamespace != null && !declaredNamespace.equals(namespace)) {
        namespacesToAddToEachTag.put(prefix, namespace);
      } else {
        namespacesToAddToParent.put(prefix, namespace);
      }
    }
    final XmlTag mergeTagCopy = (XmlTag) mergeTag.copy();
    final XmlElementFactory xmlElementFactory = XmlElementFactory.getInstance(project);

    for (XmlTag subtag : mergeTagCopy.getSubTags()) {
      final XmlAttribute[] attributes = subtag.getAttributes();
      final XmlAttribute firstAttribute = attributes.length > 0 ? attributes[0] : null;

      for (Map.Entry<String, String> entry : namespacesToAddToEachTag.entrySet()) {
        final String prefix = entry.getKey();
        final String namespace = entry.getValue();

        if (!subtag.getLocalNamespaceDeclarations().containsKey(prefix)) {
          final XmlAttribute xmlnsAttr =
              xmlElementFactory.createXmlAttribute("xmlns:" + prefix, namespace);

          if (firstAttribute != null) {
            subtag.addBefore(xmlnsAttr, firstAttribute);
          } else {
            subtag.add(xmlnsAttr);
          }
        }
      }
    }
    replaceByTagContent(project, includeTag, mergeTagCopy);
    addNamespaceAttributes(includeTagParent, namespacesToAddToParent, project);
  }
 private static void replaceElements(XmlTag tag, TemplateBuilder builder) {
   for (XmlAttribute attribute : tag.getAttributes()) {
     XmlAttributeValue value = attribute.getValueElement();
     if (value != null) {
       builder.replaceElement(value, TextRange.from(1, 0), new MacroCallNode(new CompleteMacro()));
     }
   }
   if ("<".equals(tag.getText())) {
     builder.replaceElement(
         tag, TextRange.from(1, 0), new MacroCallNode(new CompleteSmartMacro()));
   } else if (tag.getSubTags().length == 0) {
     int i = tag.getText().indexOf("></");
     if (i > 0) {
       builder.replaceElement(
           tag, TextRange.from(i + 1, 0), new MacroCallNode(new CompleteMacro()));
     }
   }
   for (XmlTag subTag : tag.getSubTags()) {
     replaceElements(subTag, builder);
   }
 }
  private static void addNamespaceAttributes(
      XmlTag tag, Map<String, String> namespaces, Project project) {
    final XmlAttribute[] parentAttributes = tag.getAttributes();
    final XmlAttribute firstParentAttribute =
        parentAttributes.length > 0 ? parentAttributes[0] : null;
    final XmlElementFactory factory = XmlElementFactory.getInstance(project);

    for (Map.Entry<String, String> entry : namespaces.entrySet()) {
      final String prefix = entry.getKey();
      final String namespace = entry.getValue();

      if (!namespace.equals(tag.getNamespaceByPrefix(prefix))) {
        final XmlAttribute xmlnsAttr = factory.createXmlAttribute("xmlns:" + prefix, namespace);

        if (firstParentAttribute != null) {
          tag.addBefore(xmlnsAttr, firstParentAttribute);
        } else {
          tag.add(xmlnsAttr);
        }
      }
    }
  }