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.config;
29  
30  import org.apache.hc.core5.util.Args;
31  
32  /**
33   * Chain of doubly linked elements.
34   * <p>
35   * This implementation makes no attempts to ensure uniqueness of element names.
36   *
37   * @param <E>
38   */
39  public class NamedElementChain<E> {
40  
41      private final Node master;
42      private int size;
43  
44      public NamedElementChain() {
45          this.master = new Node("master", null);
46          this.master.previous = this.master;
47          this.master.next = this.master;
48          this.size = 0;
49      }
50  
51      public Node getFirst() {
52          if (master.next != master) {
53              return master.next;
54          } else {
55              return null;
56          }
57      }
58  
59      public Node getLast() {
60          if (master.previous != master) {
61              return master.previous;
62          } else {
63              return null;
64          }
65      }
66  
67      public Node addFirst(final E value, final String name) {
68          Args.notBlank(name, "Name");
69          Args.notNull(value, "Value");
70          final Node newNode = new Node(name, value);
71          final Node oldNode = master.next;
72          master.next = newNode;
73          newNode.previous = master;
74          newNode.next = oldNode;
75          oldNode.previous = newNode;
76          size++;
77          return newNode;
78      }
79  
80      public Node addLast(final E value, final String name) {
81          Args.notBlank(name, "Name");
82          Args.notNull(value, "Value");
83          final Node newNode = new Node(name, value);
84          final Node oldNode = master.previous;
85          master.previous = newNode;
86          newNode.previous = oldNode;
87          newNode.next = master;
88          oldNode.next = newNode;
89          size++;
90          return newNode;
91      }
92  
93      public Node find(final String name) {
94          Args.notBlank(name, "Name");
95          return doFind(name);
96      }
97  
98      private Node doFind(final String name) {
99          Node current = master.next;
100         while (current != master) {
101             if (name.equals(current.name)) {
102                 return current;
103             }
104             current = current.next;
105         }
106         return null;
107     }
108 
109     public Node addBefore(final String existing, final E value, final String name) {
110         Args.notBlank(name, "Name");
111         Args.notNull(value, "Value");
112         final Node current = doFind(existing);
113         if (current == null) {
114             return null;
115         }
116         final Node newNode = new Node(name, value);
117         final Node previousNode = current.previous;
118         previousNode.next = newNode;
119         newNode.previous = previousNode;
120         newNode.next = current;
121         current.previous = newNode;
122         size++;
123         return newNode;
124     }
125 
126     public Node addAfter(final String existing, final E value, final String name) {
127         Args.notBlank(name, "Name");
128         Args.notNull(value, "Value");
129         final Node current = doFind(existing);
130         if (current == null) {
131             return null;
132         }
133         final Node newNode = new Node(name, value);
134         final Node nextNode = current.next;
135         current.next = newNode;
136         newNode.previous = current;
137         newNode.next = nextNode;
138         nextNode.previous = newNode;
139         size++;
140         return newNode;
141     }
142 
143     public boolean remove(final String name) {
144         final Node node = doFind(name);
145         if (node == null) {
146             return false;
147         }
148         node.previous.next = node.next;
149         node.next.previous = node.previous;
150         node.previous = null;
151         node.next = null;
152         size--;
153         return true;
154     }
155 
156     public boolean replace(final String existing, final E value) {
157         final Node node = doFind(existing);
158         if (node == null) {
159             return false;
160         }
161         node.value = value;
162         return true;
163     }
164 
165     public int getSize() {
166         return size;
167     }
168 
169     public class Node {
170 
171         private final String name;
172         private E value;
173         private Node previous;
174         private Node next;
175 
176         Node(final String name, final E value) {
177             this.name = name;
178             this.value = value;
179         }
180 
181         public String getName() {
182             return name;
183         }
184 
185         public E getValue() {
186             return value;
187         }
188 
189         public Node getPrevious() {
190             if (previous != master) {
191                 return previous;
192             } else {
193                 return null;
194             }
195         }
196 
197         public Node getNext() {
198             if (next != master) {
199                 return next;
200             } else {
201                 return null;
202             }
203         }
204 
205         @Override
206         public String toString() {
207             return name + ": " + value;
208         }
209 
210     }
211 
212 }