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

devonfw / IDEasy / 9907372175

12 Jul 2024 11:49AM UTC coverage: 61.142% (-0.02%) from 61.162%
9907372175

push

github

hohwille
fixed tests

1997 of 3595 branches covered (55.55%)

Branch coverage included in aggregate %.

5296 of 8333 relevant lines covered (63.55%)

2.8 hits per line

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

76.81
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 java.util.Collections;
4
import java.util.Iterator;
5
import javax.xml.XMLConstants;
6
import javax.xml.namespace.NamespaceContext;
7
import javax.xml.xpath.XPath;
8
import javax.xml.xpath.XPathConstants;
9
import javax.xml.xpath.XPathExpression;
10
import javax.xml.xpath.XPathExpressionException;
11
import javax.xml.xpath.XPathFactory;
12

13
import org.w3c.dom.Element;
14
import org.w3c.dom.NodeList;
15

16
import com.devonfw.tools.ide.merge.xmlmerger.model.MergeElement;
17

18
/**
19
 * The IdComputer class is responsible for building XPath expressions and evaluating those expressions to match elements in a target document.
20
 */
21
public class IdComputer {
22

23
  /**
24
   * the value of merge:id that is used to evaluate the xpath expression.
25
   */
26
  private final String id;
27

28
  private static final XPathFactory xPathFactory = XPathFactory.newInstance();
3✔
29

30
  public IdComputer(String id) {
2✔
31

32
    this.id = id;
3✔
33
  }
1✔
34

35
  /**
36
   * @return the value of id.
37
   */
38
  public String getId() {
39

40
    return this.id;
3✔
41
  }
42

43
  /**
44
   * Evaluates the XPath expression for the given merge element in the target element.
45
   *
46
   * @param sourceElement the merge element for which to build the XPath expression
47
   * @param targetElement the target element in which to evaluate the XPath expression
48
   * @return the matched Element if found, or null if not found
49
   */
50

51
  public Element evaluateExpression(MergeElement sourceElement, MergeElement targetElement) {
52
    try {
53
      XPath xpath = xPathFactory.newXPath();
3✔
54
      final String elementPrefix = sourceElement.getElement().getPrefix();
4✔
55
      final String elementNamespaceURI = sourceElement.getElement().getNamespaceURI();
4✔
56

57
      if (elementPrefix != null && !elementPrefix.isEmpty()) {
5!
58
        xpath.setNamespaceContext(new NamespaceContext() { // simple impl of NameSpaceContext that should suffice for our usecases
20✔
59
          @Override
60
          public String getNamespaceURI(String prefix) {
61
            return prefix.equals(elementPrefix) ? elementNamespaceURI : XMLConstants.NULL_NS_URI;
9!
62
          }
63

64
          @Override
65
          public String getPrefix(String namespaceURI) {
66
            return namespaceURI.equals(elementNamespaceURI) ? elementPrefix : null;
×
67
          }
68

69
          @Override
70
          public Iterator<String> getPrefixes(String namespaceURI) {
71
            return Collections.singletonList(getPrefix(namespaceURI)).iterator();
×
72
          }
73
        });
74
      }
75

76
      String xpathExpr = buildXPathExpression(sourceElement);
4✔
77
      XPathExpression xpathExpression = xpath.compile(xpathExpr);
4✔
78
      NodeList nodeList = (NodeList) xpathExpression.evaluate(targetElement.getElement(), XPathConstants.NODESET);
7✔
79
      int length = nodeList.getLength();
3✔
80
      if (length > 1) {
3!
81
        throw new IllegalStateException(
×
82
            length + " matches found when trying to match element " + sourceElement.getXPath() + " in target document " + targetElement.getDocumentPath());
×
83
      } else {
84
        return (Element) nodeList.item(0);
5✔
85
      }
86
    } catch (XPathExpressionException e) {
×
87
      throw new IllegalStateException("Failed to match " + sourceElement.getXPath(), e);
×
88
    }
89
  }
90

91
  /**
92
   * Builds the XPath expression for the given merge element based on the ID value.
93
   *
94
   * @param mergeElement the merge element for which to build the XPath expression
95
   * @return the XPath expression as a String
96
   */
97
  private String buildXPathExpression(MergeElement mergeElement) {
98

99
    Element element = mergeElement.getElement();
3✔
100
    String namespaceURI = element.getNamespaceURI();
3✔
101
    String localName = element.getLocalName();
3✔
102
    String prefix = element.getPrefix();
3✔
103

104
    StringBuilder xpathBuilder = new StringBuilder();
4✔
105
    if (prefix != null && !prefix.isEmpty()) {
5!
106
      xpathBuilder.append(prefix).append(":");
6✔
107
    }
108
    xpathBuilder.append(localName);
4✔
109

110
    if (this.id.startsWith("@")) {
5✔
111
      String attributeName = this.id.substring(1);
5✔
112
      String attributeValue = element.getAttribute(attributeName);
4✔
113
      xpathBuilder.append(String.format("[@%s='%s']", attributeName, attributeValue));
15✔
114
    } else if (this.id.equals("name()")) {
6✔
115
      xpathBuilder.append(String.format("[local-name()='%s']", localName));
11✔
116
      if (namespaceURI != null && !namespaceURI.isEmpty()) {
2!
117
        xpathBuilder.append(String.format(" and namespace-uri()='%s'", namespaceURI));
×
118
      }
119
    } else if (this.id.equals("text()")) {
5✔
120
      String textContent = element.getTextContent();
3✔
121
      xpathBuilder.append(String.format("[text()='%s']", textContent));
11✔
122
    } else { // custom xpath like ../element[@attr='value']
1✔
123
      return this.id;
3✔
124
    }
125

126
    return xpathBuilder.toString();
3✔
127
  }
128

129
}
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