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.part;
018
019import java.util.*;
020
021import org.apache.http.*;
022import org.apache.juneau.common.utils.*;
023
024/**
025 * Basic implementation of a {@link PartIterator}.
026 *
027 * <h5 class='section'>Notes:</h5><ul>
028 *    <li class='warn'>This class is not thread safe.
029 * </ul>
030 *
031 * <h5 class='section'>See Also:</h5><ul>
032 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommonBasics">juneau-rest-common Basics</a>
033 * </ul>
034 */
035public class BasicPartIterator implements PartIterator {
036
037   private final NameValuePair[] entries;
038   private final String name;
039   private final boolean caseInsensitive;
040
041   private int currentIndex;
042
043   /**
044    * Creates a new part iterator.
045    *
046    * @param parts An array of parts over which to iterate.
047    * @param name The name of the parts over which to iterate, or <jk>null</jk> for all.
048    * @param caseInsensitive Use case-insensitive matching for part name.
049    */
050   public BasicPartIterator(NameValuePair[] parts, String name, boolean caseInsensitive) {
051      this.entries = Utils.assertArgNotNull("parts", parts);
052      this.name = name;
053      this.caseInsensitive = caseInsensitive;
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 /* Iterator */
076   public boolean hasNext() {
077      return (currentIndex >= 0);
078   }
079
080   @Override /* Iterator */
081   public NameValuePair next() 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   /**
094    * Not supported.
095    */
096   @Override /* Iterator */
097   public void remove() throws UnsupportedOperationException {
098      throw new UnsupportedOperationException("Not supported.");
099   }
100
101   private boolean eq(String s1, String s2) {
102      return Utils.eq(caseInsensitive, s1, s2);
103   }
104}