1 //----------------------------------------------------------------------
2 //
3 // PerfectJPattern: "Design patterns are good but components are better!"
4 // List2QueueAdapter.java Copyright (c) 2009 Giovanni Azua Garcia
5 // bravegag@hotmail.com
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 3
10 // of the License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, see <http://www.gnu.org/licenses/>.
19 //
20 //----------------------------------------------------------------------
21 package org.perfectjpattern.core.structural.adapter;
22
23 import java.util.*;
24
25 import org.perfectjpattern.core.api.structural.adapter.*;
26
27 /**
28 * Adapter that provides a {@link Queue} based on a {@link List} implementation.
29 * That is, it adapts the {@link List} to behave and look like a {@link Queue}.
30 * Please note that this is not an exhaustive implementation of {@link Queue}
31 * nor it replaces the proper JDK {@link Queue} implementations. The purpose
32 * of this Adapter is only to demonstrate:
33 * <ul>
34 * <li>How to use PerfectJPattern's {@link Adapter} implementation to adapt an
35 * implementation to a given target interface</li>
36 * <li>How the componentized Adapter facilitates adapting types by means of:
37 * <ul>
38 * <li>Automatically delegating to the adapter implementation calls made to
39 * the target interface in this case e.g. {@link #remove()}, {@link #poll()}
40 * {@link #element()} {@link #peek()}</li>
41 * <li>Otherwise automatically delegating to the Adaptee implementation using
42 * a specified {@link IAdaptingStrategy} in this case
43 * {@link NameMatchAdaptingStrategy} where it maps e.g. {@link Queue#
44 * offer(Object)} to {@link ArrayList#add(Object)}</li>
45 * </ul>
46 * </li>
47 * </ul>
48 * Noteworthy is how this implementation did NOT have to provide a full blown
49 * implementation of all of the Target {@link Queue} interface methods e.g.
50 * {@link Collection#addAll(Collection)} or {@link Collection#toArray()} as
51 * the call forwarding is automatically handled by PerfectJPattern's
52 * {@link Adapter}
53 * <br/><br/>
54 *
55 * @param <E> Type of the {@link Queue} elements
56 *
57 * @author <a href="mailto:bravegag@hotmail.com">Giovanni Azua</a>
58 * @version $Revision: 1.0 $Date: Feb 5, 2009 8:55:42 PM $
59 */
60 public
61 class List2QueueAdapter<E>
62 extends Adapter<Queue<E>, List<E>>
63 {
64 //------------------------------------------------------------------------
65 // public
66 //------------------------------------------------------------------------
67 /**
68 * Constructs a {@link List2QueueAdapter} from the underlying Adaptee
69 * {@link List} implementation.
70 *
71 * @param anAdaptee The Adaptee {@link List} implementation to adapt
72 * @throws IllegalArgumentException 'anAdaptee' must not be null
73 */
74 @SuppressWarnings("unchecked")
75 public
76 List2QueueAdapter(List<E> anAdaptee)
77 throws IllegalArgumentException
78 {
79 super((Class<Queue<E>>) ((Class<?>) Queue.class), anAdaptee,
80 new NameMatchAdaptingStrategy(METHODS_MAPPING));
81 }
82
83 //------------------------------------------------------------------------
84 /**
85 * Retrieves and removes the head of this queue. This method differs
86 * from {@link #poll poll} only in that it throws an exception if this
87 * queue is empty.
88 *
89 * @return the head of this queue
90 * @throws NoSuchElementException if this queue is empty
91 */
92 public E
93 remove()
94 throws NoSuchElementException
95 {
96 List<E> myList = getUnderlying();
97
98 if (myList.isEmpty())
99 {
100 throw new NoSuchElementException("The Queue is empty");
101 }
102
103 E myElement = myList.get(0);
104 myList.remove(0);
105
106 return myElement;
107 }
108
109 //------------------------------------------------------------------------
110 /**
111 * Retrieves and removes the head of this queue,
112 * or returns <tt>null</tt> if this queue is empty.
113 *
114 * @return the head of this queue, or <tt>null</tt> if this queue is empty
115 */
116 public E
117 poll()
118 {
119 E myElement = null;
120 try
121 {
122 myElement = remove();
123 }
124 catch (NoSuchElementException anException)
125 {
126 // nothing to do
127 }
128
129 return myElement;
130 }
131
132 //------------------------------------------------------------------------
133 /**
134 * Retrieves, but does not remove, the head of this queue. This method
135 * differs from {@link #peek peek} only in that it throws an exception
136 * if this queue is empty.
137 *
138 * @return the head of this queue
139 * @throws NoSuchElementException if this queue is empty
140 */
141 public E
142 element()
143 {
144 List<E> myList = getUnderlying();
145
146 if (myList.isEmpty())
147 {
148 throw new NoSuchElementException("The Queue is empty");
149 }
150
151 E myElement = myList.get(0);
152
153 return myElement;
154 }
155
156 //------------------------------------------------------------------------
157 /**
158 * Retrieves, but does not remove, the head of this queue,
159 * or returns <tt>null</tt> if this queue is empty.
160 *
161 * @return the head of this queue, or <tt>null</tt> if this queue is empty
162 */
163 public E
164 peek()
165 {
166 E myElement = null;
167 try
168 {
169 myElement = element();
170 }
171 catch (NoSuchElementException anException)
172 {
173 // nothing to do
174 }
175
176 return myElement;
177 }
178
179 //------------------------------------------------------------------------
180 // members
181 //------------------------------------------------------------------------
182 private static final Map<String, String> METHODS_MAPPING =
183 new HashMap<String, String>();
184 static
185 {
186 METHODS_MAPPING.put("add", "add");
187 METHODS_MAPPING.put("offer", "add");
188 }
189 }