View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.http.message;
29  
30  import java.util.Iterator;
31  import java.util.NoSuchElementException;
32  
33  import org.apache.hc.core5.http.FormattedHeader;
34  import org.apache.hc.core5.http.Header;
35  import org.apache.hc.core5.util.Args;
36  
37  /**
38   * {@link java.util.Iterator} of {@link org.apache.hc.core5.http.HeaderElement}s.
39   *
40   * @since 5.0
41   */
42  abstract class AbstractHeaderElementIterator<T> implements Iterator<T> {
43  
44      private final Iterator<Header> headerIt;
45  
46      private T currentElement;
47      private CharSequence buffer;
48      private ParserCursor cursor;
49  
50      /**
51       * Creates a new instance of BasicHeaderElementIterator
52       */
53      AbstractHeaderElementIterator(final Iterator<Header> headerIterator) {
54          this.headerIt = Args.notNull(headerIterator, "Header iterator");
55      }
56  
57      private void bufferHeaderValue() {
58          this.cursor = null;
59          this.buffer = null;
60          while (this.headerIt.hasNext()) {
61              final Header h = this.headerIt.next();
62              if (h instanceof FormattedHeader) {
63                  this.buffer = ((FormattedHeader) h).getBuffer();
64                  this.cursor = new ParserCursor(0, this.buffer.length());
65                  this.cursor.updatePos(((FormattedHeader) h).getValuePos());
66                  break;
67              }
68              final String value = h.getValue();
69              if (value != null) {
70                  this.buffer = value;
71                  this.cursor = new ParserCursor(0, value.length());
72                  break;
73              }
74          }
75      }
76  
77      abstract T parseHeaderElement(CharSequence buf, ParserCursor cursor);
78  
79      private void parseNextElement() {
80          // loop while there are headers left to parse
81          while (this.headerIt.hasNext() || this.cursor != null) {
82              if (this.cursor == null || this.cursor.atEnd()) {
83                  // get next header value
84                  bufferHeaderValue();
85              }
86              // Anything buffered?
87              if (this.cursor != null) {
88                  // loop while there is data in the buffer
89                  while (!this.cursor.atEnd()) {
90                      final T e = parseHeaderElement(this.buffer, this.cursor);
91                      if (e != null) {
92                          // Found something
93                          this.currentElement = e;
94                          return;
95                      }
96                  }
97                  // if at the end of the buffer
98                  if (this.cursor.atEnd()) {
99                      // discard it
100                     this.cursor = null;
101                     this.buffer = null;
102                 }
103             }
104         }
105     }
106 
107     @Override
108     public boolean hasNext() {
109         if (this.currentElement == null) {
110             parseNextElement();
111         }
112         return this.currentElement != null;
113     }
114 
115     @Override
116     public T next() throws NoSuchElementException {
117         if (this.currentElement == null) {
118             parseNextElement();
119         }
120 
121         if (this.currentElement == null) {
122             throw new NoSuchElementException("No more header elements available");
123         }
124 
125         final T element = this.currentElement;
126         this.currentElement = null;
127         return element;
128     }
129 
130     @Override
131     public void remove() throws UnsupportedOperationException {
132         throw new UnsupportedOperationException("Remove not supported");
133     }
134 
135 }