001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.http.header;
014
015import static org.apache.juneau.common.internal.ArgUtils.*;
016
017import java.util.NoSuchElementException;
018
019import org.apache.http.Header;
020import org.apache.http.HeaderIterator;
021import org.apache.juneau.common.internal.*;
022
023/**
024 * Basic implementation of a {@link HeaderIterator}.
025 *
026 * <h5 class='section'>Notes:</h5><ul>
027 *    <li class='warn'>This class is not thread safe.
028 * </ul>
029 *
030 * <h5 class='section'>See Also:</h5><ul>
031 *    <li class='link'><a class="doclink" href="../../../../../index.html#juneau-rest-common">juneau-rest-common</a>
032 *    <li class='extlink'><a class="doclink" href="https://www.w3.org/Protocols/rfc2616/rfc2616.html">Hypertext Transfer Protocol -- HTTP/1.1</a>
033 * </ul>
034 */
035public class BasicHeaderIterator implements HeaderIterator {
036
037   private final Header[] entries;
038   private final String name;
039   private final boolean caseSensitive;
040
041   private int currentIndex;
042
043   /**
044    * Creates a new header iterator.
045    *
046    * @param headers An array of headers over which to iterate.
047    * @param name The name of the headers over which to iterate, or <jk>null</jk> for all.
048    * @param caseSensitive Use case-sensitive matching for part name.
049    */
050   public BasicHeaderIterator(Header[] headers, String name, boolean caseSensitive) {
051      this.entries = assertArgNotNull("headers", headers);
052      this.name = name;
053      this.caseSensitive = caseSensitive;
054      this.currentIndex = findNext(-1);
055   }
056
057   private int findNext(int pos) {
058
059      int from = pos;
060
061      int to = entries.length - 1;
062      boolean found = false;
063      while (!found && (from < to)) {
064         from++;
065         found = filter(from);
066      }
067
068      return found ? from : -1;
069   }
070
071   private boolean filter(int index) {
072      return (name == null) || eq(name, entries[index].getName());
073   }
074
075   @Override /* HeaderIterator */
076   public boolean hasNext() {
077      return (currentIndex >= 0);
078   }
079
080   @Override /* HeaderIterator */
081   public Header nextHeader() throws NoSuchElementException {
082
083      int current = currentIndex;
084
085      if (current < 0)
086         throw new NoSuchElementException("Iteration already finished.");
087
088      currentIndex = findNext(current);
089
090      return entries[current];
091   }
092
093   @Override /* HeaderIterator */
094   public final Object next() throws NoSuchElementException {
095      return nextHeader();
096   }
097
098   /**
099    * Not supported.
100    */
101   @Override /* HeaderIterator */
102   public void remove() {
103      throw new UnsupportedOperationException("Not supported.");
104   }
105
106   private boolean eq(String s1, String s2) {
107      return StringUtils.eq(!caseSensitive, s1, s2);
108   }
109}