001 // Copyright 2010, 2011 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry5.func; 016 017 import java.util.Collection; 018 import java.util.Comparator; 019 import java.util.Iterator; 020 import java.util.Map; 021 import java.util.Map.Entry; 022 023 /** 024 * Functional operations on collections with generics support. The core interface is {@link Flow} to 025 * which operations 026 * and transformations 027 * (in terms of {@link Predicate}s, {@link Mapper}s and {@link Reducer}s) to create new Flows. Flows 028 * are initially 029 * created 030 * using {@link #flow(Collection)} and {@link #flow(Object...)}. 031 * <p/> 032 * F will be used a bit, thus it has a short name (for those who don't like static imports). It provides a base set of 033 * Predicate, Mapper and Reducer factories. A good development pattern for applications is to provide a similar, 034 * application-specific, set of such factories. 035 * 036 * @since 5.2.0 037 */ 038 @SuppressWarnings("all") 039 public class F 040 { 041 final static Flow<?> EMPTY_FLOW = new EmptyFlow(); 042 043 @SuppressWarnings("unchecked") 044 static <T> Flow<T> emptyFlow() 045 { 046 return (Flow<T>) EMPTY_FLOW; 047 } 048 049 /** 050 * A Predicate factory for equality of an element from a flow against a specified 051 * value. 052 */ 053 public static <T> Predicate<T> eql(final T value) 054 { 055 return new Predicate<T>() 056 { 057 public boolean accept(T element) 058 { 059 return element.equals(value); 060 } 061 }; 062 } 063 064 /** 065 * A Predicate factory for comparison of a Comparable element from a flow against a fixed value. 066 */ 067 public static <T extends Comparable<T>> Predicate<T> eq(final T value) 068 { 069 return new Predicate<T>() 070 { 071 public boolean accept(T element) 072 { 073 return element.compareTo(value) == 0; 074 } 075 }; 076 } 077 078 /** 079 * A Predicate factory for comparison of a Comparable element against a fixed value. 080 */ 081 public static <T extends Comparable<T>> Predicate<T> neq(final T value) 082 { 083 return new Predicate<T>() 084 { 085 public boolean accept(T object) 086 { 087 return object.compareTo(value) != 0; 088 } 089 }; 090 } 091 092 /** 093 * A Predicate factory for comparison of a Comparable against a fixed value; true 094 * if the flow element is greater than the provided value. 095 */ 096 public static <T extends Comparable<T>> Predicate<T> gt(final T value) 097 { 098 return new Predicate<T>() 099 { 100 public boolean accept(T element) 101 { 102 return element.compareTo(value) > 0; 103 } 104 }; 105 } 106 107 /** 108 * A Predicate factory for comparison of a Comparable against a fixed value; true 109 * if the flow element is greater than or equal to the value. 110 */ 111 public static <T extends Comparable<T>> Predicate<T> gteq(final T value) 112 { 113 return new Predicate<T>() 114 { 115 public boolean accept(T element) 116 { 117 return element.compareTo(value) >= 0; 118 } 119 }; 120 } 121 122 /** 123 * A Predicate factory for comparison of a Comparable against a fixed value; true 124 * if the element is less than the value. 125 */ 126 public static <T extends Comparable<T>> Predicate<T> lt(T value) 127 { 128 return not(gteq(value)); 129 } 130 131 /** 132 * A Predicate factory for comparison of a Comprable element against a fixed value; true 133 * if the element is less than or equal to the value. 134 */ 135 public static <T extends Comparable<T>> Predicate<T> lteq(T value) 136 { 137 return not(gt(value)); 138 } 139 140 /** 141 * A Predicate factory; returns true if the value from the Flow is null. 142 */ 143 public static <T> Predicate<T> isNull() 144 { 145 return new Predicate<T>() 146 { 147 public boolean accept(T element) 148 { 149 return element == null; 150 } 151 }; 152 } 153 154 /** 155 * A Predicate factory; returns true if the value from the Flow is not null. 156 */ 157 public static <T> Predicate<T> notNull() 158 { 159 return not(isNull()); 160 } 161 162 /** 163 * A Mapper factory that gets the string value of the flow value using {@link String#valueOf(Object)}. 164 */ 165 public static <T> Mapper<T, String> stringValueOf() 166 { 167 return new Mapper<T, String>() 168 { 169 public String map(T value) 170 { 171 return String.valueOf(value); 172 } 173 }; 174 } 175 176 /** 177 * A Mapper factory; the returned Mapper ignores its input value and always returns a 178 * predetermined result. 179 */ 180 public static <S, T> Mapper<S, T> always(final T fixedResult) 181 { 182 return new Mapper<S, T>() 183 { 184 public T map(S input) 185 { 186 return fixedResult; 187 } 188 }; 189 } 190 191 /** 192 * A Mapper factory that combines a Predicate with two {@link Mapper}s; evaluating the predicate 193 * selects one of the two mappers. 194 * 195 * @param predicate evaluated to selected a coercion 196 * @param ifAccepted used when predicate evaluates to true 197 * @param ifRejected used when predicate evaluates to false 198 */ 199 public static <S, T> Mapper<S, T> select(final Predicate<? super S> predicate, final Mapper<S, T> ifAccepted, 200 final Mapper<S, T> ifRejected) 201 { 202 assert predicate != null; 203 assert ifAccepted != null; 204 assert ifRejected != null; 205 206 return new Mapper<S, T>() 207 { 208 public T map(S input) 209 { 210 Mapper<S, T> active = predicate.accept(input) ? ifAccepted : ifRejected; 211 212 return active.map(input); 213 } 214 }; 215 } 216 217 /** 218 * Override of {@link #select(Predicate, Mapper, Mapper)} where rejected values are replaced 219 * with null. 220 */ 221 public static <S, T> Mapper<S, T> select(Predicate<? super S> predicate, Mapper<S, T> ifAccepted) 222 { 223 return select(predicate, ifAccepted, (T) null); 224 } 225 226 /** 227 * Override of {@link #select(Predicate, Mapper)} where rejected values are replaced with a 228 * fixed value. 229 */ 230 public static <S, T> Mapper<S, T> select(Predicate<? super S> predicate, Mapper<S, T> ifAccepted, T ifRejectedValue) 231 { 232 Mapper<S, T> rejectedMapper = always(ifRejectedValue); 233 234 return select(predicate, ifAccepted, rejectedMapper); 235 } 236 237 /** 238 * A Mapper factory; the Mapper returns the the flow value unchanged. 239 */ 240 public static <S> Mapper<S, S> identity() 241 { 242 return new Mapper<S, S>() 243 { 244 public S map(S input) 245 { 246 return input; 247 } 248 }; 249 } 250 251 /** 252 * Allows a Mapper that maps to boolean to be used as a Predicate. 253 */ 254 public static <S> Predicate<S> toPredicate(final Mapper<S, Boolean> mapper) 255 { 256 assert mapper != null; 257 258 return new Predicate<S>() 259 { 260 public boolean accept(S object) 261 { 262 return mapper.map(object); 263 } 264 }; 265 } 266 267 /** 268 * A Reducer that operates on a Flow of Integers and is used to sum the values. 269 */ 270 public static Reducer<Integer, Integer> SUM_INTS = new Reducer<Integer, Integer>() 271 { 272 public Integer reduce(Integer accumulator, Integer value) 273 { 274 return accumulator + value; 275 } 276 }; 277 278 /** 279 * A two-input Mapper used to add the values from two Flows of Integers into a Flow of Integer 280 * sums. 281 */ 282 public static Mapper2<Integer, Integer, Integer> ADD_INTS = new Mapper2<Integer, Integer, Integer>() 283 { 284 public Integer map(Integer first, Integer second) 285 { 286 return first + second; 287 } 288 }; 289 290 /** 291 * Extracts the values from the collection to form a {@link Flow}. The Collection 292 * may change after the Flow is created without affecting the Flow. 293 */ 294 public static <T> Flow<T> flow(Collection<T> values) 295 { 296 assert values != null; 297 298 if (values.isEmpty()) 299 return emptyFlow(); 300 301 return new ArrayFlow<T>(values); 302 } 303 304 /** 305 * Creates a new Flow from the values. You should not change the values array 306 * after invoking this method (i.e., no defensive copy of the values is made). 307 */ 308 public static <T> Flow<T> flow(T... values) 309 { 310 if (values.length == 0) 311 return emptyFlow(); 312 313 return new ArrayFlow<T>(values); 314 } 315 316 /** 317 * Creates a lazy Flow from the {@link Iterator} obtained from the iterable. The Flow 318 * will be threadsafe as long as the iterable yields a new Iterator on each invocation <em>and</em> the underlying 319 * iterable object is not modified while the Flow is evaluating. 320 * In other words, not extremely threadsafe. 321 */ 322 public static <T> Flow<T> flow(Iterable<T> iterable) 323 { 324 assert iterable != null; 325 326 return flow(iterable.iterator()); 327 } 328 329 /** 330 * Creates a lazy Flow from the {@link Iterator}. The Flow will be threadsafe as long as the underlying iterable 331 * object is not modified while the Flow is evaluating. In other words, not extremely threadsafe. 332 * 333 * @since 5.3 334 */ 335 public static <T> Flow<T> flow(Iterator<T> iterator) 336 { 337 return lazy(new LazyIterator<T>(iterator)); 338 } 339 340 /** 341 * Creates a ZippedFlow from the provided map; the order of the tuples in the ZippedFlow is defined 342 * by the iteration order of the map entries. 343 * 344 * @param <A> type of key and first tuple value 345 * @param <B> type of value and second tuple value 346 * @param map source of tuples 347 * @return zipped flow created from map 348 * @since 5.3 349 */ 350 public static <A, B> ZippedFlow<A, B> zippedFlow(Map<A, B> map) 351 { 352 assert map != null; 353 354 Flow<Tuple<A, B>> tuples = F.flow(map.entrySet()).map(new Mapper<Map.Entry<A, B>, Tuple<A, B>>() 355 { 356 public Tuple<A, B> map(Entry<A, B> element) 357 { 358 return Tuple.create(element.getKey(), element.getValue()); 359 } 360 }); 361 362 return ZippedFlowImpl.create(tuples); 363 } 364 365 /** 366 * Creates a lazy Flow that returns integers in the given range. The range starts 367 * with the lower value and counts by 1 up to the upper range (which is not part of 368 * the Flow). If lower equals upper, the Flow is empty. If upper is less than lower, 369 * the Flow counts down instead. 370 * 371 * @param lower start of range (inclusive) 372 * @param upper end of range (exclusive) 373 */ 374 public static Flow<Integer> range(int lower, int upper) 375 { 376 if (lower == upper) 377 return F.emptyFlow(); 378 379 if (lower < upper) 380 return lazy(new LazyRange(lower, upper, 1)); 381 382 return lazy(new LazyRange(lower, upper, -1)); 383 } 384 385 /** 386 * Creates a {@link Flow} from a {@linkplain LazyFunction lazy function}. 387 */ 388 public static <T> Flow<T> lazy(LazyFunction<T> function) 389 { 390 assert function != null; 391 392 return new LazyFlow<T>(function); 393 } 394 395 private static <T> LazyFunction<T> toLazyFunction(final T currentValue, final Mapper<T, T> function) 396 { 397 return new LazyFunction<T>() 398 { 399 public LazyContinuation<T> next() 400 { 401 final T nextValue = function.map(currentValue); 402 403 return new LazyContinuation<T>(nextValue, toLazyFunction(nextValue, function)); 404 } 405 }; 406 } 407 408 /** 409 * Creates an infinite lazy flow from an initial value and a function to map from the current value to the 410 * next value. 411 * 412 * @param initial initial value in flow 413 * @param function maps from current value in flow to next value in flow 414 * @return lazy flow 415 */ 416 public static <T> Flow<T> iterate(final T initial, final Mapper<T, T> function) 417 { 418 LazyFunction<T> head = new LazyFunction<T>() 419 { 420 public LazyContinuation<T> next() 421 { 422 return new LazyContinuation<T>(initial, toLazyFunction(initial, function)); 423 } 424 }; 425 426 return lazy(head); 427 } 428 429 /** 430 * Creates an <em>infinite</em> series of numbers. 431 * <p/> 432 * Attempting to get the {@linkplain Flow#count()} of the series will form an infinite loop. 433 */ 434 public static Flow<Integer> series(int start, final int delta) 435 { 436 return iterate(start, new Mapper<Integer, Integer>() 437 { 438 public Integer map(Integer element) 439 { 440 return element + delta; 441 } 442 }); 443 } 444 445 /** 446 * A Worker factory; the returnedWorker adds the values to a provided collection. 447 */ 448 public static <T> Worker<T> addToCollection(final Collection<T> coll) 449 { 450 return new Worker<T>() 451 { 452 public void work(T value) 453 { 454 coll.add(value); 455 } 456 }; 457 } 458 459 /** 460 * A Predicate factory for matching String elements with a given prefix. 461 * 462 * @since 5.3 463 */ 464 public static Predicate<String> startsWith(String prefix) 465 { 466 return startsWith(prefix, false); 467 } 468 469 /** 470 * As {@link #startsWith(String)}, but ignores case. 471 * 472 * @since 5.3 473 */ 474 public static Predicate<String> startsWithIgnoringCase(String prefix) 475 { 476 return startsWith(prefix, true); 477 } 478 479 /** 480 * @since 5.3 481 */ 482 private static Predicate<String> startsWith(final String prefix, final boolean ignoreCase) 483 { 484 return new Predicate<String>() 485 { 486 public boolean accept(String element) 487 { 488 return element.regionMatches(ignoreCase, 0, prefix, 0, prefix.length()); 489 } 490 }; 491 } 492 493 /** 494 * A Predicate factory for matching String elements with a given suffix. 495 * 496 * @since 5.3 497 */ 498 public static Predicate<String> endsWith(String suffix) 499 { 500 return endsWith(suffix, false); 501 } 502 503 /** 504 * As with {@link #endsWith(String)} but ignores case. 505 * 506 * @since 5.3 507 */ 508 public static Predicate<String> endsWithIgnoringCase(String suffix) 509 { 510 return endsWith(suffix, true); 511 } 512 513 /** 514 * @since 5.3 515 */ 516 private static Predicate<String> endsWith(final String suffix, final boolean ignoreCase) 517 { 518 return new Predicate<String>() 519 { 520 public boolean accept(String element) 521 { 522 return element 523 .regionMatches(ignoreCase, element.length() - suffix.length(), suffix, 0, suffix.length()); 524 } 525 }; 526 } 527 528 /** 529 * Creates a Comparator for the Tuples of a {@link ZippedFlow} that sorts the Tuple elements based on the first 530 * value in the Tuple. 531 * 532 * @since 5.3 533 */ 534 public static <A extends Comparable<A>, B> Comparator<Tuple<A, B>> orderByFirst() 535 { 536 return new Comparator<Tuple<A, B>>() 537 { 538 public int compare(Tuple<A, B> o1, Tuple<A, B> o2) 539 { 540 return o1.first.compareTo(o2.first); 541 } 542 }; 543 } 544 545 /** 546 * Creates a Comparator for the Tuples of a {@link ZippedFlow} that sorts the Tuple elements based on the first 547 * value in the Tuple. 548 * 549 * @since 5.3 550 */ 551 public static <A, B extends Comparable<B>> Comparator<Tuple<A, B>> orderBySecond() 552 { 553 return new Comparator<Tuple<A, B>>() 554 { 555 public int compare(Tuple<A, B> o1, Tuple<A, B> o2) 556 { 557 return o1.second.compareTo(o2.second); 558 } 559 }; 560 } 561 562 /** 563 * Inverts a predicate. 564 * 565 * @param delegate the predicate to invert 566 * @return a new predicate that is inverse to the existing predicate 567 * @since 5.3 568 */ 569 public static <T> Predicate<T> not(final Predicate<? super T> delegate) 570 { 571 assert delegate != null; 572 573 return new Predicate<T>() 574 { 575 public boolean accept(T element) 576 { 577 return !delegate.accept(element); 578 } 579 }; 580 } 581 582 /** 583 * Combines two mappers into a composite mapping from type A to type C via type B. 584 * 585 * @param abMapper maps from A to B 586 * @param bcMapper maps from B to C 587 * @return mapper from A to C 588 */ 589 public static <A, B, C> Mapper<A, C> combine(final Mapper<A, B> abMapper, final Mapper<B, C> bcMapper) 590 { 591 assert abMapper != null; 592 assert bcMapper != null; 593 594 return new Mapper<A, C>() 595 { 596 597 public C map(A aElement) 598 { 599 B bElement = abMapper.map(aElement); 600 601 return bcMapper.map(bElement); 602 } 603 604 }; 605 } 606 607 /** 608 * Combines any number of delegates as a logical and operation. Evaluation terminates 609 * with the first delegate predicate that returns false. 610 * 611 * @param delegates to evaluate 612 * @return combined delegate 613 * @since 5.3 614 */ 615 public static <T> Predicate<T> and(final Predicate<? super T>... delegates) 616 { 617 return new Predicate<T>() 618 { 619 public boolean accept(T element) 620 { 621 for (Predicate<? super T> delegate : delegates) 622 { 623 if (!delegate.accept(element)) 624 return false; 625 } 626 627 return true; 628 } 629 }; 630 } 631 632 /** 633 * Combines any number of delegates as a logical or operation. Evaluation terminates 634 * with the first delegate predicate that returns true. 635 * 636 * @param delegates to evaluate 637 * @return combined delegate 638 * @since 5.3 639 */ 640 public static <T> Predicate<T> or(final Predicate<? super T>... delegates) 641 { 642 return new Predicate<T>() 643 { 644 public boolean accept(T element) 645 { 646 for (Predicate<? super T> delegate : delegates) 647 { 648 if (delegate.accept(element)) 649 return true; 650 } 651 652 return false; 653 } 654 }; 655 } 656 657 /** 658 * Combines several compatible workers together into a composite. 659 * 660 * @since 5.3 661 */ 662 public static <T> Worker<T> combine(final Worker<? super T>... delegates) 663 { 664 assert delegates.length > 0; 665 666 return new Worker<T>() 667 { 668 public void work(T value) 669 { 670 for (Worker<? super T> delegate : delegates) 671 { 672 delegate.work(value); 673 } 674 } 675 }; 676 } 677 }