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