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  import org.apache.commons.jxpath.ri.Compiler;
24  import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
25  import org.apache.commons.jxpath.ri.compiler.NodeTest;
26  import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
27  import org.apache.commons.jxpath.ri.model.NodeIterator;
28  import org.apache.commons.jxpath.ri.model.NodePointer;
29  import org.apache.maven.api.xml.Dom;
30  import org.codehaus.plexus.util.StringUtils;
31  import org.codehaus.plexus.util.xml.Xpp3Dom;
32  
33  /**
34   * A node iterator for JXPath to support <code>Xpp3Dom</code>.
35   *
36   * @author Benjamin Bentmann
37   */
38  class Xpp3DomNodeIterator implements NodeIterator {
39  
40      private NodePointer parent;
41  
42      private NodeTest test;
43  
44      private Dom node;
45  
46      private List<Dom> children;
47  
48      private List<Dom> filteredChildren = new ArrayList<>();
49  
50      private int filteredIndex;
51  
52      private Dom child;
53  
54      private int position;
55  
56      public Xpp3DomNodeIterator(NodePointer parent, NodeTest test, boolean reverse, NodePointer startWith) {
57          this.parent = parent;
58          this.node = (Dom) parent.getNode();
59          this.children = this.node.getChildren();
60          if (startWith != null) {
61              Xpp3Dom startWithNode = (Xpp3Dom) startWith.getNode();
62              for (; filteredIndex < children.size(); filteredIndex++) {
63                  if (startWithNode.equals(children.get(filteredIndex))) {
64                      filteredIndex++;
65                      break;
66                  }
67              }
68          }
69          this.test = test;
70          if (reverse) {
71              throw new UnsupportedOperationException();
72          }
73      }
74  
75      public NodePointer getNodePointer() {
76          if (position == 0) {
77              setPosition(1);
78          }
79          return (child == null) ? null : new Xpp3DomNodePointer(parent, child);
80      }
81  
82      public int getPosition() {
83          return position;
84      }
85  
86      public boolean setPosition(int position) {
87          this.position = position;
88          filterChildren(position);
89          child = (position > 0 && position <= filteredChildren.size()) ? filteredChildren.get(position - 1) : null;
90          return child != null;
91      }
92  
93      private void filterChildren(int position) {
94          for (; position > filteredChildren.size() && filteredIndex < children.size(); filteredIndex++) {
95              Dom child = children.get(filteredIndex);
96              if (testNode(child)) {
97                  filteredChildren.add(child);
98              }
99          }
100     }
101 
102     private boolean testNode(Dom node) {
103         if (test == null) {
104             return true;
105         }
106         if (test instanceof NodeNameTest) {
107             String nodeName = node.getName();
108             if (StringUtils.isEmpty(nodeName)) {
109                 return false;
110             }
111 
112             NodeNameTest nodeNameTest = (NodeNameTest) test;
113             String namespaceURI = nodeNameTest.getNamespaceURI();
114             boolean wildcard = nodeNameTest.isWildcard();
115             String testName = nodeNameTest.getNodeName().getName();
116             String testPrefix = nodeNameTest.getNodeName().getPrefix();
117             if (wildcard && testPrefix == null) {
118                 return true;
119             }
120             if (wildcard || testName.equals(nodeName)) {
121                 return StringUtils.isEmpty(namespaceURI) || StringUtils.isEmpty(testPrefix);
122             }
123             return false;
124         }
125         if (test instanceof NodeTypeTest) {
126             switch (((NodeTypeTest) test).getNodeType()) {
127                 case Compiler.NODE_TYPE_NODE:
128                     return true;
129                 case Compiler.NODE_TYPE_TEXT:
130                     return node.getValue() != null;
131                 default:
132                     return false;
133             }
134         }
135         return false;
136     }
137 }