001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.utils; 022 023import java.io.Serializable; 024import java.util.AbstractList; 025import java.util.AbstractMap; 026import java.util.AbstractSet; 027import java.util.ArrayList; 028import java.util.Arrays; 029import java.util.Collections; 030import java.util.Iterator; 031import java.util.List; 032import java.util.Map; 033import java.util.Set; 034 035/** 036 * @author Matthew Pocock 037 * @author Thomas Down 038 * @author Mark Schreiber 039 */ 040public class ListTools implements Serializable{ 041 public static Iterator nonRemoveIterator(Iterator i) { 042 final Iterator it = i; 043 return new Iterator() { 044 public boolean hasNext() { 045 return it.hasNext(); 046 } 047 public Object next() { 048 return it.next(); 049 } 050 public void remove() { 051 throw new UnsupportedOperationException(); 052 } 053 }; 054 } 055 056 public static List createList(List l) { 057 switch (l.size()) { 058 case 0: 059 return Collections.EMPTY_LIST; 060 case 1: 061 return Collections.nCopies(1, l.get(0)); 062 case 2: 063 Doublet d = new Doublet(l.get(0), l.get(1)); 064 return d; 065 case 3: 066 Triplet t = new Triplet(l.get(0), l.get(1), l.get(2)); 067 return t; 068 default: 069 return new ArrayList(l); 070 } 071 } 072 073 public static List createList(Object[] a) { 074 switch (a.length) { 075 case 0: 076 return Collections.EMPTY_LIST; 077 case 1: 078 return Collections.nCopies(1, a[0]); 079 case 2: 080 Doublet d = new Doublet(a[0],a[1]); 081 return d; 082 case 3: 083 Triplet t = new Triplet(a[0],a[1],a[2]); 084 return t; 085 default: 086 return Arrays.asList(a); 087 } 088 } 089 090 /** 091 * Create a new SeriesList with the given leader, trailer and size. 092 * 093 * @param leader the String that will prefix the index 094 * @param trailer the String that will suffix the index 095 * @param size the length of the list 096 * @throws NullPointerException if leader or trailer are null (use the empty 097 * string instead) 098 * @throws IllegalArgumentException if the size is negative 099 */ 100 public static SeriesList createSeriesList( 101 String leader, 102 String trailer, 103 int size 104 ) { 105 return new SeriesList(leader, trailer, size); 106 } 107 108 public static class Doublet extends AbstractList implements Serializable { 109 private Object a; 110 private Object b; 111 112 public Doublet() {} 113 public Doublet(Object a, Object b) { 114 this(); 115 set(a, b); 116 } 117 118 public void set(Object a, Object b) { 119 this.a = a; 120 this.b = b; 121 } 122 123 public void setA(Object a) { 124 this.a = a; 125 } 126 127 public void setB(Object b) { 128 this.b = b; 129 } 130 131 public Object getA() { 132 return a; 133 } 134 135 public Object getB() { 136 return b; 137 } 138 139 public int size() { 140 return 2; 141 } 142 143 public Object get(int indx) { 144 switch (indx) { 145 case 0: 146 return a; 147 case 1: 148 return b; 149 default: 150 throw new IndexOutOfBoundsException("indx must be 0 or 1"); 151 } 152 } 153 154 public Iterator getIterator() { 155 return new Iterator() { 156 private int indx = 0; 157 158 public boolean hasNext() { 159 return indx < 2; 160 } 161 162 public Object next() { 163 return get(indx++); 164 } 165 166 public void remove() 167 throws UnsupportedOperationException { 168 throw new UnsupportedOperationException(); 169 } 170 }; 171 } 172 173 public int hashCode() { 174 int hashcode = 1; 175 hashcode = 31*hashcode + a.hashCode(); 176 hashcode = 31*hashcode + b.hashCode(); 177 return hashcode; 178 } 179 180 public boolean equals(Object o) { 181 if(! (o instanceof List) ) { 182 return false; 183 } 184 185 List other = (List) o; 186 if(other.size() != 2) { 187 return false; 188 } 189 190 return other.get(0).equals(a) && other.get(1).equals(b); 191 } 192 } 193 194 public static class Triplet extends AbstractList implements Serializable { 195 private Object a; 196 private Object b; 197 private Object c; 198 199 public Triplet() {} 200 public Triplet(Object a, Object b, Object c) { 201 this(); 202 set(a, b, c); 203 } 204 205 public void set(Object a, Object b, Object c) { 206 this.a = a; 207 this.b = b; 208 this.c = c; 209 } 210 211 public void setA(Object a) { 212 this.a = a; 213 } 214 215 public void setB(Object b) { 216 this.b = b; 217 } 218 219 public void setC(Object c) { 220 this.c = c; 221 } 222 223 public Object getA() { 224 return a; 225 } 226 227 public Object getB() { 228 return b; 229 } 230 231 public Object getC() { 232 return c; 233 } 234 235 public int size() { 236 return 3; 237 } 238 239 public Object get(int indx) { 240 switch (indx) { 241 case 0: 242 return a; 243 case 1: 244 return b; 245 case 2: 246 return c; 247 default: 248 throw new IndexOutOfBoundsException("indx must be 0 or 1"); 249 } 250 } 251 252 public Iterator getIterator() { 253 return new Iterator() { 254 private int indx = 0; 255 256 public boolean hasNext() { 257 return indx < 3; 258 } 259 260 public Object next() { 261 return get(indx++); 262 } 263 264 public void remove() 265 throws UnsupportedOperationException { 266 throw new UnsupportedOperationException(); 267 } 268 }; 269 } 270 271 public int hashCode() { 272 int hashcode = 1; 273 hashcode = 31*hashcode + a.hashCode(); 274 hashcode = 31*hashcode + b.hashCode(); 275 hashcode = 31*hashcode + c.hashCode(); 276 return hashcode; 277 } 278 279 public boolean equals(Object o) { 280 if(! (o instanceof List) ) { 281 return false; 282 } 283 284 List other = (List) o; 285 if(other.size() != 3) { 286 return false; 287 } 288 289 return other.get(0).equals(a) && other.get(1).equals(b) && other.get(2).equals(c); 290 } 291 } 292 293 /** 294 * A list that represents a series of values. 295 * 296 * <p>This provides a simple list implementation that synthesises elements from 297 * a leading and trailing string and the index into the list.</p> 298 * 299 * <p>For example, a SeriesList with leader "" and trailer ":" will contain 300 * values like "0:", "1:", "2:" and so on. A SeriesList with leader "Chapter " 301 * and trailer "" will have values like "Chapter 5".</p> 302 * 303 * @author Matthew Pocock 304 * @since 1.4 305 */ 306 public static class SeriesList 307 extends AbstractList { 308 private final String leader; 309 private final String trailer; 310 private final int size; 311 312 private SeriesList(String leader, String trailer, int size) { 313 if(leader == null) { 314 throw new NullPointerException( 315 "Leader was null. Use the empty string instead"); 316 } 317 318 if(trailer == null) { 319 throw new NullPointerException( 320 "Trailer was null. Use the empty string instead"); 321 } 322 323 if(size < 0) { 324 throw new IllegalArgumentException( 325 "Size must be zero or positive: " + size ); 326 } 327 328 this.leader = leader; 329 this.trailer = trailer; 330 this.size = size; 331 } 332 333 public String getLeader() { 334 return leader; 335 } 336 337 public String getTrailer() { 338 return trailer; 339 } 340 341 public int size() { 342 return size; 343 } 344 345 public Object get(int indx) { 346 return leader + indx + trailer; 347 } 348 } 349 350 public static List mapList(final List list, 351 final Mapper mapper) 352 { 353 return new AbstractList() { 354 public Object get(int index) 355 { 356 return mapper.map(list.get(index)); 357 } 358 359 public int size() 360 { 361 return list.size(); 362 } 363 }; 364 } 365 366 public static Set mapSet(final Set set, 367 final Mapper mapper) 368 { 369 return new AbstractSet() { 370 public Iterator iterator() 371 { 372 return new Iterator() { 373 Iterator i = set.iterator(); 374 public boolean hasNext() 375 { 376 return i.hasNext(); 377 } 378 379 public Object next() 380 { 381 return mapper.map(i.next()); 382 } 383 384 public void remove() 385 { 386 i.remove(); 387 } 388 }; 389 } 390 391 public int size() 392 { 393 return set.size(); 394 } 395 }; 396 } 397 398 public static Map mapMap(final Map map, 399 final Mapper keyMapper, 400 final Mapper valMapper) 401 { 402 return new AbstractMap() { 403 public Set entrySet() 404 { 405 return mapSet(map.entrySet(), new Mapper() { 406 public Object map(Object val) 407 { 408 final Map.Entry ent = (Map.Entry) val; 409 return new Map.Entry() { 410 public Object getKey() 411 { 412 return keyMapper.map(ent.getKey()); 413 } 414 415 public Object getValue() 416 { 417 return valMapper.map(ent.getValue()); 418 } 419 420 public Object setValue(Object value) 421 { 422 throw new UnsupportedOperationException(); 423 } 424 }; 425 } 426 }); 427 } 428 }; 429 } 430 431 /** 432 * Maps one object to another. 433 * 434 * @author Matthew Pocock 435 * @since 1.4 436 */ 437 public interface Mapper { 438 /** 439 * Map the object. 440 * 441 * @param val the object to map 442 * @return the new value 443 */ 444 public Object map(Object val); 445 } 446 447 public static final Mapper NULL_MAPPER = new Mapper() { 448 public Object map(Object val) 449 { 450 return val; 451 } 452 }; 453}