View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.project.harness;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import org.apache.commons.jxpath.ri.Compiler;
25  import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
26  import org.apache.commons.jxpath.ri.compiler.NodeTest;
27  import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
28  import org.apache.commons.jxpath.ri.model.NodeIterator;
29  import org.apache.commons.jxpath.ri.model.NodePointer;
30  import org.apache.maven.api.xml.XmlNode;
31  import org.codehaus.plexus.util.xml.Xpp3Dom;
32  
33  /**
34   * A node iterator for JXPath to support <code>Xpp3Dom</code>.
35   *
36   */
37  class Xpp3DomNodeIterator implements NodeIterator {
38  
39      private NodePointer parent;
40  
41      private NodeTest test;
42  
43      private XmlNode node;
44  
45      private List<XmlNode> children;
46  
47      private List<XmlNode> filteredChildren = new ArrayList<>();
48  
49      private int filteredIndex;
50  
51      private XmlNode child;
52  
53      private int position;
54  
55      public Xpp3DomNodeIterator(NodePointer parent, NodeTest test, boolean reverse, NodePointer startWith) {
56          this.parent = parent;
57          this.node = (XmlNode) parent.getNode();
58          this.children = this.node.getChildren();
59          if (startWith != null) {
60              Xpp3Dom startWithNode = (Xpp3Dom) startWith.getNode();
61              for (; filteredIndex < children.size(); filteredIndex++) {
62                  if (startWithNode.equals(children.get(filteredIndex))) {
63                      filteredIndex++;
64                      break;
65                  }
66              }
67          }
68          this.test = test;
69          if (reverse) {
70              throw new UnsupportedOperationException();
71          }
72      }
73  
74      public NodePointer getNodePointer() {
75          if (position == 0) {
76              setPosition(1);
77          }
78          return (child == null) ? null : new Xpp3DomNodePointer(parent, child);
79      }
80  
81      public int getPosition() {
82          return position;
83      }
84  
85      public boolean setPosition(int position) {
86          this.position = position;
87          filterChildren(position);
88          child = (position > 0 && position <= filteredChildren.size()) ? filteredChildren.get(position - 1) : null;
89          return child != null;
90      }
91  
92      private void filterChildren(int position) {
93          for (; position > filteredChildren.size() && filteredIndex < children.size(); filteredIndex++) {
94              XmlNode child = children.get(filteredIndex);
95              if (testNode(child)) {
96                  filteredChildren.add(child);
97              }
98          }
99      }
100 
101     private boolean testNode(XmlNode node) {
102         if (test == null) {
103             return true;
104         }
105         if (test instanceof NodeNameTest) {
106             String nodeName = node.getName();
107             if (nodeName == null || nodeName.isEmpty()) {
108                 return false;
109             }
110 
111             NodeNameTest nodeNameTest = (NodeNameTest) test;
112             String namespaceURI = nodeNameTest.getNamespaceURI();
113             boolean wildcard = nodeNameTest.isWildcard();
114             String testName = nodeNameTest.getNodeName().getName();
115             String testPrefix = nodeNameTest.getNodeName().getPrefix();
116             if (wildcard && testPrefix == null) {
117                 return true;
118             }
119             if (wildcard || testName.equals(nodeName)) {
120                 return (namespaceURI == null || namespaceURI.isEmpty()) || (testPrefix == null || testPrefix.isEmpty());
121             }
122             return false;
123         }
124         if (test instanceof NodeTypeTest) {
125             switch (((NodeTypeTest) test).getNodeType()) {
126                 case Compiler.NODE_TYPE_NODE:
127                     return true;
128                 case Compiler.NODE_TYPE_TEXT:
129                     return node.getValue() != null;
130                 default:
131                     return false;
132             }
133         }
134         return false;
135     }
136 }