View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.configuration2.tree.xpath;
18  
19  import java.util.ArrayList;
20  import java.util.LinkedHashSet;
21  import java.util.List;
22  import java.util.Set;
23  
24  import org.apache.commons.jxpath.ri.QName;
25  import org.apache.commons.jxpath.ri.model.NodePointer;
26  import org.apache.commons.lang3.Strings;
27  
28  /**
29   * A specialized node iterator implementation that deals with attribute nodes.
30   *
31   * @param <T> the type of the nodes this iterator deals with
32   */
33  final class ConfigurationNodeIteratorAttribute<T> extends AbstractConfigurationNodeIterator<T> {
34  
35      /** Constant for the wildcard node name. */
36      private static final String WILDCARD = "*";
37  
38      /** Stores the parent node pointer. */
39      private final ConfigurationNodePointer<T> parentPointer;
40  
41      /** A list with the names of the managed attributes. */
42      private final List<String> attributeNames;
43  
44      /**
45       * Creates a new instance of {@code ConfigurationNodeIteratorAttribute}.
46       *
47       * @param parent the parent node pointer
48       * @param qName the name of the selected attribute
49       */
50      public ConfigurationNodeIteratorAttribute(final ConfigurationNodePointer<T> parent, final QName qName) {
51          super(parent, false);
52          parentPointer = parent;
53          attributeNames = createAttributeDataList(parent, qName);
54      }
55  
56      /**
57       * Helper method for checking whether an attribute is defined and adding it to the list of attributes to iterate over.
58       *
59       * @param parent the parent node pointer
60       * @param result the result list
61       * @param name the name of the current attribute
62       */
63      private void addAttributeData(final ConfigurationNodePointer<T> parent, final List<String> result, final String name) {
64          if (parent.getNodeHandler().getAttributeValue(parent.getConfigurationNode(), name) != null) {
65              result.add(name);
66          }
67      }
68  
69      /**
70       * Determines which attributes are selected based on the passed in node name.
71       *
72       * @param parent the parent node pointer
73       * @param qName the name of the selected attribute
74       * @return a list with the selected attributes
75       */
76      private List<String> createAttributeDataList(final ConfigurationNodePointer<T> parent, final QName qName) {
77          final List<String> result = new ArrayList<>();
78          if (!WILDCARD.equals(qName.getName())) {
79              addAttributeData(parent, result, qualifiedName(qName));
80          } else {
81              final Set<String> names = new LinkedHashSet<>(parent.getNodeHandler().getAttributes(parent.getConfigurationNode()));
82              final String prefix = qName.getPrefix() != null ? prefixName(qName.getPrefix(), null) : null;
83              names.forEach(n -> {
84                  if (prefix == null || Strings.CS.startsWith(n, prefix)) {
85                      addAttributeData(parent, result, n);
86                  }
87              });
88          }
89  
90          return result;
91      }
92  
93      /**
94       * Creates a pointer for the node at the specified position.
95       *
96       * @param position the desired position
97       * @return a pointer for the attribute at this position
98       */
99      @Override
100     protected NodePointer createNodePointer(final int position) {
101         return new ConfigurationAttributePointer<>(parentPointer, attributeNames.get(position));
102     }
103 
104     /**
105      * Returns the size of the managed iteration.
106      *
107      * @return the iteration size
108      */
109     @Override
110     protected int size() {
111         return attributeNames.size();
112     }
113 }