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