@Override
    public Object invokeXpathProjection(
        final InvocationContext invocationContext, final Object proxy, final Object[] args)
        throws Throwable {

      //            try {
      //                if (ReflectionHelper.mayProvideParameterNames()) {
      //                    xPath.setXPathVariableResolver(new MethodParamVariableResolver(method,
      // args, xPath.getXPathVariableResolver()));
      //               }

      final XPathExpression expression = invocationContext.getxPathExpression();
      NodeList nodes = (NodeList) expression.evaluate(node, XPathConstants.NODESET);
      int count = 0;
      for (int i = 0; i < nodes.getLength(); ++i) {
        if (Node.ATTRIBUTE_NODE == nodes.item(i).getNodeType()) {
          Attr attr = (Attr) nodes.item(i);
          attr.getOwnerElement().removeAttributeNode(attr);
          ++count;
          continue;
        }
        Node parentNode = nodes.item(i).getParentNode();
        if (parentNode == null) {
          continue;
        }
        parentNode.removeChild(nodes.item(i));
        ++count;
      }
      return getProxyReturnValueForMethod(proxy, method, Integer.valueOf(count));
      //            } finally {
      //                xPath.reset();
      //            }
    }
  protected StructuredSelection getNewSelection(Node node) {
    int type = node.getNodeType();
    if (type == 1) {
      // node type = element
      PictogramElement pe = null;
      Element elem = (Element) node;
      String value = elem.getAttribute("bpmnElement"); // $NON-NLS-1$
      if (value != null) {
        pe = findPictogramElement(value);
      }

      if (pe == null) {
        value = elem.getAttribute("id"); // $NON-NLS-1$
        if (value != null) pe = findPictogramElement(value);
      }

      if (pe != null) {
        return new StructuredSelection(pe);
      }
      return getNewSelection(node.getParentNode());
    } else if (type == 2) {
      // node type = attribute
      // search the attribute's owner
      Attr attr = (Attr) node;
      return getNewSelection(attr.getOwnerElement());
    } else if (type == 3) {
      // node type = text
      return getNewSelection(node.getParentNode());
    }
    return null;
  }
  public Attr setAttributeNode(Attr newAttr) throws DOMException {
    // Check if this attribute is already in use.
    Element owner = newAttr.getOwnerElement();
    if (owner != null) {
      if (owner == this) { // Replacing an attribute node by itself has no effect
        return null;
      } else {
        throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR, Messages.getString("imageio.8E"));
      }
    }

    String name = newAttr.getName();
    Attr oldAttr = getAttributeNode(name);
    if (oldAttr != null) {
      removeAttributeNode(oldAttr);
    }

    IIOMetadataAttr iioAttr;
    if (newAttr instanceof IIOMetadataAttr) {
      iioAttr = (IIOMetadataAttr) newAttr;
      iioAttr.setOwnerElement(this);
    } else {
      iioAttr = new IIOMetadataAttr(name, newAttr.getValue(), this);
    }

    attrs.list.add(iioAttr);

    return oldAttr;
  }
 @Override
 public Directive getAngularDirective(Object project, Attr attr) {
   if (attr == null) {
     return null;
   }
   return AngularModulesManager.getInstance()
       .getDirective(project, attr.getOwnerElement().getNodeName(), attr.getName(), Restriction.A);
 }
 public Node getParentNode() {
   Node parentNode = null;
   if (attribute != null) {
     parentNode = attribute.getOwnerElement();
   } else if (parent != null) {
     parentNode = parent;
   }
   return parentNode;
 }
 @Override
 public DirectiveParameter getAngularDirectiveParameter(Object project, Attr attr) {
   Element element = attr.getOwnerElement();
   // check if owner element is a directive?
   Directive elementDirective = getAngularDirective(project, element);
   if (elementDirective != null) {
     return elementDirective.getParameter(attr.getName());
   } else {
     // retrieve directives from other attributes.
     List<Directive> directives = getAngularDirectives(project, attr.getOwnerElement(), attr);
     DirectiveParameter parameter = null;
     for (Directive directive : directives) {
       parameter = directive.getParameter(attr.getName());
       if (parameter != null) {
         return parameter;
       }
     }
   }
   return null;
 }
 /**
  * {@inheritDoc}
  *
  * @see HTMLFilter#filter(Document, Map)
  */
 public void filter(Document document, Map<String, String> parameters) {
   try {
     NodeList emptyAttributes = XPathAPI.selectNodeList(document, "//@*[. = '']");
     for (int i = emptyAttributes.getLength() - 1; i >= 0; i--) {
       Attr emptyAttribute = (Attr) emptyAttributes.item(i);
       emptyAttribute.getOwnerElement().removeAttributeNode(emptyAttribute);
     }
   } catch (TransformerException e) {
     LOG.error("Exception while filtering empty attributes.", e);
   }
 }
  @Override
  public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) {
    assert attribute.getName().equals(ATTR_ID) || attribute.getLocalName().equals(ATTR_ID);
    String id = attribute.getValue();
    if (context.getPhase() == 1) {
      if (mIds.contains(id)) {
        Location location = context.getLocation(attribute);

        Attr first = findIdAttribute(attribute.getOwnerDocument(), id);
        if (first != null && first != attribute) {
          Location secondLocation = context.getLocation(first);
          secondLocation.setMessage(String.format("%1$s originally defined here", id));
          location.setSecondary(secondLocation);
        }

        context.report(
            WITHIN_LAYOUT,
            attribute,
            location,
            String.format("Duplicate id %1$s, already defined earlier in this layout", id),
            null);
      } else if (id.startsWith(NEW_ID_PREFIX)) {
        // Skip id's on include tags
        if (attribute.getOwnerElement().getTagName().equals(VIEW_INCLUDE)) {
          return;
        }

        mIds.add(id);
      }
    } else {
      Collection<Multimap<String, Occurrence>> maps = mLocations.get(context.file);
      if (maps != null && !maps.isEmpty()) {
        for (Multimap<String, Occurrence> map : maps) {
          if (!maps.isEmpty()) {
            Collection<Occurrence> occurrences = map.get(id);
            if (occurrences != null && !occurrences.isEmpty()) {
              for (Occurrence occurrence : occurrences) {
                if (context.getDriver().isSuppressed(CROSS_LAYOUT, attribute)) {
                  return;
                }
                Location location = context.getLocation(attribute);
                location.setClientData(attribute);
                location.setMessage(occurrence.message);
                location.setSecondary(occurrence.location);
                occurrence.location = location;
              }
            }
          }
        }
      }
    }
  }
  /**
   * @see
   *     com.ibm.sse.editor.extensions.hyperlink.IHyperlinkPartitionRecognizer#recognize(org.eclipse.jface.text.IDocument,
   *     com.ibm.sse.editor.extensions.hyperlink.IHyperlinkRegion)
   */
  public boolean recognize(IDocument document, int offset, IHyperlinkRegion region) {
    StructuredModelWrapper smw = new StructuredModelWrapper();
    smw.init(document);
    try {
      Document xmlDocument = smw.getDocument();
      if (xmlDocument == null) return false;

      Node n = Utils.findNodeForOffset(xmlDocument, offset);
      if (!(n instanceof Attr)) return false;

      IHyperlinkRegion r = getRegion(document, offset);
      if (r == null) return false;

      Attr attr = (Attr) n;
      String attrName = attr.getNodeName();
      if (!"var".equals(attrName) && !"basename".equals(attrName))
        return false; //$NON-NLS-1$ //$NON-NLS-2$

      Element lbTag = attr.getOwnerElement();
      String name = lbTag.getTagName();
      int column = name.indexOf(":"); // $NON-NLS-1$
      if (column == -1) return false;
      String usedPrefix = name.substring(0, column);
      if (usedPrefix == null || usedPrefix.trim().length() == 0) return false;

      String[] prefixes = getLoadBundleTagPrefixes(document, offset);
      if (prefixes == null) return true; // xhtml

      boolean prefixIsAbleToBeUsed = false;
      for (String prefix : prefixes) {
        if (usedPrefix.equals(prefix)) {
          prefixIsAbleToBeUsed = true;
          break;
        }
      }
      if (!prefixIsAbleToBeUsed) return false;

      Attr lbTagVar = lbTag.getAttributeNode("var"); // $NON-NLS-1$
      Attr lbTagBasename = lbTag.getAttributeNode("basename"); // $NON-NLS-1$

      if (lbTagVar == null
          || lbTagVar.getNodeValue() == null
          || lbTagVar.getNodeValue().trim().length() == 0) return false;
      if (lbTagBasename == null
          || lbTagBasename.getNodeValue() == null
          || lbTagBasename.getNodeValue().trim().length() == 0) return false;

      return true;
    } finally {
      smw.dispose();
    }
  }
 void deleteMe() {
   if (dom instanceof Attr) {
     Attr attr = (Attr) this.dom;
     attr.getOwnerElement()
         .getAttributes()
         .removeNamedItemNS(attr.getNamespaceURI(), attr.getLocalName());
   } else {
     if (this.dom.getParentNode() != null) {
       this.dom.getParentNode().removeChild(this.dom);
     } else {
       //    This case can be exercised at least when executing the regression
       //    tests under https://bugzilla.mozilla.org/show_bug.cgi?id=354145
     }
   }
 }
 /**
  * Runs the test case.
  *
  * @throws Throwable Any uncaught exception causes test to fail
  */
 public void runTest() throws Throwable {
   Document doc;
   NodeList addressList;
   Node testNode;
   NamedNodeMap attributes;
   Attr domesticAttr;
   Element elementNode;
   String name;
   doc = (Document) load("staff", false);
   addressList = doc.getElementsByTagName("address");
   testNode = addressList.item(0);
   attributes = testNode.getAttributes();
   domesticAttr = (Attr) attributes.getNamedItem("domestic");
   elementNode = domesticAttr.getOwnerElement();
   name = elementNode.getNodeName();
   assertEquals("throw_Equals", "address", name);
 }
 public CMAttributeDeclaration getCMAttributeDeclaration(Attr attr) {
   CMAttributeDeclaration result = null;
   Element element = attr.getOwnerElement();
   if (element != null) {
     CMElementDeclaration ed = getCMElementDeclaration(element);
     if (ed != null) {
       result = (CMAttributeDeclaration) ed.getAttributes().getNamedItem(attr.getName());
       if (result == null) {
         // try to get the unprefixed name
         String name = DOMNamespaceHelper.getUnprefixedName(attr.getName());
         result = (CMAttributeDeclaration) ed.getAttributes().getNamedItem(name);
       }
       if (result == null) {
         // todo... perhaps this is a globally defined attribute...
       }
     }
   }
   return result;
 }
  /** {@inheritDoc} */
  protected void processAttribute(XMLObject samlObject, Attr attribute)
      throws UnmarshallingException {
    EntityDescriptor entityDescriptor = (EntityDescriptor) samlObject;

    if (attribute.getLocalName().equals(EntityDescriptor.ENTITY_ID_ATTRIB_NAME)) {
      entityDescriptor.setEntityID(attribute.getValue());
    } else if (attribute.getLocalName().equals(EntityDescriptor.ID_ATTRIB_NAME)) {
      entityDescriptor.setID(attribute.getValue());
      attribute.getOwnerElement().setIdAttributeNode(attribute, true);
    } else if (attribute.getLocalName().equals(TimeBoundSAMLObject.VALID_UNTIL_ATTRIB_NAME)
        && !DatatypeHelper.isEmpty(attribute.getValue())) {
      entityDescriptor.setValidUntil(
          new DateTime(attribute.getValue(), ISOChronology.getInstanceUTC()));
    } else if (attribute.getLocalName().equals(CacheableSAMLObject.CACHE_DURATION_ATTRIB_NAME)) {
      entityDescriptor.setCacheDuration(XMLHelper.durationToLong(attribute.getValue()));
    } else {
      QName attribQName = XMLHelper.getNodeQName(attribute);
      if (attribute.isId()) {
        entityDescriptor.getUnknownAttributes().registerID(attribQName);
      }
      entityDescriptor.getUnknownAttributes().put(attribQName, attribute.getValue());
    }
  }
  /**
   * Report how to qualify the provided difference
   *
   * @param difference the difference to inspect
   * @return the difference qualification
   */
  @Override
  public int differenceFound(Difference difference) {

    NodeDetail controlDetail = difference.getControlNodeDetail();
    String controlValue = controlDetail.getValue();
    Node controlNode = controlDetail.getNode();
    NodeDetail testDetail = difference.getTestNodeDetail();
    String testValue = testDetail.getValue();

    if (controlNode != null) {
      short controlType = controlNode.getNodeType();

      switch (controlType) {
        case Node.ELEMENT_NODE:
          {
            // Check irrelevant missing attribute
            if (difference.getDescription().equals("attribute name")) {
              Element elem = (Element) controlNode;
              String attrName = controlValue.equals("null") ? testValue : controlValue;

              if (filter != null && filter.canIgnore(elem, attrName)) {
                return RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR;
              }
            }

            break;
          }

        case Node.ATTRIBUTE_NODE:
          {
            Attr attr = (Attr) controlNode;
            Element elem = attr.getOwnerElement();

            // Irrelevant attribute?
            if (filter != null && filter.canIgnore(elem, attr)) {
              return RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR;
            }

            // Tolerance on attribute value?
            if (filter != null && filter.canTolerate(elem, attr, controlValue, testValue)) {
              return RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR;
            }

            break;
          }

        case Node.TEXT_NODE:
          {
            Node controlParent = controlNode.getParentNode();

            if (controlParent != null) {
              if (filter != null && filter.canTolerate(controlParent, controlValue, testValue)) {
                return RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR;
              }

              break;
            }
          }
        default:
      }
    } else {
      /// output.dump(--diffId, difference);
      Node testNode = testDetail.getNode();
      if (filter != null && filter.canIgnore(testNode)) {
        return RETURN_IGNORE_DIFFERENCE_NODES_SIMILAR;
      }
    }

    // Default
    return RETURN_ACCEPT_DIFFERENCE;
  }
    @Override
    public Object invokeProjection(
        final String resolvedXpath, final Object proxy, final Object[] args) throws Throwable {
      //   final String pathToElement = resolvedXpath.replaceAll("\\[@",
      // "[attribute::").replaceAll("/?@.*", "").replaceAll("\\[attribute::", "[@");
      lastInvocationContext.updateMethodArgs(args);
      final Document document = DOMHelper.getOwnerDocumentFor(node);
      assert document != null;
      final Object valueToSet = args[findIndexOfValue];
      final boolean isMultiValue = isMultiValue(method.getParameterTypes()[findIndexOfValue]);
      // ROOT element update
      if ("/*".equals(resolvedXpath)) { // Setting a new root element.
        if (isMultiValue) {
          throw new IllegalArgumentException(
              "Method "
                  + method
                  + " was invoked as setter changing the document root element, but tries to set multiple values.");
        }
        return handeRootElementReplacement(proxy, method, document, valueToSet);
      }
      final boolean wildCardTarget = resolvedXpath.endsWith("/*");
      try {
        if (!lastInvocationContext.isStillValid(resolvedXpath)) {
          final DuplexExpression duplexExpression =
              wildCardTarget
                  ? new DuplexXPathParser(projector.config().getUserDefinedNamespaceMapping())
                      .compile(resolvedXpath.substring(0, resolvedXpath.length() - 2))
                  : new DuplexXPathParser(projector.config().getUserDefinedNamespaceMapping())
                      .compile(resolvedXpath);
          MethodParamVariableResolver resolver = null;
          if (duplexExpression.isUsingVariables()) {
            resolver =
                new MethodParamVariableResolver(
                    method, args, duplexExpression, projector.config().getStringRenderer(), null);
            duplexExpression.setXPathVariableResolver(resolver);
          }
          Class<?> targetComponentType = findTargetComponentType(method);
          lastInvocationContext =
              new InvocationContext(
                  resolvedXpath,
                  null,
                  null,
                  duplexExpression,
                  resolver,
                  targetComponentType,
                  projector);
        }
        final DuplexExpression duplexExpression = lastInvocationContext.getDuplexExpression();
        if (duplexExpression.getExpressionType().isMustEvalAsString()) {
          throw new XBPathException("Unwriteable xpath selector used ", method, resolvedXpath);
        }
        // MULTIVALUE
        if (isMultiValue) {
          if (duplexExpression.getExpressionType().equals(ExpressionType.ATTRIBUTE)) {
            throw new IllegalArgumentException(
                "Method "
                    + method
                    + " was invoked as setter changing some attribute, but was declared to set multiple values. I can not create multiple attributes for one path.");
          }
          final Iterable<?> iterable2Set =
              valueToSet == null
                  ? Collections.emptyList()
                  : (valueToSet.getClass().isArray())
                      ? ReflectionHelper.array2ObjectList(valueToSet)
                      : (Iterable<?>) valueToSet;
          if (wildCardTarget) {
            // TODO: check support of ParameterizedType e.g. Supplier
            final Element parentElement = (Element) duplexExpression.ensureExistence(node);
            DOMHelper.removeAllChildren(parentElement);
            int count = 0;
            for (Object o : iterable2Set) {
              if (o == null) {
                continue;
              }
              ++count;
              if (o instanceof Node) {
                DOMHelper.appendClone(parentElement, (Node) o);
                continue;
              }
              if (o instanceof DOMAccess) {
                DOMHelper.appendClone(parentElement, ((DOMAccess) o).getDOMBaseElement());
                continue;
              }
              throw new XBPathException(
                  "When using a wildcard target, the type to set must be a DOM Node or another projection. Otherwise I can not determine the element name.",
                  method,
                  resolvedXpath);
            }
            return getProxyReturnValueForMethod(proxy, method, Integer.valueOf(count));
          }
          final Element parentElement = duplexExpression.ensureParentExistence(node);
          duplexExpression.deleteAllMatchingChildren(parentElement);
          int count = applyIterableSetOnElement(iterable2Set, parentElement, duplexExpression);
          return getProxyReturnValueForMethod(proxy, method, Integer.valueOf(count));
        }

        // ATTRIBUTES
        if (duplexExpression.getExpressionType().equals(ExpressionType.ATTRIBUTE)) {
          if (wildCardTarget) {
            // TODO: This may never happen, right?
            throw new XBPathException(
                "Wildcards are not allowed when writing to an attribute. I need to know to which Element I should set the attribute",
                method,
                resolvedXpath);
          }
          Attr attribute = (Attr) duplexExpression.ensureExistence(node);
          if (valueToSet == null) {
            attribute.getOwnerElement().removeAttributeNode(attribute);
            return getProxyReturnValueForMethod(proxy, method, Integer.valueOf(1));
          }

          DOMHelper.setStringValue(attribute, valueToSet.toString());
          return getProxyReturnValueForMethod(proxy, method, Integer.valueOf(1));
        }

        if ((valueToSet instanceof Node) || (valueToSet instanceof DOMAccess)) {
          if (valueToSet instanceof Attr) {
            if (wildCardTarget) {
              throw new XBPathException(
                  "Wildcards are not allowed when writing an attribute. I need to know to which Element I should set the attribute",
                  method,
                  resolvedXpath);
            }
            Element parentNode = duplexExpression.ensureParentExistence(node);
            if (((Attr) valueToSet).getNamespaceURI() != null) {
              parentNode.setAttributeNodeNS((Attr) valueToSet);
              return getProxyReturnValueForMethod(proxy, method, Integer.valueOf(1));
            }
            parentNode.setAttributeNode((Attr) valueToSet);
            return getProxyReturnValueForMethod(proxy, method, Integer.valueOf(1));
          }
          final Element newNodeOrigin =
              valueToSet instanceof DOMAccess
                  ? ((DOMAccess) valueToSet).getDOMBaseElement()
                  : (Element) valueToSet;
          final Element newNode = (Element) newNodeOrigin.cloneNode(true);
          DOMHelper.ensureOwnership(document, newNode);
          if (wildCardTarget) {
            Element parentElement = (Element) duplexExpression.ensureExistence(node);
            DOMHelper.removeAllChildren(parentElement);
            parentElement.appendChild(newNode);
            return getProxyReturnValueForMethod(proxy, method, Integer.valueOf(1));
          }
          Element previousElement = (Element) duplexExpression.ensureExistence(node);

          DOMHelper.replaceElement(previousElement, newNode);
          return getProxyReturnValueForMethod(proxy, method, Integer.valueOf(1));
        }

        final Element elementToChange = (Element) duplexExpression.ensureExistence(node);
        if (valueToSet == null) {
          // TODO: This should depend on the parameter type?
          // If param type == String, no structural change might be expected.
          DOMHelper.removeAllChildren(elementToChange);
        } else {
          final String asString =
              projector
                  .config()
                  .getStringRenderer()
                  .render(
                      valueToSet.getClass(),
                      valueToSet,
                      duplexExpression.getExpressionFormatPattern());
          elementToChange.setTextContent(asString);
        }
        return getProxyReturnValueForMethod(proxy, method, Integer.valueOf(1));
      } catch (XBPathParsingException e) {
        throw new XBPathException(e, method, resolvedXpath);
      }
    }