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