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          return master.next != master ? master.next : null;
53      }
54  
55      public Node getLast() {
56          return master.previous != master ? master.previous : null;
57      }
58  
59      public Node addFirst(final E value, final String name) {
60          Args.notBlank(name, "Name");
61          Args.notNull(value, "Value");
62          final Node newNode = new Node(name, value);
63          final Node oldNode = master.next;
64          master.next = newNode;
65          newNode.previous = master;
66          newNode.next = oldNode;
67          oldNode.previous = newNode;
68          size++;
69          return newNode;
70      }
71  
72      public Node addLast(final E value, final String name) {
73          Args.notBlank(name, "Name");
74          Args.notNull(value, "Value");
75          final Node newNode = new Node(name, value);
76          final Node oldNode = master.previous;
77          master.previous = newNode;
78          newNode.previous = oldNode;
79          newNode.next = master;
80          oldNode.next = newNode;
81          size++;
82          return newNode;
83      }
84  
85      public Node find(final String name) {
86          Args.notBlank(name, "Name");
87          return doFind(name);
88      }
89  
90      private Node doFind(final String name) {
91          Node current = master.next;
92          while (current != master) {
93              if (name.equals(current.name)) {
94                  return current;
95              }
96              current = current.next;
97          }
98          return null;
99      }
100 
101     public Node addBefore(final String existing, final E value, final String name) {
102         Args.notBlank(name, "Name");
103         Args.notNull(value, "Value");
104         final Node current = doFind(existing);
105         if (current == null) {
106             return null;
107         }
108         final Node newNode = new Node(name, value);
109         final Node previousNode = current.previous;
110         previousNode.next = newNode;
111         newNode.previous = previousNode;
112         newNode.next = current;
113         current.previous = newNode;
114         size++;
115         return newNode;
116     }
117 
118     public Node addAfter(final String existing, final E value, final String name) {
119         Args.notBlank(name, "Name");
120         Args.notNull(value, "Value");
121         final Node current = doFind(existing);
122         if (current == null) {
123             return null;
124         }
125         final Node newNode = new Node(name, value);
126         final Node nextNode = current.next;
127         current.next = newNode;
128         newNode.previous = current;
129         newNode.next = nextNode;
130         nextNode.previous = newNode;
131         size++;
132         return newNode;
133     }
134 
135     public boolean remove(final String name) {
136         final Node node = doFind(name);
137         if (node == null) {
138             return false;
139         }
140         node.previous.next = node.next;
141         node.next.previous = node.previous;
142         node.previous = null;
143         node.next = null;
144         size--;
145         return true;
146     }
147 
148     public boolean replace(final String existing, final E value) {
149         final Node node = doFind(existing);
150         if (node == null) {
151             return false;
152         }
153         node.value = value;
154         return true;
155     }
156 
157     public int getSize() {
158         return size;
159     }
160 
161     public class Node {
162 
163         private final String name;
164         private E value;
165         private Node previous;
166         private Node next;
167 
168         Node(final String name, final E value) {
169             this.name = name;
170             this.value = value;
171         }
172 
173         public String getName() {
174             return name;
175         }
176 
177         public E getValue() {
178             return value;
179         }
180 
181         public Node getPrevious() {
182             return previous != master ? previous : null;
183         }
184 
185         public Node getNext() {
186             return next != master ? next: null;
187         }
188 
189         @Override
190         public String toString() {
191             return name + ": " + value;
192         }
193 
194     }
195 
196 }