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 }