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