• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 12814582559

16 Jan 2025 05:44PM UTC coverage: 68.152% (+0.3%) from 67.83%
12814582559

Pull #912

github

web-flow
Merge 770216085 into 0dc965a5d
Pull Request #912: #498: resolve variables on load #691: solve sub-node merging

2709 of 4345 branches covered (62.35%)

Branch coverage included in aggregate %.

7021 of 9932 relevant lines covered (70.69%)

3.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.03
cli/src/main/java/com/devonfw/tools/ide/merge/xmlmerger/matcher/IdComputer.java
1
package com.devonfw.tools.ide.merge.xmlmerger.matcher;
2

3
import javax.xml.xpath.XPath;
4
import javax.xml.xpath.XPathConstants;
5
import javax.xml.xpath.XPathExpression;
6
import javax.xml.xpath.XPathExpressionException;
7
import javax.xml.xpath.XPathFactory;
8

9
import org.w3c.dom.Element;
10
import org.w3c.dom.NodeList;
11

12
import com.devonfw.tools.ide.merge.xmlmerger.XmlMergeSupport;
13

14
/**
15
 * The IdComputer class is responsible for building XPath expressions and evaluating those expressions to match elements in a target document.
16
 */
17
public class IdComputer {
18

19
  /** The value of merge:id that is used to evaluate the xpath expression. */
20
  private final String id;
21

22
  private static final XPathFactory xPathFactory = XPathFactory.newInstance();
3✔
23

24
  /**
25
   * The constructor.
26
   *
27
   * @param id the {@link #getId() merge ID}.
28
   */
29
  public IdComputer(String id) {
30

31
    super();
2✔
32
    this.id = id;
3✔
33
  }
1✔
34

35
  /**
36
   * @return the value of "merge:id" attribute what is an {@link XPath} expression.
37
   * @see XmlMergeSupport#getMergeId(Element)
38
   */
39
  public String getId() {
40

41
    return this.id;
×
42
  }
43

44
  /**
45
   * Evaluates the XPath expression for the given merge element in the target element.
46
   *
47
   * @param templateElement the template {@link Element} for which to build the {@link XPath} expression.
48
   * @param workspaceElement the workspace {@link Element} in which to evaluate the {@link XPath} expression.
49
   * @return the matched Element if found, or {@code null} if not found
50
   */
51
  public Element evaluateExpression(Element templateElement, Element workspaceElement) {
52
    XPath xpath = xPathFactory.newXPath();
3✔
53
    xpath.setNamespaceContext(new NamespaceContextFromElement(templateElement));
6✔
54
    String xpathExpr = buildXPathExpression(templateElement);
4✔
55
    try {
56
      XPathExpression xpathExpression = xpath.compile(xpathExpr);
4✔
57
      NodeList nodeList = (NodeList) xpathExpression.evaluate(workspaceElement, XPathConstants.NODESET);
6✔
58
      int length = nodeList.getLength();
3✔
59
      if (length == 1) {
3✔
60
        return (Element) nodeList.item(0);
5✔
61
      } else if (length == 0) {
2!
62
        return null;
2✔
63
      } else {
64
        throw new IllegalStateException(
×
65
            length + " matches found for XPath " + xpathExpr + " in workspace XML at " + XmlMergeSupport.getXPath(workspaceElement, true));
×
66
      }
67
    } catch (XPathExpressionException e) {
×
68
      throw new IllegalStateException("Failed to compile XPath expression " + xpath, e);
×
69
    }
70
  }
71

72
  /**
73
   * Builds the XPath expression for the given merge element based on the {@link #getId()} merge:id} value.
74
   *
75
   * @param element the {@link Element} for which to build the XPath expression
76
   * @return the XPath expression as a {@link String}.
77
   */
78
  private String buildXPathExpression(Element element) {
79

80
    String namespaceURI = element.getNamespaceURI();
3✔
81
    String localName = element.getLocalName();
3✔
82
    if (localName == null) {
2!
83
      localName = element.getTagName();
×
84
    }
85
    String prefix = element.getPrefix();
3✔
86

87
    StringBuilder xpathBuilder = new StringBuilder(localName.length());
6✔
88
    if ((prefix != null) && !prefix.isEmpty()) {
5!
89
      xpathBuilder.append(prefix).append(":");
6✔
90
    }
91
    xpathBuilder.append(localName);
4✔
92
    if (this.id.startsWith("@")) {
5✔
93
      String attributeName = this.id.substring(1);
5✔
94
      String attributeValue = element.getAttribute(attributeName);
4✔
95
      xpathBuilder.append('[').append(this.id).append("='").append(XmlMergeSupport.escapeSingleQuotes(attributeValue)).append("']");
14✔
96
    } else if (this.id.equals(XmlMergeSupport.XPATH_ELEMENT_NAME)) {
6✔
97
      xpathBuilder.append("[local-name()='").append(localName).append("']");
8✔
98
      if ((namespaceURI != null) && !namespaceURI.isEmpty()) {
2!
99
        xpathBuilder.append(" and namespace-uri()='").append(namespaceURI).append('\'');
×
100
      }
101
    } else if (this.id.equals(XmlMergeSupport.XPATH_ELEMENT_TEXT)) {
5✔
102
      String textContent = element.getTextContent();
3✔
103
      xpathBuilder.append("[text()='").append(XmlMergeSupport.escapeSingleQuotes(textContent)).append("']");
9✔
104
    } else { // custom xpath like ../element[@attr='value']
1✔
105
      return this.id;
3✔
106
    }
107
    return xpathBuilder.toString();
3✔
108
  }
109

110
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc