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 }