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    *     http://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  
18  package org.apache.commons.configuration;
19  
20  import java.util.Iterator;
21  import java.util.NoSuchElementException;
22  
23  /**
24   * * A specialized iterator implementation used by {@link AbstractConfiguration}
25   * to return an iteration over all keys starting with a specified prefix.
26   *
27   * <p>This class is basically a stripped-down version of the
28   * {@code FilterIterator} class of Commons Collections</p>
29   *
30   * @author <a href="http://commons.apache.org/configuration/team-list.html">Commons Configuration team</a>
31   * @version $Id: PrefixedKeysIterator.java 1205603 2011-11-23 21:17:38Z oheger $
32   */
33  class PrefixedKeysIterator implements Iterator<String>
34  {
35      /** Stores the wrapped iterator. */
36      private final Iterator<String> iterator;
37  
38      /** Stores the prefix. */
39      private final String prefix;
40  
41      /** Stores the next element in the iteration. */
42      private String nextElement;
43  
44      /** A flag whether the next element has been calculated. */
45      private boolean nextElementSet;
46  
47      /**
48       * Creates a new instance of {@code PrefixedKeysIterator} and sets
49       * the wrapped iterator and the prefix for the accepted keys.
50       *
51       * @param wrappedIterator the wrapped iterator
52       * @param keyPrefix the prefix of the allowed keys
53       */
54      public PrefixedKeysIterator(Iterator<String> wrappedIterator, String keyPrefix)
55      {
56          iterator = wrappedIterator;
57          prefix = keyPrefix;
58      }
59  
60      /**
61       * Returns a flag whether there are more elements in the iteration.
62       *
63       * @return a flag if there is a next element
64       */
65      public boolean hasNext()
66      {
67          return nextElementSet || setNextElement();
68      }
69  
70      /**
71       * Returns the next element in the iteration. This is the next key that
72       * matches the specified prefix.
73       *
74       * @return the next element in the iteration
75       * @throws NoSuchElementException if there is no next element
76       */
77      public String next()
78      {
79          if (!nextElementSet && !setNextElement())
80          {
81              throw new NoSuchElementException();
82          }
83          nextElementSet = false;
84          return nextElement;
85      }
86  
87      /**
88       * Removes from the underlying collection of the base iterator the last
89       * element returned by this iterator. This method can only be called if
90       * {@code next()} was called, but not after {@code hasNext()},
91       * because the {@code hasNext()} call changes the base iterator.
92       *
93       * @throws IllegalStateException if {@code hasNext()} has already
94       *         been called.
95       */
96      public void remove()
97      {
98          if (nextElementSet)
99          {
100             throw new IllegalStateException("remove() cannot be called");
101         }
102         iterator.remove();
103     }
104 
105     /**
106      * Determines the next element in the iteration. The return value indicates
107      * whether such an element can be found.
108      *
109      * @return a flag whether a next element exists
110      */
111     private boolean setNextElement()
112     {
113         while (iterator.hasNext())
114         {
115             String key = iterator.next();
116             if (key.startsWith(prefix + ".") || key.equals(prefix))
117             {
118                 nextElement = key;
119                 nextElementSet = true;
120                 return true;
121             }
122         }
123         return false;
124     }
125 }